Compare commits

..

16 Commits

Author SHA1 Message Date
ac68251a00 Bump version to 3.10.2
Update NEWS.
2013-11-14 12:32:23 +00:00
6fd705e009 Updated Tamil Translations 2013-11-11 15:02:33 +05:30
923a908a2a Update Chinese simplified translation 2013-11-10 11:40:37 +08:00
59e868b8f5 popupMenu: Fix removing the active menu from PopupMenuManager
Commit b42af9aa99 changed the parameter list of _closeMenu()
to account for changes in the GrabHelper ungrab mechanism, but
didn't update other callers.

https://bugzilla.gnome.org/show_bug.cgi?id=709806
2013-11-07 00:12:37 +01:00
f83144b79a screencast: Validate parameters of ScreencastArea
... just as we do for screenshots.

https://bugzilla.gnome.org/show_bug.cgi?id=699752
2013-11-04 16:59:46 +01:00
267a42c31c screencast: Fix disabling screencasts via session mode
If screencasts are disabled, we return a DBus error, but still start
the recording happily - add early returns in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=699752
2013-11-04 16:59:46 +01:00
3ac7bf874c screenshot: Extend ScreenshotArea parameter validation
We currently only ensure that width and height are positive, so it
is still possible to pass in values that don't make any sense at all
(which may even result in a crash when exceeding limits imposed by
X11).
There is nothing to screenshot outside the actual screen area, so
restrict the parameters to that.

https://bugzilla.gnome.org/show_bug.cgi?id=699752
2013-11-04 16:59:46 +01:00
cac32dfe2a Updated Russian translation 2013-11-01 23:31:14 +04:00
1a61f288f6 system: Restore support for 'disable-restart-buttons'
The org.gnome.login-screen schema contains a key to disable the
power/restart buttons; our support for this fell victim to the
new combined status menu, add it back.

https://bugzilla.gnome.org/show_bug.cgi?id=711244
2013-11-01 13:09:21 +01:00
aca619ff89 Updated Brazilian Portuguese translation
Fixes "Off" translation
2013-10-27 15:45:09 -02:00
6673f52df2 Updated Norwegian bokmål translation 2013-10-26 15:17:08 +02:00
a70ee216b0 theme: Add some vertical padding on login screen
This was apparently lost during some rewrite this cycle ...

https://bugzilla.gnome.org/show_bug.cgi?id=710555
2013-10-25 14:16:18 +01:00
261514187e Updated Greek translation 2013-10-24 09:37:12 +03:00
1bf6fa039f Updated Norwegian bokmål translation 2013-10-20 13:07:54 +02:00
9360e60ed2 Updated Russian translation 2013-10-18 18:36:10 +04:00
afb6286994 Updated Belarusian translation. 2013-10-15 23:45:34 +03:00
91 changed files with 5199 additions and 4739 deletions

2
.gitignore vendored
View File

@ -43,8 +43,6 @@ docs/reference/*/xml/
docs/reference/shell/doc-gen-*
gtk-doc.make
js/misc/config.js
js/js-resources.c
js/js-resources.h
intltool-extract.in
intltool-merge.in
intltool-update.in

View File

@ -1,11 +1,7 @@
# Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src tests po docs
if BUILD_BROWSER_PLUGIN
SUBDIRS += browser-plugin
endif
SUBDIRS = data js src browser-plugin tests po docs
if ENABLE_MAN
SUBDIRS += man

40
NEWS
View File

@ -1,41 +1,17 @@
3.11.2
3.10.2
======
* Cache search result display actors [Jasper; #704912]
* Use username in userWidget if real name doesn't fit [Jasper; #706851]
* Support shell_global_reexec_self() on OpenBSD [Antoine; #709571]
* Support disabling browser plugin [Colin; #711218]
* Restore support for 'disable-restart-buttons' [Florian; #711244]
* Validate parameters of exposed DBus methods [Florian; #699752]
* Connect applications to systemd journal if available [Colin; #711626]
* Misc bug fixes and cleanups [Florian, Jasper; #711205, #698486, #711416,
#644306, #711555, #709806, #711631, #711732]
Contributors:
Cosimo Cecchi, Antoine Jacoutot, Florian Müllner, Jasper St. Pierre,
Rico Tzschichholz, Colin Walters
Translations:
Yuri Myasoedov [ru], Kjartan Maraas [nb], Efstathios Iosifidis [el],
Benjamin Steinwender [de], eternalhui [zh_CN], Shantha kumar [ta]
3.11.1
======
* power: Use UPower directly instead of gnome-settings-daemon [Bastien; #710273]
* Implement support for new GTK+ notification API [Jasper, Giovanni, Florian;
#710137, #710596]
* gdm: Don't allow user-list to fill up the entire screen [Florian; #710555]
* Don't autostart remote search providers at login [Giovanni; #708830]
* Fix spacing in end-session dialog [Sebastien; #710543]
* Prepare for js24 [Tim; #711052]
* Misc bug fixes and cleanups [Jasper, Florian, Adel, Tim, Sebastien; #710347,
#710144, #710541, #691409, #710745, #688331, #704912]
* Restore support for 'disable-restart-buttons' [Florian; #711244]
* alidate parameters of exposed DBus methods [Florian; #699752]
* Misc. bug fixes [Florian; #709806]
Contributors:
Giovanni Campagna, Adel Gadllah, Sebastien Lafargue, Tim Lunn,
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
Florian Müllner
Translations:
Stas Solovey [ru], Yosef Or Boczko [he], Rafael Ferreira [pt_BR]
Ihar Hrachyshka [be], Stas Solovey [ru], Kjartan Maraas [nb],
Dimitris Spingos [el], Rafael Ferreira [pt_BR], Yuri Myasoedov [ru],
Sphinx Jiang [zh_CN], Shantha kumar [ta]
3.10.1
======

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.11.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.10.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -16,7 +16,6 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
# Initialize libtool
LT_PREREQ([2.2.6])
@ -58,25 +57,10 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
AC_ARG_ENABLE([systemd],
AS_HELP_STRING([--enable-systemd], [Use systemd]),
[enable_systemd=$enableval],
[enable_systemd=auto])
AS_IF([test x$enable_systemd != xno], [
AC_MSG_CHECKING([for libsystemd-journal])
PKG_CHECK_EXISTS([libsystemd-journal],
[have_systemd=yes
AC_DEFINE([HAVE_SYSTEMD], [1], [Define if we have systemd])],
[have_systemd=no])
AC_MSG_RESULT($have_systemd)
])
AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.13.4
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.38.1
MUTTER_MIN_VERSION=3.11.1
MUTTER_MIN_VERSION=3.10.2
GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3
@ -86,6 +70,7 @@ POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11
GCR_MIN_VERSION=3.7.5
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
GNOME_MENUS_REQUIRED_VERSION=3.5.3
NETWORKMANAGER_MIN_VERSION=0.9.8
PULSE_MIN_VERS=2.0
@ -95,6 +80,7 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
gtk+-3.0 >= $GTK_MIN_VERSION
atk-bridge-2.0
gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
$recorder_modules
gdk-x11-3.0 libsoup-2.4
xtst
@ -108,9 +94,6 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION"
if test x$have_systemd = xyes; then
SHARED_PCS="${SHARED_PCS} libsystemd-journal"
fi
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION)
@ -126,20 +109,12 @@ PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8)
AC_ARG_ENABLE(browser-plugin,
[AS_HELP_STRING([--enable-browser-plugin],
[Enable browser plugin [default=yes]])],,
enable_browser_plugin=yes)
AS_IF([test x$enable_browser_plugin = xyes], [
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
])
AM_CONDITIONAL(BUILD_BROWSER_PLUGIN, test x$enable_browser_plugin = xyes)
AC_MSG_CHECKING([for bluetooth support])
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.9.0],
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
@ -172,9 +147,6 @@ AC_SUBST(MUTTER_TYPELIB_DIR)
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
AC_SUBST(GJS_CONSOLE)
GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
AC_SUBST(GLIB_COMPILE_RESOURCES)
AC_CHECK_FUNCS(fdwalk)
AC_CHECK_FUNCS(mallinfo)
AC_CHECK_HEADERS([sys/resource.h])

View File

@ -1,3 +1,6 @@
wandadir = $(pkgdatadir)
dist_wanda_DATA = wanda.png
desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
if HAVE_MUTTER_WAYLAND

View File

@ -306,13 +306,16 @@ StScrollBar StButton#vhandle:active {
font-size: 12pt;
border-bottom: 1px solid #666;
padding: 12px;
spacing: 20px;
}
.nm-dialog-item:selected {
.nm-dialog-item:checked {
background-color: #333;
}
.nm-dialog-item-box {
spacing: 20px;
}
.nm-dialog-icons {
spacing: .5em;
}
@ -1967,11 +1970,6 @@ StScrollBar StButton#vhandle:active {
padding-left: 50px;
}
.end-session-dialog-session-list,
.end-session-dialog-app-list {
spacing: 1em;
}
.end-session-dialog-list-header {
font-weight: bold;
}

BIN
data/wanda.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,5 +1,7 @@
NULL =
BUILT_SOURCES =
EXTRA_DIST = misc/config.js.in
CLEANFILES = misc/config.js
misc/config.js: misc/config.js.in Makefile
[ -d $(@D) ] || $(mkdir_p) $(@D) ; \
@ -12,26 +14,112 @@ misc/config.js: misc/config.js.in Makefile
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \
$< > $@
js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/js-resources.gresource.xml)
js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
jsdir = $(pkgdatadir)/js
js_built_sources = js-resources.c js-resources.h
BUILT_SOURCES += $(js_built_sources)
all-local: $(js_built_sources)
js_resource_dist_files = $(filter-out misc/config.js, $(js_resource_files))
EXTRA_DIST = \
$(js_resource_dist_files) \
js-resources.gresource.xml \
misc/config.js.in \
$(NULL)
CLEANFILES = \
$(js_built_sources) \
nobase_dist_js_DATA = \
gdm/authPrompt.js \
gdm/batch.js \
gdm/fingerprint.js \
gdm/loginDialog.js \
gdm/oVirt.js \
gdm/realmd.js \
gdm/util.js \
extensionPrefs/main.js \
misc/config.js \
misc/extensionUtils.js \
misc/fileUtils.js \
misc/gnomeSession.js \
misc/hash.js \
misc/history.js \
misc/jsParse.js \
misc/loginManager.js \
misc/modemManager.js \
misc/objectManager.js \
misc/params.js \
misc/smartcardManager.js \
misc/util.js \
perf/core.js \
ui/altTab.js \
ui/animation.js \
ui/appDisplay.js \
ui/appFavorites.js \
ui/backgroundMenu.js \
ui/background.js \
ui/boxpointer.js \
ui/calendar.js \
ui/checkBox.js \
ui/ctrlAltTab.js \
ui/dash.js \
ui/dateMenu.js \
ui/dnd.js \
ui/endSessionDialog.js \
ui/extensionSystem.js \
ui/extensionDownloader.js \
ui/environment.js \
ui/focusCaretTracker.js\
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \
ui/keyboard.js \
ui/layout.js \
ui/lightbox.js \
ui/lookingGlass.js \
ui/magnifier.js \
ui/magnifierDBus.js \
ui/main.js \
ui/messageTray.js \
ui/modalDialog.js \
ui/separator.js \
ui/sessionMode.js \
ui/shellEntry.js \
ui/shellMountOperation.js \
ui/slider.js \
ui/notificationDaemon.js \
ui/osdWindow.js \
ui/overview.js \
ui/overviewControls.js \
ui/panel.js \
ui/panelMenu.js \
ui/pointerWatcher.js \
ui/popupMenu.js \
ui/remoteSearch.js \
ui/remoteMenu.js \
ui/runDialog.js \
ui/screencast.js \
ui/screenshot.js \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \
ui/searchDisplay.js \
ui/shellDBus.js \
ui/status/accessibility.js \
ui/status/brightness.js \
ui/status/keyboard.js \
ui/status/network.js \
ui/status/power.js \
ui/status/rfkill.js \
ui/status/volume.js \
ui/status/bluetooth.js \
ui/status/screencast.js \
ui/status/system.js \
ui/switcherPopup.js \
ui/tweener.js \
ui/unlockDialog.js \
ui/userWidget.js \
ui/viewSelector.js \
ui/wanda.js \
ui/windowAttentionHandler.js \
ui/windowManager.js \
ui/workspace.js \
ui/workspaceThumbnail.js \
ui/workspacesView.js \
ui/workspaceSwitcherPopup.js \
ui/xdndHandler.js \
ui/components/__init__.js \
ui/components/autorunManager.js \
ui/components/automountManager.js \
ui/components/networkAgent.js \
ui/components/polkitAgent.js \
ui/components/telepathyClient.js \
ui/components/keyring.js \
$(NULL)

View File

@ -13,15 +13,13 @@ const _ = Gettext.gettext;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
const GnomeShellIface = '<node> \
<interface name="org.gnome.Shell.Extensions"> \
<signal name="ExtensionStatusChanged"> \
<arg type="s" name="uuid"/> \
<arg type="i" name="state"/> \
<arg type="s" name="error"/> \
</signal> \
</interface> \
</node>';
const GnomeShellIface = <interface name="org.gnome.Shell.Extensions">
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
</interface>;
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@ -206,11 +204,11 @@ const Application = new Lang.Class({
_scanExtensions: function() {
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', Lang.bind(this, this._extensionFound));
finder.connect('extensions-loaded', Lang.bind(this, this._extensionsLoaded));
finder.scanExtensions();
this._extensionsLoaded();
},
_extensionFound: function(finder, extension) {
_extensionFound: function(signals, extension) {
let iter = this._model.append();
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
this._extensionIters[extension.uuid] = iter;

View File

@ -5,13 +5,11 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = '<node> \
<interface name="net.reactivated.Fprint.Manager"> \
<method name="GetDefaultDevice"> \
<arg type="o" direction="out" /> \
</method> \
</interface> \
</node>';
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
<method name='GetDefaultDevice'>
<arg type='o' direction='out' />
</method>
</interface>;
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);

View File

@ -59,7 +59,7 @@ const UserListItem = new Lang.Class({
this._userChangedId = this.user.connect('changed',
Lang.bind(this, this._onUserChanged));
let layout = new St.BoxLayout({ vertical: true });
let layout = new St.BoxLayout({ vertical: false });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
@ -68,18 +68,39 @@ const UserListItem = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._userWidget = new UserWidget.UserWidget(this.user);
layout.add(this._userWidget.actor);
this._userAvatar = new UserWidget.Avatar(this.user,
{ styleClass: 'login-dialog-user-list-item-icon' });
layout.add(this._userAvatar.actor);
let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
vertical: true });
layout.add(textLayout, { expand: true });
this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' });
this.actor.label_actor = this._nameLabel;
textLayout.add(this._nameLabel,
{ y_fill: false,
y_align: St.Align.MIDDLE,
expand: true });
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
scale_x: 0 });
layout.add(this._timedLoginIndicator);
textLayout.add(this._timedLoginIndicator,
{ x_fill: true,
x_align: St.Align.MIDDLE,
y_fill: false,
y_align: St.Align.END });
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this._onUserChanged();
},
_onUserChanged: function() {
this._nameLabel.set_text(this.user.get_real_name());
this._userAvatar.update();
this._updateLoggedIn();
},
syncStyleClasses: function() {
this._updateLoggedIn();
},
@ -168,6 +189,7 @@ const UserList = new Lang.Class({
for (let userName in this._items) {
let item = this._items[userName];
item.actor.sync_hover();
item.syncStyleClasses();
}
},

View File

@ -4,13 +4,11 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const OVirtCredentialsIface = '<node> \
<interface name="org.ovirt.vdsm.Credentials"> \
<signal name="UserAuthenticated"> \
<arg type="s" name="token"/> \
</signal> \
</interface> \
</node>';
const OVirtCredentialsIface = <interface name='org.ovirt.vdsm.Credentials'>
<signal name="UserAuthenticated">
<arg type="s" name="token"/>
</signal>
</interface>;
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);

View File

@ -5,58 +5,52 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const ProviderIface = '<node> \
<interface name="org.freedesktop.realmd.Provider"> \
<property name="Name" type="s" access="read"/> \
<property name="Version" type="s" access="read"/> \
<property name="Realms" type="ao" access="read"/> \
<method name="Discover"> \
<arg name="string" type="s" direction="in"/> \
<arg name="options" type="a{sv}" direction="in"/> \
<arg name="relevance" type="i" direction="out"/> \
<arg name="realm" type="ao" direction="out"/> \
</method> \
</interface> \
</node>';
const ProviderIface = <interface name='org.freedesktop.realmd.Provider'>
<property name="Name" type="s" access="read"/>
<property name="Version" type="s" access="read"/>
<property name="Realms" type="ao" access="read"/>
<method name="Discover">
<arg name="string" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="relevance" type="i" direction="out"/>
<arg name="realm" type="ao" direction="out"/>
</method>
</interface>;
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
const ServiceIface = '<node> \
<interface name="org.freedesktop.realmd.Service"> \
<method name="Cancel"> \
<arg name="operation" type="s" direction="in"/> \
</method> \
<method name="Release" /> \
<method name="SetLocale"> \
<arg name="locale" type="s" direction="in"/> \
</method> \
<signal name="Diagnostics"> \
<arg name="data" type="s"/> \
<arg name="operation" type="s"/> \
</signal> \
</interface> \
</node>';
const ServiceIface = <interface name="org.freedesktop.realmd.Service">
<method name="Cancel">
<arg name="operation" type="s" direction="in"/>
</method>
<method name="Release" />
<method name="SetLocale">
<arg name="locale" type="s" direction="in"/>
</method>
<signal name="Diagnostics">
<arg name="data" type="s"/>
<arg name="operation" type="s"/>
</signal>
</interface>;
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = '<node> \
<interface name="org.freedesktop.realmd.Realm"> \
<property name="Name" type="s" access="read"/> \
<property name="Configured" type="s" access="read"/> \
<property name="Details" type="a(ss)" access="read"/> \
<property name="LoginFormats" type="as" access="read"/> \
<property name="LoginPolicy" type="s" access="read"/> \
<property name="PermittedLogins" type="as" access="read"/> \
<property name="SupportedInterfaces" type="as" access="read"/> \
<method name="ChangeLoginPolicy"> \
<arg name="login_policy" type="s" direction="in"/> \
<arg name="permitted_add" type="as" direction="in"/> \
<arg name="permitted_remove" type="as" direction="in"/> \
<arg name="options" type="a{sv}" direction="in"/> \
</method> \
<method name="Deconfigure"> \
<arg name="options" type="a{sv}" direction="in"/> \
</method> \
</interface> \
</node>';
const RealmIface = <interface name="org.freedesktop.realmd.Realm">
<property name="Name" type="s" access="read"/>
<property name="Configured" type="s" access="read"/>
<property name="Details" type="a(ss)" access="read"/>
<property name="LoginFormats" type="as" access="read"/>
<property name="LoginPolicy" type="s" access="read"/>
<property name="PermittedLogins" type="as" access="read"/>
<property name="SupportedInterfaces" type="as" access="read"/>
<method name="ChangeLoginPolicy">
<arg name="login_policy" type="s" direction="in"/>
<arg name="permitted_add" type="as" direction="in"/>
<arg name="permitted_remove" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
</method>
<method name="Deconfigure">
<arg name="options" type="a{sv}" direction="in"/>
</method>
</interface>;
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
const Manager = new Lang.Class({

View File

@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>gdm/authPrompt.js</file>
<file>gdm/batch.js</file>
<file>gdm/fingerprint.js</file>
<file>gdm/loginDialog.js</file>
<file>gdm/oVirt.js</file>
<file>gdm/realmd.js</file>
<file>gdm/util.js</file>
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/gnomeSession.js</file>
<file>misc/hash.js</file>
<file>misc/history.js</file>
<file>misc/jsParse.js</file>
<file>misc/loginManager.js</file>
<file>misc/modemManager.js</file>
<file>misc/objectManager.js</file>
<file>misc/params.js</file>
<file>misc/smartcardManager.js</file>
<file>misc/util.js</file>
<file>perf/core.js</file>
<file>ui/altTab.js</file>
<file>ui/animation.js</file>
<file>ui/appDisplay.js</file>
<file>ui/appFavorites.js</file>
<file>ui/backgroundMenu.js</file>
<file>ui/background.js</file>
<file>ui/boxpointer.js</file>
<file>ui/calendar.js</file>
<file>ui/checkBox.js</file>
<file>ui/ctrlAltTab.js</file>
<file>ui/dash.js</file>
<file>ui/dateMenu.js</file>
<file>ui/dnd.js</file>
<file>ui/endSessionDialog.js</file>
<file>ui/extensionSystem.js</file>
<file>ui/extensionDownloader.js</file>
<file>ui/environment.js</file>
<file>ui/focusCaretTracker.js</file>
<file>ui/ibusCandidatePopup.js</file>
<file>ui/grabHelper.js</file>
<file>ui/iconGrid.js</file>
<file>ui/keyboard.js</file>
<file>ui/layout.js</file>
<file>ui/lightbox.js</file>
<file>ui/lookingGlass.js</file>
<file>ui/magnifier.js</file>
<file>ui/magnifierDBus.js</file>
<file>ui/main.js</file>
<file>ui/messageTray.js</file>
<file>ui/modalDialog.js</file>
<file>ui/separator.js</file>
<file>ui/sessionMode.js</file>
<file>ui/shellEntry.js</file>
<file>ui/shellMountOperation.js</file>
<file>ui/slider.js</file>
<file>ui/notificationDaemon.js</file>
<file>ui/osdWindow.js</file>
<file>ui/overview.js</file>
<file>ui/overviewControls.js</file>
<file>ui/panel.js</file>
<file>ui/panelMenu.js</file>
<file>ui/pointerWatcher.js</file>
<file>ui/popupMenu.js</file>
<file>ui/remoteSearch.js</file>
<file>ui/remoteMenu.js</file>
<file>ui/runDialog.js</file>
<file>ui/screencast.js</file>
<file>ui/screenshot.js</file>
<file>ui/screenShield.js</file>
<file>ui/scripting.js</file>
<file>ui/search.js</file>
<file>ui/shellDBus.js</file>
<file>ui/status/accessibility.js</file>
<file>ui/status/brightness.js</file>
<file>ui/status/keyboard.js</file>
<file>ui/status/network.js</file>
<file>ui/status/power.js</file>
<file>ui/status/rfkill.js</file>
<file>ui/status/volume.js</file>
<file>ui/status/bluetooth.js</file>
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
<file>ui/switcherPopup.js</file>
<file>ui/tweener.js</file>
<file>ui/unlockDialog.js</file>
<file>ui/userWidget.js</file>
<file>ui/viewSelector.js</file>
<file>ui/windowAttentionHandler.js</file>
<file>ui/windowManager.js</file>
<file>ui/workspace.js</file>
<file>ui/workspaceThumbnail.js</file>
<file>ui/workspacesView.js</file>
<file>ui/workspaceSwitcherPopup.js</file>
<file>ui/xdndHandler.js</file>
<file>ui/components/__init__.js</file>
<file>ui/components/autorunManager.js</file>
<file>ui/components/automountManager.js</file>
<file>ui/components/networkAgent.js</file>
<file>ui/components/polkitAgent.js</file>
<file>ui/components/telepathyClient.js</file>
<file>ui/components/keyring.js</file>
</gresource>
</gresources>

View File

@ -174,9 +174,17 @@ const ExtensionFinder = new Lang.Class({
this.emit('extension-found', extension);
},
_extensionsLoaded: function() {
this.emit('extensions-loaded');
},
scanExtensions: function() {
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, Lang.bind(this, this._loadExtension, perUserDir));
FileUtils.collectFromDatadirsAsync('extensions',
{ processFile: Lang.bind(this, this._loadExtension),
loadedCallback: Lang.bind(this, this._extensionsLoaded),
includeUserDir: true,
data: perUserDir });
}
});
Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@ -25,27 +25,60 @@ function listDirAsync(file, callback) {
});
}
function collectFromDatadirs(subdir, includeUserDir, processFile) {
function _collectFromDirectoryAsync(dir, loadState) {
function done() {
loadState.numLoading--;
if (loadState.loadedCallback &&
loadState.numLoading == 0)
loadState.loadedCallback(loadState.data);
}
dir.query_info_async('standard::type', Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT, null, function(object, res) {
try {
object.query_info_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
log(e.message);
done();
return;
}
listDirAsync(dir, Lang.bind(this, function(infos) {
for (let i = 0; i < infos.length; i++)
loadState.processFile(dir.get_child(infos[i].get_name()),
infos[i], loadState.data);
done();
}));
});
}
function collectFromDatadirsAsync(subdir, params) {
params = Params.parse(params, { includeUserDir: false,
processFile: null,
loadedCallback: null,
data: null });
let loadState = { data: params.data,
numLoading: 0,
loadedCallback: params.loadedCallback,
processFile: params.processFile };
if (params.processFile == null) {
if (params.loadedCallback)
params.loadedCallback(params.data);
return;
}
let dataDirs = GLib.get_system_data_dirs();
if (includeUserDir)
if (params.includeUserDir)
dataDirs.unshift(GLib.get_user_data_dir());
loadState.numLoading = dataDirs.length;
for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
let dir = Gio.File.new_for_path(path);
let fileEnum;
try {
fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
fileEnum = null;
}
if (fileEnum != null) {
let info;
while ((info = fileEnum.next_file(null)))
processFile(fileEnum.get_child(info), info);
}
_collectFromDirectoryAsync(dir, loadState);
}
}

View File

@ -4,17 +4,15 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const PresenceIface = '<node> \
<interface name="org.gnome.SessionManager.Presence"> \
<method name="SetStatus"> \
<arg type="u" direction="in"/> \
</method> \
<property name="status" type="u" access="readwrite"/> \
<signal name="StatusChanged"> \
<arg type="u" direction="out"/> \
</signal> \
</interface> \
</node>';
const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
<method name="SetStatus">
<arg type="u" direction="in"/>
</method>
<property name="status" type="u" access="readwrite"/>
<signal name="StatusChanged">
<arg type="u" direction="out"/>
</signal>
</interface>;
const PresenceStatus = {
AVAILABLE: 0,
@ -32,16 +30,14 @@ function Presence(initCallback, cancellable) {
// Note inhibitors are immutable objects, so they don't
// change at runtime (changes always come in the form
// of new inhibitors)
const InhibitorIface = '<node> \
<interface name="org.gnome.SessionManager.Inhibitor"> \
<method name="GetAppId"> \
<arg type="s" direction="out" /> \
</method> \
<method name="GetReason"> \
<arg type="s" direction="out" /> \
</method> \
</interface> \
</node>';
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
<method name="GetAppId">
<arg type="s" direction="out" />
</method>
<method name="GetReason">
<arg type="s" direction="out" />
</method>
</interface>;
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
function Inhibitor(objectPath, initCallback, cancellable) {
@ -49,29 +45,27 @@ function Inhibitor(objectPath, initCallback, cancellable) {
}
// Not the full interface, only the methods we use
const SessionManagerIface = '<node> \
<interface name="org.gnome.SessionManager"> \
<method name="Logout"> \
<arg type="u" direction="in" /> \
</method> \
<method name="Shutdown" /> \
<method name="Reboot" /> \
<method name="CanShutdown"> \
<arg type="b" direction="out" /> \
</method> \
<method name="IsInhibited"> \
<arg type="u" direction="in" /> \
<arg type="b" direction="out" /> \
</method> \
<property name="SessionIsActive" type="b" access="read"/> \
<signal name="InhibitorAdded"> \
<arg type="o" direction="out"/> \
</signal> \
<signal name="InhibitorRemoved"> \
<arg type="o" direction="out"/> \
</signal> \
</interface> \
</node>';
const SessionManagerIface = <interface name="org.gnome.SessionManager">
<method name="Logout">
<arg type="u" direction="in" />
</method>
<method name="Shutdown" />
<method name="Reboot" />
<method name="CanShutdown">
<arg type="b" direction="out" />
</method>
<method name="IsInhibited">
<arg type="u" direction="in" />
<arg type="b" direction="out" />
</method>
<property name="SessionIsActive" type="b" access="read"/>
<signal name="InhibitorAdded">
<arg type="o" direction="out"/>
</signal>
<signal name="InhibitorRemoved">
<arg type="o" direction="out"/>
</signal>
</interface>;
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
function SessionManager(initCallback, cancellable) {

View File

@ -7,66 +7,58 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const SystemdLoginManagerIface = '<node> \
<interface name="org.freedesktop.login1.Manager"> \
<method name="Suspend"> \
<arg type="b" direction="in"/> \
</method> \
<method name="CanSuspend"> \
<arg type="s" direction="out"/> \
</method> \
<method name="Inhibit"> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="h" direction="out"/> \
</method> \
<method name="GetSession"> \
<arg type="s" direction="in"/> \
<arg type="o" direction="out"/> \
</method> \
<method name="ListSessions"> \
<arg name="sessions" type="a(susso)" direction="out"/> \
</method> \
<signal name="PrepareForSleep"> \
<arg type="b" direction="out"/> \
</signal> \
</interface> \
</node>';
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
<method name='Suspend'>
<arg type='b' direction='in'/>
</method>
<method name='CanSuspend'>
<arg type='s' direction='out'/>
</method>
<method name='Inhibit'>
<arg type='s' direction='in'/>
<arg type='s' direction='in'/>
<arg type='s' direction='in'/>
<arg type='s' direction='in'/>
<arg type='h' direction='out'/>
</method>
<method name='GetSession'>
<arg type='s' direction='in'/>
<arg type='o' direction='out'/>
</method>
<method name='ListSessions'>
<arg name='sessions' type='a(susso)' direction='out'/>
</method>
<signal name='PrepareForSleep'>
<arg type='b' direction='out'/>
</signal>
</interface>;
const SystemdLoginSessionIface = '<node> \
<interface name="org.freedesktop.login1.Session"> \
<signal name="Lock" /> \
<signal name="Unlock" /> \
</interface> \
</node>';
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
<signal name='Lock' />
<signal name='Unlock' />
</interface>;
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
const ConsoleKitManagerIface = '<node> \
<interface name="org.freedesktop.ConsoleKit.Manager"> \
<method name="CanRestart"> \
<arg type="b" direction="out"/> \
</method> \
<method name="CanStop"> \
<arg type="b" direction="out"/> \
</method> \
<method name="Restart" /> \
<method name="Stop" /> \
<method name="GetCurrentSession"> \
<arg type="o" direction="out" /> \
</method> \
</interface> \
</node>';
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
<method name='CanRestart'>
<arg type='b' direction='out'/>
</method>
<method name='CanStop'>
<arg type='b' direction='out'/>
</method>
<method name='Restart' />
<method name='Stop' />
<method name='GetCurrentSession'>
<arg type='o' direction='out' />
</method>
</interface>;
const ConsoleKitSessionIface = '<node> \
<interface name="org.freedesktop.ConsoleKit.Session"> \
<signal name="Lock" /> \
<signal name="Unlock" /> \
</interface> \
</node>';
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
<signal name='Lock' />
<signal name='Unlock' />
</interface>;
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);

View File

@ -92,41 +92,37 @@ function _findProviderForSid(sid) {
// The following are not the complete interfaces, just the methods we need
// (or may need in the future)
const ModemGsmNetworkInterface = '<node> \
<interface name="org.freedesktop.ModemManager.Modem.Gsm.Network"> \
<method name="GetRegistrationInfo"> \
<arg type="(uss)" direction="out" /> \
</method> \
<method name="GetSignalQuality"> \
<arg type="u" direction="out" /> \
</method> \
<property name="AccessTechnology" type="u" access="read" /> \
<signal name="SignalQuality"> \
<arg type="u" direction="out" /> \
</signal> \
<signal name="RegistrationInfo"> \
<arg type="u" direction="out" /> \
<arg type="s" direction="out" /> \
<arg type="s" direction="out" /> \
</signal> \
</interface> \
</node>';
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
<method name="GetRegistrationInfo">
<arg type="(uss)" direction="out" />
</method>
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<property name="AccessTechnology" type="u" access="read" />
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
<signal name="RegistrationInfo">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="s" direction="out" />
</signal>
</interface>;
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
const ModemCdmaInterface = '<node> \
<interface name="org.freedesktop.ModemManager.Modem.Cdma"> \
<method name="GetSignalQuality"> \
<arg type="u" direction="out" /> \
</method> \
<method name="GetServingSystem"> \
<arg type="(usu)" direction="out" /> \
</method> \
<signal name="SignalQuality"> \
<arg type="u" direction="out" /> \
</signal> \
</interface> \
</node>';
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<method name="GetServingSystem">
<arg type="(usu)" direction="out" />
</method>
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
</interface>;
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
@ -222,26 +218,20 @@ Signals.addSignalMethods(ModemCdma.prototype);
// Support for the new ModemManager1 interface (MM >= 0.7)
//------------------------------------------------------------------------------
const BroadbandModemInterface = '<node> \
<interface name="org.freedesktop.ModemManager1.Modem"> \
<property name="SignalQuality" type="(ub)" access="read" /> \
</interface> \
</node>';
const BroadbandModemInterface = <interface name="org.freedesktop.ModemManager1.Modem">
<property name="SignalQuality" type="(ub)" access="read" />
</interface>;
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
const BroadbandModem3gppInterface = '<node> \
<interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp"> \
<property name="OperatorCode" type="s" access="read" /> \
<property name="OperatorName" type="s" access="read" /> \
</interface> \
</node>';
const BroadbandModem3gppInterface = <interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp">
<property name="OperatorCode" type="s" access="read" />
<property name="OperatorName" type="s" access="read" />
</interface>;
const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface);
const BroadbandModemCdmaInterface = '<node> \
<interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> \
<property name="Sid" type="u" access="read" /> \
</interface> \
</node>';
const BroadbandModemCdmaInterface = <interface name="org.freedesktop.ModemManager1.Modem.ModemCdma">
<property name="Sid" type="u" access="read" />
</interface>;
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
const BroadbandModem = new Lang.Class({

View File

@ -8,21 +8,19 @@ const Signals = imports.signals;
// Specified in the D-Bus specification here:
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
const ObjectManagerIface = '<node> \
<interface name="org.freedesktop.DBus.ObjectManager"> \
<method name="GetManagedObjects"> \
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/> \
</method> \
<signal name="InterfacesAdded"> \
<arg name="objectPath" type="o"/> \
<arg name="interfaces" type="a{sa{sv}}" /> \
</signal> \
<signal name="InterfacesRemoved"> \
<arg name="objectPath" type="o"/> \
<arg name="interfaces" type="as" /> \
</signal> \
</interface> \
</node>';
const ObjectManagerIface = <interface name="org.freedesktop.DBus.ObjectManager">
<method name="GetManagedObjects">
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
</method>
<signal name="InterfacesAdded">
<arg name="objectPath" type="o"/>
<arg name="interfaces" type="a{sa{sv}}" />
</signal>
<signal name="InterfacesRemoved">
<arg name="objectPath" type="o"/>
<arg name="interfaces" type="as" />
</signal>
</interface>;
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);

View File

@ -7,14 +7,12 @@ const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager;
const SmartcardTokenIface = '<node> \
<interface name="org.gnome.SettingsDaemon.Smartcard.Token"> \
<property name="Name" type="s" access="read"/> \
<property name="Driver" type="o" access="read"/> \
<property name="IsInserted" type="b" access="read"/> \
<property name="UsedToLogin" type="b" access="read"/> \
</interface> \
</node>';
const SmartcardTokenIface = <interface name="org.gnome.SettingsDaemon.Smartcard.Token">
<property name="Name" type="s" access="read"/>
<property name="Driver" type="o" access="read"/>
<property name="IsInserted" type="b" access="read"/>
<property name="UsedToLogin" type="b" access="read"/>
</interface>;
let _smartcardManager = null;

View File

@ -106,8 +106,6 @@ const AppSwitcherPopup = new Lang.Class({
this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons;
if (this._items.length == 0)
return false;
return true;
},
@ -377,9 +375,6 @@ const WindowSwitcherPopup = new Lang.Class({
this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons;
if (this._items.length == 0)
return false;
return true;
},

View File

@ -55,13 +55,13 @@ function _loadCategory(dir, view) {
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.ENTRY) {
let entry = iter.get_entry();
let appInfo = entry.get_app_info();
let app = appSystem.lookup_app(entry.get_desktop_file_id());
if (appInfo.should_show())
let app = appSystem.lookup_app_by_tree_entry(entry);
if (!entry.get_app_info().get_nodisplay())
view.addApp(app);
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
let itemDir = iter.get_directory();
_loadCategory(itemDir, view);
if (!itemDir.get_is_nodisplay())
_loadCategory(itemDir, view);
}
}
};
@ -92,7 +92,7 @@ const BaseAppView = new Lang.Class({
},
removeAll: function() {
this._grid.destroyAll();
this._grid.removeAll();
this._items = {};
this._allItems = [];
},
@ -613,10 +613,6 @@ const FrequentView = new Lang.Class({
return this._usage.get_most_used("").length >= MIN_FREQUENT_APPS_COUNT;
},
removeAll: function() {
this._grid.destroyAll();
},
loadApps: function() {
let mostUsed = this._usage.get_most_used ("");
let hasUsefulData = this.hasUsefulData();
@ -695,7 +691,8 @@ const AppDisplay = new Lang.Class({
Name: 'AppDisplay',
_init: function() {
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
Main.queueDeferredWork(this._allAppsWorkId);
}));
Main.overview.connect('showing', Lang.bind(this, function() {
@ -816,8 +813,7 @@ const AppDisplay = new Lang.Class({
view.removeAll();
let tree = new GMenu.Tree({ menu_basename: "applications.menu" });
tree.load_sync();
let tree = this._appSystem.get_tree();
let root = tree.get_root_directory();
let iter = root.iter();
@ -826,6 +822,8 @@ const AppDisplay = new Lang.Class({
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.DIRECTORY) {
let dir = iter.get_directory();
if (dir.get_is_nodisplay())
continue;
if (folderCategories.indexOf(dir.get_menu_id()) != -1)
view.addFolder(dir);
@ -873,8 +871,8 @@ const AppSearchProvider = new Lang.Class({
getResultMetas: function(apps, callback) {
let metas = [];
for (let i = 0; i < apps.length; i++) {
let app = this._appSys.lookup_app(apps[i]);
metas.push({ 'id': app.get_id(),
let app = apps[i];
metas.push({ 'id': app,
'name': app.get_name(),
'createIcon': function(size) {
return app.create_icon_texture(size);
@ -888,16 +886,15 @@ const AppSearchProvider = new Lang.Class({
return results.slice(0, maxNumber);
},
getInitialResultSet: function(terms, callback, cancellable) {
callback(this._appSys.initial_search(terms));
getInitialResultSet: function(terms) {
this.searchSystem.setResults(this, this._appSys.initial_search(terms));
},
getSubsearchResultSet: function(previousResults, terms, callback, cancellable) {
callback(this._appSys.subsearch(previousResults, terms));
getSubsearchResultSet: function(previousResults, terms) {
this.searchSystem.setResults(this, this._appSys.subsearch(previousResults, terms));
},
activateResult: function(result) {
let app = this._appSys.lookup_app(result);
activateResult: function(app) {
let event = Clutter.get_current_event();
let modifiers = event ? event.get_state() : 0;
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
@ -916,8 +913,8 @@ const AppSearchProvider = new Lang.Class({
app.open_new_window(workspace);
},
createResultObject: function (resultMeta) {
let app = this._appSys.lookup_app(resultMeta['id']);
createResultObject: function (resultMeta, terms) {
let app = resultMeta['id'];
return new AppIcon(app);
}
});
@ -1355,9 +1352,7 @@ const AppIcon = new Lang.Class({
this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() {
this._menuTimeoutId = 0;
this.popupMenu();
return false;
}));
} else if (button == 3) {
this.popupMenu();

View File

@ -315,6 +315,7 @@ const Background = new Lang.Class({
this._brightness = 1.0;
this._vignetteSharpness = 0.2;
this._saturation = 1.0;
this._cancellable = new Gio.Cancellable();
this.isLoaded = false;
@ -415,6 +416,7 @@ const Background = new Lang.Class({
},
_addImage: function(content, index, filename) {
content.saturation = this._saturation;
content.brightness = this._brightness;
content.vignette_sharpness = this._vignetteSharpness;
@ -430,6 +432,7 @@ const Background = new Lang.Class({
},
_updateImage: function(content, index, filename) {
content.saturation = this._saturation;
content.brightness = this._brightness;
content.vignette_sharpness = this._vignetteSharpness;
@ -587,6 +590,24 @@ const Background = new Lang.Class({
this._loadFile(filename);
},
get saturation() {
return this._saturation;
},
set saturation(saturation) {
this._saturation = saturation;
if (this._pattern && this._pattern.content)
this._pattern.content.saturation = saturation;
let keys = Object.keys(this._images);
for (let i = 0; i < keys.length; i++) {
let image = this._images[keys[i]];
if (image && image.content)
image.content.saturation = saturation;
}
},
get brightness() {
return this._brightness;
},
@ -730,6 +751,7 @@ const BackgroundManager = new Lang.Class({
let newBackground = this._createBackground(monitorIndex);
newBackground.vignetteSharpness = background.vignetteSharpness;
newBackground.brightness = background.brightness;
newBackground.saturation = background.saturation;
newBackground.visible = background.visible;
newBackground.loadedSignalId = newBackground.connect('loaded',

View File

@ -190,18 +190,16 @@ const EmptyEventSource = new Lang.Class({
});
Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = '<node> \
<interface name="org.gnome.Shell.CalendarServer"> \
<method name="GetEvents"> \
<arg type="x" direction="in" /> \
<arg type="x" direction="in" /> \
<arg type="b" direction="in" /> \
<arg type="a(sssbxxa{sv})" direction="out" /> \
</method> \
<property name="HasCalendars" type="b" access="read" /> \
<signal name="Changed" /> \
</interface> \
</node>';
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>;
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);

View File

@ -75,14 +75,12 @@ function startAppForMount(app, mount) {
/******************************************/
const HotplugSnifferIface = '<node> \
<interface name="org.gnome.Shell.HotplugSniffer"> \
<method name="SniffURI"> \
<arg type="s" direction="in" /> \
<arg type="as" direction="out" /> \
</method> \
</interface> \
</node>';
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
<method name="SniffURI">
<arg type="s" direction="in" />
<arg type="as" direction="out" />
</method>
</interface>;
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() {

View File

@ -138,8 +138,6 @@ const NetworkSecretDialog = new Lang.Class({
key: Clutter.KEY_Escape,
},
this._okButton]);
this._updateOkButton();
},
_updateOkButton: function() {
@ -434,7 +432,6 @@ const VPNRequestHandler = new Lang.Class({
},
_vpnChildFinished: function(pid, status, requestObj) {
this._childWatch = 0;
if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions
// Just reap the process here

View File

@ -446,7 +446,6 @@ const ChatSource = new Lang.Class({
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
this._notification = new ChatNotification(this);
this._notification.connect('clicked', Lang.bind(this, this.open));
this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notifyTimeoutId = 0;
@ -545,19 +544,20 @@ const ChatSource = new Lang.Class({
this._notification.update(this._notification.title, null, { customContent: true });
},
open: function() {
if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy
this._client.delegate_channels_async([this._channel],
global.get_current_time(),
'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
} else {
// We are not the handler, just ask to present the channel
let dbus = Tp.DBusDaemon.dup();
let cd = Tp.ChannelDispatcher.new(dbus);
open: function(notification) {
if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy
this._client.delegate_channels_async([this._channel],
global.get_current_time(),
'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
}
else {
// We are not the handler, just ask to present the channel
let dbus = Tp.DBusDaemon.dup();
let cd = Tp.ChannelDispatcher.new(dbus);
cd.present_channel_async(this._channel, global.get_current_time(), null);
}
cd.present_channel_async(this._channel, global.get_current_time(), null);
}
},
_getLogMessages: function() {
@ -960,8 +960,6 @@ const ChatNotification = new Lang.Class({
},
appendTimestamp: function() {
this._timestampTimeoutId = 0;
let lastMessageTime = this._history[0].time;
let lastMessageDate = new Date(lastMessageTime * 1000);
@ -1097,16 +1095,22 @@ const RoomInviteNotification = new Lang.Class({
* for example. */
this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier()));
this.addAction(_("Decline"), Lang.bind(this, function() {
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
src.leave_channels_finish(result);
});
this.destroy();
}));
this.addAction(_("Accept"), Lang.bind(this, function() {
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
src.handle_with_time_finish(result);
});
this.addButton('decline', _("Decline"));
this.addButton('accept', _("Accept"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'decline':
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
'', function(src, result) {
src.leave_channels_finish(result)});
break;
case 'accept':
dispatchOp.handle_with_time_async('', global.get_current_time(),
function(src, result) {
src.handle_with_time_finish(result)});
break;
}
this.destroy();
}));
}
@ -1132,17 +1136,23 @@ const AudioVideoNotification = new Lang.Class({
this.setUrgency(MessageTray.Urgency.CRITICAL);
this.addAction(_("Decline"), Lang.bind(this, function() {
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
src.leave_channels_finish(result);
});
this.destroy();
}));
this.addButton('reject', _("Decline"));
/* translators: this is a button label (verb), not a noun */
this.addAction(_("Answer"), Lang.bind(this, function() {
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
src.handle_with_time_finish(result);
});
this.addButton('answer', _("Answer"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'reject':
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
'', function(src, result) {
src.leave_channels_finish(result)});
break;
case 'answer':
dispatchOp.handle_with_time_async('', global.get_current_time(),
function(src, result) {
src.handle_with_time_finish(result)});
break;
}
this.destroy();
}));
}
@ -1166,16 +1176,22 @@ const FileTransferNotification = new Lang.Class({
{ customContent: true });
this.setResident(true);
this.addAction(_("Decline"), Lang.bind(this, function() {
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
src.leave_channels_finish(result);
});
this.destroy();
}));
this.addAction(_("Accept"), Lang.bind(this, function() {
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
src.handle_with_time_finish(result);
});
this.addButton('decline', _("Decline"));
this.addButton('accept', _("Accept"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'decline':
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
'', function(src, result) {
src.leave_channels_finish(result)});
break;
case 'accept':
dispatchOp.handle_with_time_async('', global.get_current_time(),
function(src, result) {
src.handle_with_time_finish(result)});
break;
}
this.destroy();
}));
}
@ -1223,20 +1239,27 @@ const SubscriptionRequestNotification = new Lang.Class({
this.addActor(layout);
this.addAction(_("Decline"), Lang.bind(this, function() {
contact.remove_async(function(src, result) {
src.remove_finish(result);
});
}));
this.addAction(_("Accept"), Lang.bind(this, function() {
// Authorize the contact and request to see his status as well
contact.authorize_publication_async(function(src, result) {
src.authorize_publication_finish(result);
});
this.addButton('decline', _("Decline"));
this.addButton('accept', _("Accept"));
contact.request_subscription_async('', function(src, result) {
src.request_subscription_finish(result);
});
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'decline':
contact.remove_async(function(src, result) {
src.remove_finish(result)});
break;
case 'accept':
// Authorize the contact and request to see his status as well
contact.authorize_publication_async(function(src, result) {
src.authorize_publication_finish(result)});
contact.request_subscription_async('', function(src, result) {
src.request_subscription_finish(result)});
break;
}
// rely on _subscriptionStatesChangedCb to destroy the
// notification
}));
this._changedId = contact.connect('subscription-states-changed',
@ -1335,11 +1358,18 @@ const AccountNotification = new Lang.Class({
this._account = account;
this.addAction(_("View account"), Lang.bind(this, function() {
let cmd = 'empathy-accounts --select-account=' +
account.get_path_suffix();
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
app_info.launch([], global.create_app_launch_context());
this.addButton('view', _("View account"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'view':
let cmd = 'empathy-accounts --select-account=' +
account.get_path_suffix();
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
app_info.launch([], global.create_app_launch_context());
break;
}
this.destroy();
}));
this._enabledId = account.connect('notify::enabled',

View File

@ -576,7 +576,6 @@ const Dash = new Lang.Class({
Lang.bind(this, function() {
this._labelShowing = true;
item.showLabel();
this._showLabelTimeoutId = 0;
return false;
}));
if (this._resetHoverTimeoutId > 0) {
@ -593,7 +592,6 @@ const Dash = new Lang.Class({
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
Lang.bind(this, function() {
this._labelShowing = false;
this._resetHoverTimeoutId = 0;
return false;
}));
}

View File

@ -236,7 +236,7 @@ const _Draggable = new Lang.Class({
if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor();
Main.uiGroup.add_child(this._dragActor);
this._dragActor.reparent(Main.uiGroup);
this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true);
@ -285,8 +285,7 @@ const _Draggable = new Lang.Class({
this._dragOffsetX = actorStageX - this._dragStartX;
this._dragOffsetY = actorStageY - this._dragStartY;
this._dragOrigParent.remove_actor(this._dragActor);
Main.uiGroup.add_child(this._dragActor);
this._dragActor.reparent(Main.uiGroup);
this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true);
}
@ -346,7 +345,6 @@ const _Draggable = new Lang.Class({
},
_updateDragHover : function () {
this._updateHoverId = 0;
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY);
let dragEvent = {
@ -391,7 +389,7 @@ const _Draggable = new Lang.Class({
_queueUpdateDragHover: function() {
if (this._updateHoverId)
return;
GLib.source_remove(this._updateHoverId);
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._updateDragHover));
@ -557,8 +555,7 @@ const _Draggable = new Lang.Class({
_onAnimationComplete : function (dragActor, eventTime) {
if (this._dragOrigParent) {
Main.uiGroup.remove_child(this._dragActor);
this._dragOrigParent.add_actor(this._dragActor);
dragActor.reparent(this._dragOrigParent);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
dragActor.set_position(this._dragOrigX, this._dragOrigY);
} else {

View File

@ -43,22 +43,20 @@ const _DIALOG_ICON_SIZE = 32;
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = '<node> \
<interface name="org.gnome.SessionManager.EndSessionDialog"> \
<method name="Open"> \
<arg type="u" direction="in" /> \
<arg type="u" direction="in" /> \
<arg type="u" direction="in" /> \
<arg type="ao" direction="in" /> \
</method> \
<method name="Close" /> \
<signal name="ConfirmedLogout" /> \
<signal name="ConfirmedReboot" /> \
<signal name="ConfirmedShutdown" /> \
<signal name="Canceled" /> \
<signal name="Closed" /> \
</interface> \
</node>';
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
<method name="Open">
<arg type="u" direction="in" />
<arg type="u" direction="in" />
<arg type="u" direction="in" />
<arg type="ao" direction="in" />
</method>
<method name="Close" />
<signal name="ConfirmedLogout" />
<signal name="ConfirmedReboot" />
<signal name="ConfirmedShutdown" />
<signal name="Canceled" />
<signal name="Closed" />
</interface>;
const logoutDialogContent = {
subjectWithUser: C_("title", "Log Out %s"),
@ -133,15 +131,13 @@ const DialogContent = {
const MAX_USERS_IN_SESSION_DIALOG = 5;
const LogindSessionIface = '<node> \
<interface name="org.freedesktop.login1.Session"> \
<property name="Id" type="s" access="read"/> \
<property name="Remote" type="b" access="read"/> \
<property name="Class" type="s" access="read"/> \
<property name="Type" type="s" access="read"/> \
<property name="State" type="s" access="read"/> \
</interface> \
</node>';
const LogindSessionIface = <interface name='org.freedesktop.login1.Session'>
<property name="Id" type="s" access="read"/>
<property name="Remote" type="b" access="read"/>
<property name="Class" type="s" access="read"/>
<property name="Type" type="s" access="read"/>
<property name="State" type="s" access="read"/>
</interface>;
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
@ -273,15 +269,13 @@ const EndSessionDialog = new Lang.Class({
this._applicationHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
text: _("Some applications are busy or have unsaved work.") });
this._applicationList = new St.BoxLayout({ style_class: 'end-session-dialog-app-list',
vertical: true });
this._applicationList = new St.BoxLayout({ vertical: true });
this._inhibitorSection.add_actor(this._applicationHeader);
this._inhibitorSection.add_actor(this._applicationList);
this._sessionHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
text: _("Other users are logged in.") });
this._sessionList = new St.BoxLayout({ style_class: 'end-session-dialog-session-list',
vertical: true });
this._sessionList = new St.BoxLayout({ vertical: true });
this._inhibitorSection.add_actor(this._sessionHeader);
this._inhibitorSection.add_actor(this._sessionList);
@ -415,7 +409,6 @@ const EndSessionDialog = new Lang.Class({
let dialogContent = DialogContent[this._type];
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
this._confirm(button.signal);
this._timerId = 0;
return false;
}));

View File

@ -76,11 +76,7 @@ function disableExtension(uuid) {
theme.unload_stylesheet(extension.stylesheet.get_path());
}
try {
extension.stateObj.disable();
} catch(e) {
logExtensionError(uuid, e);
}
extension.stateObj.disable();
for (let i = 0; i < order.length; i++) {
let uuid = order[i];
@ -93,10 +89,8 @@ function disableExtension(uuid) {
extensionOrder.splice(orderIdx, 1);
if ( extension.state != ExtensionState.ERROR ) {
extension.state = ExtensionState.DISABLED;
_signals.emit('extension-state-changed', extension);
}
extension.state = ExtensionState.DISABLED;
_signals.emit('extension-state-changed', extension);
}
function enableExtension(uuid) {
@ -123,15 +117,10 @@ function enableExtension(uuid) {
}
}
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
_signals.emit('extension-state-changed', extension);
return;
} catch(e) {
logExtensionError(uuid, e);
return;
}
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
_signals.emit('extension-state-changed', extension);
}
function logExtensionError(uuid, error) {
@ -161,8 +150,7 @@ function loadExtension(extension) {
} else {
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
if (enabled) {
if (!initExtension(extension.uuid))
return;
initExtension(extension.uuid);
if (extension.state == ExtensionState.DISABLED)
enableExtension(extension.uuid);
} else {
@ -217,12 +205,7 @@ function initExtension(uuid) {
extensionModule = extension.imports.extension;
if (extensionModule.init) {
try {
extensionState = extensionModule.init(extension);
} catch(e) {
logExtensionError(uuid, e);
return false;
}
extensionState = extensionModule.init(extension);
}
if (!extensionState)
@ -231,7 +214,6 @@ function initExtension(uuid) {
extension.state = ExtensionState.DISABLED;
_signals.emit('extension-loaded', uuid);
return true;
}
function getEnabledExtensions() {
@ -253,7 +235,11 @@ function onEnabledExtensionsChanged() {
newEnabledExtensions.filter(function(uuid) {
return enabledExtensions.indexOf(uuid) == -1;
}).forEach(function(uuid) {
enableExtension(uuid);
try {
enableExtension(uuid);
} catch(e) {
logExtensionError(uuid, e);
}
});
// Find and disable all the newly disabled extensions: UUIDs found in the
@ -261,7 +247,11 @@ function onEnabledExtensionsChanged() {
enabledExtensions.filter(function(item) {
return newEnabledExtensions.indexOf(item) == -1;
}).forEach(function(uuid) {
disableExtension(uuid);
try {
disableExtension(uuid);
} catch(e) {
logExtensionError(uuid, e);
}
});
enabledExtensions = newEnabledExtensions;
@ -272,8 +262,12 @@ function _loadExtensions() {
enabledExtensions = getEnabledExtensions();
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', function(finder, extension) {
loadExtension(extension);
finder.connect('extension-found', function(signals, extension) {
try {
loadExtension(extension);
} catch(e) {
logExtensionError(extension.uuid, e);
}
});
finder.scanExtensions();
}

View File

@ -413,18 +413,15 @@ const IconGrid = new Lang.Class({
},
removeAll: function() {
this._items = [];
this._grid.remove_all_children();
},
destroyAll: function() {
this._items = [];
this._grid.destroy_all_children();
},
addItem: function(item, index) {
if (!item.icon instanceof BaseIcon)
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
if (!item.icon || !item.icon instanceof BaseIcon) {
log('Only items with a BaseIcon icon property can be added to IconGrid');
return;
}
this._items.push(item);
if (index !== undefined)

View File

@ -23,29 +23,27 @@ const KEYBOARD_TYPE = 'keyboard-type';
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
const CaribouKeyboardIface = '<node> \
<interface name="org.gnome.Caribou.Keyboard"> \
<method name="Show"> \
<arg type="u" direction="in" /> \
</method> \
<method name="Hide"> \
<arg type="u" direction="in" /> \
</method> \
<method name="SetCursorLocation"> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
</method> \
<method name="SetEntryLocation"> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
</method> \
<property name="Name" access="read" type="s" /> \
</interface> \
</node>';
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
<method name='Show'>
<arg type='u' direction='in' />
</method>
<method name='Hide'>
<arg type='u' direction='in' />
</method>
<method name='SetCursorLocation'>
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
</method>
<method name='SetEntryLocation'>
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
</method>
<property name='Name' access='read' type='s' />
</interface>;
const Key = new Lang.Class({
Name: 'Key',

View File

@ -629,6 +629,55 @@ const Inspector = new Lang.Class({
Signals.addSignalMethods(Inspector.prototype);
const Memory = new Lang.Class({
Name: 'Memory',
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
this._glibc_uordblks = new St.Label();
this.actor.add(this._glibc_uordblks);
this._js_bytes = new St.Label();
this.actor.add(this._js_bytes);
this._gjs_boxed = new St.Label();
this.actor.add(this._gjs_boxed);
this._gjs_gobject = new St.Label();
this.actor.add(this._gjs_gobject);
this._gjs_function = new St.Label();
this.actor.add(this._gjs_function);
this._gjs_closure = new St.Label();
this.actor.add(this._gjs_closure);
this._last_gc_seconds_ago = new St.Label();
this.actor.add(this._last_gc_seconds_ago);
this._gcbutton = new St.Button({ label: 'Full GC',
style_class: 'lg-obj-inspector-button' });
this._gcbutton.connect('clicked', Lang.bind(this, function () { System.gc(); this._renderText(); }));
this.actor.add(this._gcbutton, { x_align: St.Align.START,
x_fill: false });
this.actor.connect('notify::mapped', Lang.bind(this, this._renderText));
},
_renderText: function() {
if (!this.actor.mapped)
return;
let memInfo = global.get_memory_info();
this._glibc_uordblks.text = 'glibc_uordblks: ' + memInfo.glibc_uordblks;
this._js_bytes.text = 'js bytes: ' + memInfo.js_bytes;
this._gjs_boxed.text = 'gjs_boxed: ' + memInfo.gjs_boxed;
this._gjs_gobject.text = 'gjs_gobject: ' + memInfo.gjs_gobject;
this._gjs_function.text = 'gjs_function: ' + memInfo.gjs_function;
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
}
});
const Extensions = new Lang.Class({
Name: 'Extensions',
@ -831,19 +880,6 @@ const LookingGlass = new Lang.Class({
return true;
}));
let gcIcon = new St.Icon({ icon_name: 'gnome-fs-trash-full',
icon_size: 24 });
toolbar.add_actor(gcIcon);
gcIcon.reactive = true;
gcIcon.connect('button-press-event', Lang.bind(this, function () {
gcIcon.icon_name = 'gnome-fs-trash-empty';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () {
gcIcon.icon_name = 'gnome-fs-trash-full';
Mainloop.source_remove(this._timeoutId);
}));
}));
let notebook = new Notebook();
this._notebook = notebook;
this.actor.add(notebook.actor, { expand: true });
@ -871,6 +907,9 @@ const LookingGlass = new Lang.Class({
this._windowList = new WindowList(this);
notebook.appendPage('Windows', this._windowList.actor);
this._memory = new Memory();
notebook.appendPage('Memory', this._memory.actor);
this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions.actor);

View File

@ -9,89 +9,85 @@ const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
const MagnifierIface = '<node> \
<interface name="org.gnome.Magnifier"> \
<method name="setActive"> \
<arg type="b" direction="in" /> \
</method> \
<method name="isActive"> \
<arg type="b" direction="out" /> \
</method> \
<method name="showCursor" /> \
<method name="hideCursor" /> \
<method name="createZoomRegion"> \
<arg type="d" direction="in" /> \
<arg type="d" direction="in" /> \
<arg type="ai" direction="in" /> \
<arg type="ai" direction="in" /> \
<arg type="o" direction="out" /> \
</method> \
<method name="addZoomRegion"> \
<arg type="o" direction="in" /> \
<arg type="b" direction="out" /> \
</method> \
<method name="getZoomRegions"> \
<arg type="ao" direction="out" /> \
</method> \
<method name="clearAllZoomRegions" /> \
<method name="fullScreenCapable"> \
<arg type="b" direction="out" /> \
</method> \
<method name="setCrosswireSize"> \
<arg type="i" direction="in" /> \
</method> \
<method name="getCrosswireSize"> \
<arg type="i" direction="out" /> \
</method> \
<method name="setCrosswireLength"> \
<arg type="i" direction="in" /> \
</method> \
<method name="getCrosswireLength"> \
<arg type="i" direction="out" /> \
</method> \
<method name="setCrosswireClip"> \
<arg type="b" direction="in" /> \
</method> \
<method name="getCrosswireClip"> \
<arg type="b" direction="out" /> \
</method> \
<method name="setCrosswireColor"> \
<arg type="u" direction="in" /> \
</method> \
<method name="getCrosswireColor"> \
<arg type="u" direction="out" /> \
</method> \
</interface> \
</node>';
const MagnifierIface = <interface name="org.gnome.Magnifier">
<method name="setActive">
<arg type="b" direction="in" />
</method>
<method name="isActive">
<arg type="b" direction="out" />
</method>
<method name="showCursor" />
<method name="hideCursor" />
<method name="createZoomRegion">
<arg type="d" direction="in" />
<arg type="d" direction="in" />
<arg type="ai" direction="in" />
<arg type="ai" direction="in" />
<arg type="o" direction="out" />
</method>
<method name="addZoomRegion">
<arg type="o" direction="in" />
<arg type="b" direction="out" />
</method>
<method name="getZoomRegions">
<arg type="ao" direction="out" />
</method>
<method name="clearAllZoomRegions" />
<method name="fullScreenCapable">
<arg type="b" direction="out" />
</method>
<method name="setCrosswireSize">
<arg type="i" direction="in" />
</method>
<method name="getCrosswireSize">
<arg type="i" direction="out" />
</method>
<method name="setCrosswireLength">
<arg type="i" direction="in" />
</method>
<method name="getCrosswireLength">
<arg type="i" direction="out" />
</method>
<method name="setCrosswireClip">
<arg type="b" direction="in" />
</method>
<method name="getCrosswireClip">
<arg type="b" direction="out" />
</method>
<method name="setCrosswireColor">
<arg type="u" direction="in" />
</method>
<method name="getCrosswireColor">
<arg type="u" direction="out" />
</method>
</interface>;
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
const ZoomRegionIface = '<node> \
<interface name="org.gnome.Magnifier.ZoomRegion"> \
<method name="setMagFactor"> \
<arg type="d" direction="in" /> \
<arg type="d" direction="in" /> \
</method> \
<method name="getMagFactor"> \
<arg type="d" direction="out" /> \
<arg type="d" direction="out" /> \
</method> \
<method name="setRoi"> \
<arg type="ai" direction="in" /> \
</method> \
<method name="getRoi"> \
<arg type="ai" direction="out" /> \
</method> \
<method name="shiftContentsTo"> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
<arg type="b" direction="out" /> \
</method> \
<method name="moveResize"> \
<arg type="ai" direction="in" /> \
</method> \
</interface> \
</node>';
const ZoomRegionIface = <interface name="org.gnome.Magnifier.ZoomRegion">
<method name="setMagFactor">
<arg type="d" direction="in" />
<arg type="d" direction="in" />
</method>
<method name="getMagFactor">
<arg type="d" direction="out" />
<arg type="d" direction="out" />
</method>
<method name="setRoi">
<arg type="ai" direction="in" />
</method>
<method name="getRoi">
<arg type="ai" direction="out" />
</method>
<method name="shiftContentsTo">
<arg type="i" direction="in" />
<arg type="i" direction="in" />
<arg type="b" direction="out" />
</method>
<method name="moveResize">
<arg type="ai" direction="in" />
</method>
</interface>;
// For making unique ZoomRegion DBus proxy object paths of the form:
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',

View File

@ -112,6 +112,11 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode();
sessionMode.connect('sessions-loaded', _sessionsLoaded);
sessionMode.init();
}
function _sessionsLoaded() {
sessionMode.connect('updated', _sessionUpdated);
_initializePrefs();
_initializeUI();

View File

@ -280,6 +280,10 @@ const URLHighlighter = new Lang.Class({
}
});
function strHasSuffix(string, suffix) {
return string.substr(-suffix.length) == suffix;
}
// NotificationPolicy:
// An object that holds all bits of configurable policy related to a notification
// source, such as whether to play sound or honour the critical bit.
@ -499,6 +503,7 @@ const Notification = new Lang.Class({
this.focused = false;
this.acknowledged = false;
this._destroyed = false;
this._useActionIcons = false;
this._customContent = false;
this.bannerBodyText = null;
this.bannerBodyMarkup = false;
@ -831,7 +836,17 @@ const Notification = new Lang.Class({
}
},
addButton: function(button, callback) {
// addButton:
// @id: the action ID
// @label: the label for the action's button
//
// Adds a button with the given @label to the notification. All
// action buttons will appear in a single row at the bottom of
// the notification.
//
// If the button is clicked, the notification will emit the
// %action-invoked signal with @id as a parameter
addButton: function(id, label) {
if (!this._buttonBox) {
let box = new St.BoxLayout({ style_class: 'notification-actions' });
this.setActionArea(box, { x_expand: false,
@ -843,37 +858,43 @@ const Notification = new Lang.Class({
global.focus_manager.add_group(this._buttonBox);
}
this._buttonBox.add(button);
button.connect('clicked', Lang.bind(this, function() {
callback();
let button = new St.Button({ can_focus: true });
button._actionId = id;
if (!this.resident) {
// We don't hide a resident notification when the user invokes one of its actions,
// because it is common for such notifications to update themselves with new
// information based on the action. We'd like to display the updated information
// in place, rather than pop-up a new notification.
this.emit('done-displaying');
this.destroy();
}
}));
let iconName = strHasSuffix(id, '-symbolic') ? id : id + '-symbolic';
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
button.add_style_class_name('notification-icon-button');
button.child = new St.Icon({ icon_name: iconName });
} else {
button.add_style_class_name('notification-button');
button.label = label;
}
this._buttonBox.add(button);
button.connect('clicked', Lang.bind(this, this._onActionInvoked, id));
this.updated();
return button;
},
// addAction:
// @label: the label for the action's button
// @callback: the callback for the action
// setButtonSensitive:
// @id: the action ID
// @sensitive: whether the button should be sensitive
//
// Adds a button with the given @label to the notification. All
// action buttons will appear in a single row at the bottom of
// the notification.
addAction: function(label, callback) {
let button = new St.Button({ style_class: 'notification-button',
label: label,
can_focus: true });
// If the notification contains a button with action ID @id,
// its sensitivity will be set to @sensitive. Insensitive
// buttons cannot be clicked.
setButtonSensitive: function(id, sensitive) {
if (!this._buttonBox)
return;
return this.addButton(button, callback);
let button = this._buttonBox.get_children().filter(function(b) {
return b._actionId == id;
})[0];
if (!button || button.reactive == sensitive)
return;
button.reactive = sensitive;
},
setUrgency: function(urgency) {
@ -892,6 +913,10 @@ const Notification = new Lang.Class({
this.forFeedback = forFeedback;
},
setUseActionIcons: function(useIcons) {
this._useActionIcons = useIcons;
},
_styleChanged: function() {
this._spacing = this._table.get_theme_node().get_length('spacing-columns');
},
@ -1116,6 +1141,18 @@ const Notification = new Lang.Class({
this.actor.add_style_class_name('notification-unexpanded');
},
_onActionInvoked: function(actor, mouseButtonClicked, id) {
this.emit('action-invoked', id);
if (!this.resident) {
// We don't hide a resident notification when the user invokes one of its actions,
// because it is common for such notifications to update themselves with new
// information based on the action. We'd like to display the updated information
// in place, rather than pop-up a new notification.
this.emit('done-displaying');
this.destroy();
}
},
_onClicked: function() {
this.emit('clicked');
// We hide all types of notifications once the user clicks on them because the common
@ -1381,7 +1418,9 @@ const Source = new Lang.Class({
if (this.notifications.indexOf(notification) >= 0)
return;
notification.connect('clicked', Lang.bind(this, this.open));
notification.connect('destroy', Lang.bind(this, this._onNotificationDestroy));
this.notifications.push(notification);
this.emit('notification-added', notification);
@ -2173,10 +2212,7 @@ const MessageTray = new Lang.Class({
},
toggleAndNavigate: function() {
if (!this.toggle())
return;
if (this._traySummoned)
if (this.toggle())
this._summary.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
@ -2373,6 +2409,7 @@ const MessageTray = new Lang.Class({
this._showNotification();
}
} else if (this._notificationState == State.SHOWN) {
let pinned = this._pointerInNotification && !this._notificationRemoved;
let expired = (this._userActiveWhileNotificationShown &&
this._notificationTimeoutId == 0 &&
!(this._notification.urgency == Urgency.CRITICAL) &&
@ -2383,9 +2420,9 @@ const MessageTray = new Lang.Class({
if (mustClose) {
let animate = hasNotifications && !this._notificationRemoved;
this._hideNotification(animate);
} else if (this._pointerInNotification && !this._notification.expanded) {
} else if (pinned && !this._notification.expanded) {
this._expandNotification(false);
} else if (this._pointerInNotification) {
} else if (pinned) {
this._ensureNotificationFocused();
}
}
@ -2755,12 +2792,12 @@ const MessageTray = new Lang.Class({
} else if (this._notification.y != expandedY) {
// Tween also opacity here, to override a possible tween that's
// currently hiding the notification.
Tweener.addTween(this._notificationWidget,
{ y: expandedY,
opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
{ y: expandedY,
opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
},

View File

@ -4,7 +4,6 @@ const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop;
@ -16,56 +15,54 @@ const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params;
const Util = imports.misc.util;
let nextNotificationId = 1;
// Should really be defined in Gio.js
const BusIface = '<node> \
<interface name="org.freedesktop.DBus"> \
<method name="GetConnectionUnixProcessID"> \
<arg type="s" direction="in" /> \
<arg type="u" direction="out" /> \
</method> \
</interface> \
</node>';
const BusIface = <interface name="org.freedesktop.DBus">
<method name="GetConnectionUnixProcessID">
<arg type="s" direction="in" />
<arg type="u" direction="out" />
</method>
</interface>;
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
function Bus() {
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
const FdoNotificationsIface = '<node> \
<interface name="org.freedesktop.Notifications"> \
<method name="Notify"> \
<arg type="s" direction="in"/> \
<arg type="u" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="as" direction="in"/> \
<arg type="a{sv}" direction="in"/> \
<arg type="i" direction="in"/> \
<arg type="u" direction="out"/> \
</method> \
<method name="CloseNotification"> \
<arg type="u" direction="in"/> \
</method> \
<method name="GetCapabilities"> \
<arg type="as" direction="out"/> \
</method> \
<method name="GetServerInformation"> \
<arg type="s" direction="out"/> \
<arg type="s" direction="out"/> \
<arg type="s" direction="out"/> \
<arg type="s" direction="out"/> \
</method> \
<signal name="NotificationClosed"> \
<arg type="u"/> \
<arg type="u"/> \
</signal> \
<signal name="ActionInvoked"> \
<arg type="u"/> \
<arg type="s"/> \
</signal> \
</interface> \
</node>';
const NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
<method name="Notify">
<arg type="s" direction="in"/>
<arg type="u" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="as" direction="in"/>
<arg type="a{sv}" direction="in"/>
<arg type="i" direction="in"/>
<arg type="u" direction="out"/>
</method>
<method name="CloseNotification">
<arg type="u" direction="in"/>
</method>
<method name="GetCapabilities">
<arg type="as" direction="out"/>
</method>
<method name="GetServerInformation">
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
</method>
<signal name="NotificationClosed">
<arg type="u"/>
<arg type="u"/>
</signal>
<signal name="ActionInvoked">
<arg type="u"/>
<arg type="s"/>
</signal>
</interface>;
const NotificationClosedReason = {
EXPIRED: 1,
@ -106,11 +103,11 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'ibus-ui-gtk': 'keyboard'
};
const FdoNotificationDaemon = new Lang.Class({
Name: 'FdoNotificationDaemon',
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
_init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(FdoNotificationsIface, this);
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
this._sources = [];
@ -118,8 +115,6 @@ const FdoNotificationDaemon = new Lang.Class({
this._notifications = {};
this._busProxy = new Bus();
this._nextNotificationId = 1;
this._trayManager = new Shell.TrayManager();
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
@ -218,7 +213,7 @@ const FdoNotificationDaemon = new Lang.Class({
}
}
let source = new FdoNotificationDaemonSource(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
let source = new Source(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
source.setTransient(isForTransientNotification);
if (!isForTransientNotification) {
@ -257,7 +252,7 @@ const FdoNotificationDaemon = new Lang.Class({
hints['category'] == 'presence.offline')) {
// Ignore replacesId since we already sent back a
// NotificationClosed for that id.
id = this._nextNotificationId++;
id = nextNotificationId++;
Mainloop.idle_add(Lang.bind(this,
function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
@ -301,7 +296,7 @@ const FdoNotificationDaemon = new Lang.Class({
ndata.notification = this._notifications[replacesId].notification;
} else {
replacesId = 0;
ndata.id = id = this._nextNotificationId++;
ndata.id = id = nextNotificationId++;
}
this._notifications[id] = ndata;
@ -356,19 +351,6 @@ const FdoNotificationDaemon = new Lang.Class({
return invocation.return_value(GLib.Variant.new('(u)', [id]));
},
_makeButton: function(id, label, useActionIcons) {
let button = new St.Button({ can_focus: true });
let iconName = id.endsWith('-symbolic') ? id : id + '-symbolic';
if (useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
button.add_style_class_name('notification-icon-button');
button.child = new St.Icon({ icon_name: iconName });
} else {
button.add_style_class_name('notification-button');
button.label = label;
}
return button;
},
_notifyForSource: function(source, ndata) {
let [id, icon, summary, body, actions, hints, notification] =
[ndata.id, ndata.icon, ndata.summary, ndata.body,
@ -394,6 +376,10 @@ const FdoNotificationDaemon = new Lang.Class({
}
this._emitNotificationClosed(ndata.id, notificationClosedReason);
}));
notification.connect('action-invoked', Lang.bind(this,
function(n, actionId) {
this._emitActionInvoked(ndata.id, actionId);
}));
}
// Mark music notifications so they can be shown in the screen shield
@ -427,33 +413,18 @@ const FdoNotificationDaemon = new Lang.Class({
soundName: hints['sound-name'] });
notification.setImage(image);
let hasDefaultAction = false;
if (actions.length) {
let useActionIcons = (hints['action-icons'] == true);
notification.setUseActionIcons(hints['action-icons'] == true);
for (let i = 0; i < actions.length - 1; i += 2) {
let [actionId, label] = [actions[i], actions[i+1]];
if (actionId == 'default') {
hasDefaultAction = true;
} else {
notification.addButton(this._makeButton(actionId, label, useActionIcons), Lang.bind(this, function() {
this._emitActionInvoked(ndata.id, actionId);
}));
}
if (actions[i] == 'default')
notification.connect('clicked', Lang.bind(this,
function() {
this._emitActionInvoked(ndata.id, "default");
}));
else
notification.addButton(actions[i], actions[i + 1]);
}
}
if (hasDefaultAction) {
notification.connect('clicked', Lang.bind(this, function() {
this._emitActionInvoked(ndata.id, 'default');
}));
} else {
notification.connect('clicked', Lang.bind(this, function() {
source.open();
}));
}
switch (hints.urgency) {
case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW);
@ -546,8 +517,8 @@ const FdoNotificationDaemon = new Lang.Class({
}
});
const FdoNotificationDaemonSource = new Lang.Class({
Name: 'FdoNotificationDaemonSource',
const Source = new Lang.Class({
Name: 'NotificationDaemonSource',
Extends: MessageTray.Source,
_init: function(title, pid, sender, trayIcon, appId) {
@ -582,7 +553,7 @@ const FdoNotificationDaemonSource = new Lang.Class({
},
_createPolicy: function() {
if (this.app && this.app.get_app_info()) {
if (this.app) {
let id = this.app.get_id().replace(/\.desktop$/,'');
return new MessageTray.NotificationApplicationPolicy(id);
} else {
@ -672,7 +643,7 @@ const FdoNotificationDaemonSource = new Lang.Class({
this.parent(title);
},
open: function() {
open: function(notification) {
this.openApp();
this.destroyNonResidentNotifications();
},
@ -714,276 +685,3 @@ const FdoNotificationDaemonSource = new Lang.Class({
}
}
});
const GtkNotificationDaemonNotification = new Lang.Class({
Name: 'GtkNotificationDaemonNotification',
Extends: MessageTray.Notification,
_init: function(source, notification) {
this.parent(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
let { "title": title,
"body": body,
"icon": gicon,
"urgent": urgent,
"buttons": buttons,
"default-action": defaultAction,
"default-action-target": defaultActionTarget } = notification;
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
if (buttons) {
buttons.deep_unpack().forEach(Lang.bind(this, function(button) {
this.addAction(button.label.unpack(),
Lang.bind(this, this._onButtonClicked, button));
}));
}
this._defaultAction = defaultAction ? defaultAction.unpack() : null;
this._defaultActionTarget = defaultActionTarget;
this.update(title.unpack(), body ? body.unpack() : null,
{ gicon: gicon ? Gio.icon_deserialize(gicon) : null });
},
_activateAction: function(namespacedActionId, target) {
if (namespacedActionId) {
if (namespacedActionId.startsWith('app.')) {
let actionId = namespacedActionId.slice('app.'.length);
this.source.activateAction(actionId, target);
}
} else {
this.source.open();
}
},
_onButtonClicked: function(button) {
let { 'action': action, 'target': actionTarget } = button;
this._activateAction(action.unpack(), actionTarget);
},
_onClicked: function() {
this._activateAction(this._defaultAction, this._defaultActionTarget);
this.parent();
},
serialize: function() {
return this._serialized;
},
});
const FdoApplicationIface = '<node> \
<interface name="org.freedesktop.Application"> \
<method name="ActivateAction"> \
<arg type="s" direction="in" /> \
<arg type="av" direction="in" /> \
<arg type="a{sv}" direction="in" /> \
</method> \
<method name="Activate"> \
<arg type="a{sv}" direction="in" /> \
</method> \
</interface> \
</node>';
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
function objectPathFromAppId(appId) {
return '/' + appId.replace(/\./g, '/');
}
function getPlatformData() {
let startupId = GLib.Variant.new('s', '_TIME' + global.get_current_time());
return { "desktop-startup-id": startupId };
}
function InvalidAppError() {}
const GtkNotificationDaemonAppSource = new Lang.Class({
Name: 'GtkNotificationDaemonAppSource',
Extends: MessageTray.Source,
_init: function(appId) {
this._appId = appId;
this._objectPath = objectPathFromAppId(appId);
this._app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
if (!this._app)
throw new InvalidAppError();
this._notifications = {};
this.parent(this._app.get_name());
},
createIcon: function(size) {
return this._app.create_icon_texture(size);
},
_createPolicy: function() {
return new MessageTray.NotificationApplicationPolicy(this._appId);
},
_createApp: function() {
return new FdoApplicationProxy(Gio.DBus.session, this._appId, this._objectPath);
},
activateAction: function(actionId, target) {
let app = this._createApp();
app.ActivateActionRemote(actionId, target ? [target] : [], getPlatformData());
},
open: function() {
let app = this._createApp();
app.ActivateRemote(getPlatformData());
},
addNotification: function(notificationId, notificationParams, showBanner) {
if (this._notifications[notificationId])
this._notifications[notificationId].destroy();
let notification = new GtkNotificationDaemonNotification(this, notificationParams);
notification.connect('destroy', Lang.bind(this, function() {
delete this._notifications[notificationId];
}));
this._notifications[notificationId] = notification;
if (showBanner)
this.notify(notification);
else
this.pushNotification(notification);
},
removeNotification: function(notificationId) {
if (this._notifications[notificationId])
this._notifications[notificationId].destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
},
serialize: function() {
let notifications = [];
for (let notificationId in this._notifications) {
let notification = this._notifications[notificationId];
notifications.push([notificationId, notification.serialize()]);
}
return [this._appId, notifications];
},
});
const GtkNotificationsIface = '<node> \
<interface name="org.gtk.Notifications"> \
<method name="AddNotification"> \
<arg type="s" direction="in" /> \
<arg type="s" direction="in" /> \
<arg type="a{sv}" direction="in" /> \
</method> \
<method name="RemoveNotification"> \
<arg type="s" direction="in" /> \
<arg type="s" direction="in" /> \
</method> \
</interface> \
</node>';
const GtkNotificationDaemon = new Lang.Class({
Name: 'GtkNotificationDaemon',
_init: function() {
this._sources = {};
this._loadNotifications();
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GtkNotificationsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gtk/Notifications');
Gio.DBus.session.own_name('org.gtk.Notifications', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
_ensureAppSource: function(appId) {
if (this._sources[appId])
return this._sources[appId];
let source = new GtkNotificationDaemonAppSource(appId);
source.connect('destroy', Lang.bind(this, function() {
delete this._sources[appId];
this._saveNotifications();
}));
source.connect('count-updated', Lang.bind(this, this._saveNotifications));
Main.messageTray.add(source);
this._sources[appId] = source;
return source;
},
_loadNotifications: function() {
this._isLoading = true;
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(Lang.bind(this, function([appId, notifications]) {
if (notifications.length == 0)
return;
let source;
try {
source = this._ensureAppSource(appId);
} catch(e if e instanceof InvalidAppError) {
return;
}
notifications.forEach(function([notificationId, notification]) {
source.addNotification(notificationId, notification.deep_unpack(), false);
});
}));
}
this._isLoading = false;
},
_saveNotifications: function() {
if (this._isLoading)
return;
let sources = [];
for (let appId in this._sources) {
let source = this._sources[appId];
sources.push(source.serialize());
}
global.set_persistent_state('notifications', new GLib.Variant('a(sa(sv))', sources));
},
AddNotificationAsync: function(params, invocation) {
let [appId, notificationId, notification] = params;
let source;
try {
source = this._ensureAppSource(appId);
} catch(e if e instanceof InvalidAppError) {
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
return;
}
source.addNotification(notificationId, notification, true);
invocation.return_value(null);
},
RemoveNotificationAsync: function(params, invocation) {
let [appId, notificationId] = params;
let source = this._sources[appId];
if (source)
source.removeNotification(notificationId);
invocation.return_value(null);
},
});
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
_init: function() {
this._fdoNotificationDaemon = new FdoNotificationDaemon();
this._gtkNotificationDaemon = new GtkNotificationDaemon();
},
});

View File

@ -78,8 +78,10 @@ const ShellInfo = new Lang.Class({
}
this._undoCallback = undoCallback;
if (undoCallback)
notification.addAction(_("Undo"), Lang.bind(this, this._onUndoClicked));
if (undoCallback) {
notification.addButton('system-undo', _("Undo"));
notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked));
}
this._source.notify(notification);
}
@ -363,13 +365,11 @@ const Overview = new Lang.Class({
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
Lang.bind(this, function() {
this._windowSwitchTimeoutId = 0;
this._needsFakePointerEvent = true;
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
this._windowSwitchTimestamp);
this.hide();
this._lastHoveredWindow = null;
return false;
}));
}
@ -445,17 +445,17 @@ const Overview = new Lang.Class({
this._inDrag = false;
},
beginWindowDrag: function(clone) {
this.emit('window-drag-begin', clone);
beginWindowDrag: function(source) {
this.emit('window-drag-begin');
this._inDrag = true;
},
cancelledWindowDrag: function(clone) {
this.emit('window-drag-cancelled', clone);
cancelledWindowDrag: function(source) {
this.emit('window-drag-cancelled');
},
endWindowDrag: function(clone) {
this.emit('window-drag-end', clone);
endWindowDrag: function(source) {
this.emit('window-drag-end');
this._inDrag = false;
},

View File

@ -36,7 +36,6 @@ const SlideLayout = new Lang.Class({
_init: function(params) {
this._slideX = 1;
this._translationX = 0;
this._direction = SlideDirection.LEFT;
this.parent(params);
@ -67,9 +66,9 @@ const SlideLayout = new Lang.Class({
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0;
let actorBox = new Clutter.ActorBox();
actorBox.x1 = box.x1 + alignX + this._translationX;
actorBox.x2 = actorBox.x1 + (child.x_expand ? availWidth : natWidth);
actorBox.y1 = box.y1;
actorBox.x1 = alignX;
actorBox.x2 = actorBox.x1 + child.x_expand ? availWidth : natWidth;
actorBox.y1 = 0;
actorBox.y2 = actorBox.y1 + availHeight;
child.allocate(actorBox, flags);
@ -91,16 +90,7 @@ const SlideLayout = new Lang.Class({
get slideDirection() {
return this._direction;
},
set translationX(value) {
this._translationX = value;
this.layout_changed();
},
get translationX() {
return this._translationX;
},
}
});
const SlidingControl = new Lang.Class({
@ -109,8 +99,8 @@ const SlidingControl = new Lang.Class({
_init: function(params) {
params = Params.parse(params, { slideDirection: SlideDirection.LEFT });
this._visible = true;
this._inDrag = false;
this.visible = true;
this.inDrag = false;
this.layout = new SlideLayout();
this.layout.slideDirection = params.slideDirection;
@ -119,7 +109,6 @@ const SlidingControl = new Lang.Class({
clip_to_allocation: true });
Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing));
Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding));
Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
Main.overview.connect('item-drag-end', Lang.bind(this, this._onDragEnd));
@ -130,12 +119,12 @@ const SlidingControl = new Lang.Class({
Main.overview.connect('window-drag-end', Lang.bind(this, this._onWindowDragEnd));
},
_getSlide: function() {
getSlide: function() {
throw new Error('getSlide() must be overridden');
},
_updateSlide: function() {
Tweener.addTween(this.layout, { slideX: this._getSlide(),
updateSlide: function() {
Tweener.addTween(this.layout, { slideX: this.getSlide(),
time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' });
},
@ -162,30 +151,28 @@ const SlidingControl = new Lang.Class({
let translationEnd = 0;
let translation = this._getTranslation();
if (this._visible) {
if (this.visible) {
translationStart = translation;
} else {
translationEnd = translation;
}
if (this.layout.translationX == translationEnd)
if (this.actor.translation_x == translationEnd)
return;
this.layout.translationX = translationStart;
Tweener.addTween(this.layout, { translationX: translationEnd,
time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' });
this.actor.translation_x = translationStart;
Tweener.addTween(this.actor, { translation_x: translationEnd,
time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
_onOverviewShowing: function() {
this._visible = true;
this.layout.slideX = this._getSlide();
this.layout.translationX = this._getTranslation();
this.slideIn();
},
_onOverviewHiding: function() {
this.slideOut();
// reset any translation and make sure the actor is visible when
// entering the overview
this.visible = true;
this.layout.slideX = this.getSlide();
this.actor.translation_x = 0;
},
_onWindowDragBegin: function() {
@ -197,14 +184,14 @@ const SlidingControl = new Lang.Class({
},
_onDragBegin: function() {
this._inDrag = true;
this.layout.translationX = 0;
this._updateSlide();
this.inDrag = true;
this.actor.translation_x = 0;
this.updateSlide();
},
_onDragEnd: function() {
this._inDrag = false;
this._updateSlide();
this.inDrag = false;
this.updateSlide();
},
fadeIn: function() {
@ -222,13 +209,13 @@ const SlidingControl = new Lang.Class({
},
slideIn: function() {
this._visible = true;
this.visible = true;
this._updateTranslation();
// we will update slideX and the translation from pageEmpty
},
slideOut: function() {
this._visible = false;
this.visible = false;
this._updateTranslation();
// we will update slideX from pageEmpty
},
@ -238,7 +225,7 @@ const SlidingControl = new Lang.Class({
// selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called,
// changing the visiblity
this.layout.slideX = this._getSlide();
this.layout.slideX = this.getSlide();
this._updateTranslation();
}
});
@ -257,15 +244,16 @@ const ThumbnailsSlider = new Lang.Class({
this.actor.track_hover = true;
this.actor.add_actor(this._thumbnailsBox.actor);
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateSlide));
this.actor.connect('notify::hover', Lang.bind(this, this._updateSlide));
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.updateSlide));
Main.overview.connect('hiding', Lang.bind(this, this.slideOut));
this.actor.connect('notify::hover', Lang.bind(this, this.updateSlide));
this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
},
_getAlwaysZoomOut: function() {
// Always show the pager when hover, during a drag, or if workspaces are
// actually used, e.g. there are windows on more than one
let alwaysZoomOut = this.actor.hover || this._inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2;
let alwaysZoomOut = this.actor.hover || this.inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2;
if (!alwaysZoomOut) {
let monitors = Main.layoutManager.monitors;
@ -285,13 +273,20 @@ const ThumbnailsSlider = new Lang.Class({
return alwaysZoomOut;
},
_onOverviewShowing: function() {
this.visible = true;
this.layout.slideX = this.getSlide();
this.actor.translation_x = this._getTranslation();
this.slideIn();
},
getNonExpandedWidth: function() {
let child = this.actor.get_first_child();
return child.get_theme_node().get_length('visible-width');
},
_getSlide: function() {
if (!this._visible)
getSlide: function() {
if (!this.visible)
return 0;
let alwaysZoomOut = this._getAlwaysZoomOut();
@ -328,22 +323,29 @@ const DashSlider = new Lang.Class({
// available allocation
this._dash.actor.x_expand = true;
this.actor.x_expand = true;
this.actor.x_align = Clutter.ActorAlign.START;
this.actor.y_expand = true;
this.actor.add_actor(this._dash.actor);
this._dash.connect('icon-size-changed', Lang.bind(this, this._updateSlide));
this._dash.connect('icon-size-changed', Lang.bind(this, this.updateSlide));
Main.overview.connect('hiding', Lang.bind(this, this.slideOut));
},
_getSlide: function() {
if (this._visible || this._inDrag)
getSlide: function() {
if (this.visible || this.inDrag)
return 1;
else
return 0;
},
_onOverviewShowing: function() {
this.visible = true;
this.layout.slideX = this.getSlide();
this.actor.translation_x = this._getTranslation();
this.slideIn();
},
_onWindowDragBegin: function() {
this.fadeHalf();
},

View File

@ -7,63 +7,58 @@ const Lang = imports.lang;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const FileUtils = imports.misc.fileUtils;
const Search = imports.ui.search;
const KEY_FILE_GROUP = 'Shell Search Provider';
const SearchProviderIface = '<node> \
<interface name="org.gnome.Shell.SearchProvider"> \
<method name="GetInitialResultSet"> \
<arg type="as" direction="in" /> \
<arg type="as" direction="out" /> \
</method> \
<method name="GetSubsearchResultSet"> \
<arg type="as" direction="in" /> \
<arg type="as" direction="in" /> \
<arg type="as" direction="out" /> \
</method> \
<method name="GetResultMetas"> \
<arg type="as" direction="in" /> \
<arg type="aa{sv}" direction="out" /> \
</method> \
<method name="ActivateResult"> \
<arg type="s" direction="in" /> \
</method> \
</interface> \
</node>';
const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
<method name="GetInitialResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetSubsearchResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetResultMetas">
<arg type="as" direction="in" />
<arg type="aa{sv}" direction="out" />
</method>
<method name="ActivateResult">
<arg type="s" direction="in" />
</method>
</interface>;
const SearchProvider2Iface = '<node> \
<interface name="org.gnome.Shell.SearchProvider2"> \
<method name="GetInitialResultSet"> \
<arg type="as" direction="in" /> \
<arg type="as" direction="out" /> \
</method> \
<method name="GetSubsearchResultSet"> \
<arg type="as" direction="in" /> \
<arg type="as" direction="in" /> \
<arg type="as" direction="out" /> \
</method> \
<method name="GetResultMetas"> \
<arg type="as" direction="in" /> \
<arg type="aa{sv}" direction="out" /> \
</method> \
<method name="ActivateResult"> \
<arg type="s" direction="in" /> \
<arg type="as" direction="in" /> \
<arg type="u" direction="in" /> \
</method> \
<method name="LaunchSearch"> \
<arg type="as" direction="in" /> \
<arg type="u" direction="in" /> \
</method> \
</interface> \
</node>';
const SearchProvider2Iface = <interface name="org.gnome.Shell.SearchProvider2">
<method name="GetInitialResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetSubsearchResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetResultMetas">
<arg type="as" direction="in" />
<arg type="aa{sv}" direction="out" />
</method>
<method name="ActivateResult">
<arg type="s" direction="in" />
<arg type="as" direction="in" />
<arg type="u" direction="in" />
</method>
<method name="LaunchSearch">
<arg type="as" direction="in" />
<arg type="u" direction="in" />
</method>
</interface>;
var SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
var SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
function loadRemoteSearchProviders(callback) {
function loadRemoteSearchProviders(addProviderCallback) {
let objectPaths = {};
let loadedProviders = [];
@ -117,25 +112,30 @@ function loadRemoteSearchProviders(callback) {
}
}
let dataDirs = GLib.get_system_data_dirs();
dataDirs.forEach(function(dataDir) {
let path = GLib.build_filenamev([dataDir, 'gnome-shell', 'search-providers']);
let dir = Gio.File.new_for_path(path);
let fileEnum;
try {
fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
fileEnum = null;
}
if (fileEnum != null) {
let info;
while ((info = fileEnum.next_file(null)))
loadRemoteSearchProvider(fileEnum.get_child(info));
}
});
let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
if (searchSettings.get_boolean('disable-external')) {
callback([]);
return;
}
FileUtils.collectFromDatadirs('search-providers', false, loadRemoteSearchProvider);
let sortOrder = searchSettings.get_strv('sort-order');
// Special case gnome-control-center to be always active and always first
sortOrder.unshift('gnome-control-center.desktop');
loadedProviders = loadedProviders.filter(function(provider) {
let appId = provider.appInfo.get_id();
let disabled = searchSettings.get_strv('disabled');
return disabled.indexOf(appId) == -1;
});
loadedProviders.sort(function(providerA, providerB) {
let idxA, idxB;
let appIdA, appIdB;
@ -166,28 +166,28 @@ function loadRemoteSearchProviders(callback) {
return (idxA - idxB);
});
callback(loadedProviders);
loadedProviders.forEach(addProviderCallback);
}
const RemoteSearchProvider = new Lang.Class({
Name: 'RemoteSearchProvider',
_init: function(appInfo, dbusName, dbusPath, proxyInfo) {
if (!proxyInfo)
proxyInfo = SearchProviderProxyInfo;
_init: function(appInfo, dbusName, dbusPath, proxyType) {
if (!proxyType)
proxyType = SearchProviderProxy;
this.proxy = new Gio.DBusProxy({ g_bus_type: Gio.BusType.SESSION,
g_name: dbusName,
g_object_path: dbusPath,
g_interface_info: proxyInfo,
g_interface_name: proxyInfo.name,
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START_AT_CONSTRUCTION |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
this.proxy = new proxyType(Gio.DBus.session,
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
this.appInfo = appInfo;
this.id = appInfo.get_id();
this.isRemoteProvider = true;
this._cancellable = new Gio.Cancellable();
},
_onProxyConstructed: function(proxy) {
// Do nothing
},
createIcon: function(size, meta) {
@ -217,33 +217,40 @@ const RemoteSearchProvider = new Lang.Class({
return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
},
_getResultsFinished: function(results, error, callback) {
if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
callback([]);
_getResultsFinished: function(results, error) {
if (error)
return;
this.searchSystem.setResults(this, results[0]);
},
getInitialResultSet: function(terms) {
this._cancellable.cancel();
this._cancellable.reset();
try {
this.proxy.GetInitialResultSetRemote(terms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString()));
this.searchSystem.setResults(this, []);
}
callback(results[0]);
},
getInitialResultSet: function(terms, callback, cancellable) {
this.proxy.GetInitialResultSetRemote(terms,
Lang.bind(this, this._getResultsFinished, callback),
cancellable);
},
getSubsearchResultSet: function(previousResults, newTerms, callback, cancellable) {
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
Lang.bind(this, this._getResultsFinished, callback),
cancellable);
getSubsearchResultSet: function(previousResults, newTerms) {
this._cancellable.cancel();
this._cancellable.reset();
try {
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString()));
this.searchSystem.setResults(this, []);
}
},
_getResultMetasFinished: function(results, error, callback) {
if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('Received error from DBus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
callback([]);
return;
}
@ -265,10 +272,17 @@ const RemoteSearchProvider = new Lang.Class({
callback(resultMetas);
},
getResultMetas: function(ids, callback, cancellable) {
this.proxy.GetResultMetasRemote(ids,
Lang.bind(this, this._getResultMetasFinished, callback),
cancellable);
getResultMetas: function(ids, callback) {
this._cancellable.cancel();
this._cancellable.reset();
try {
this.proxy.GetResultMetasRemote(ids,
Lang.bind(this, this._getResultMetasFinished, callback),
this._cancellable);
} catch(e) {
log('Error calling GetResultMetas for provider %s: %s'.format(this.id, e.toString()));
callback([]);
}
},
activateResult: function(id) {
@ -288,7 +302,7 @@ const RemoteSearchProvider2 = new Lang.Class({
Extends: RemoteSearchProvider,
_init: function(appInfo, dbusName, dbusPath) {
this.parent(appInfo, dbusName, dbusPath, SearchProvider2ProxyInfo);
this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy);
this.canLaunchSearch = true;
},

View File

@ -198,8 +198,8 @@ const NotificationsBox = new Lang.Class({
let body = '';
if (n.bannerBodyText) {
body = n.bannerBodyMarkup ? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
body = n.bannerBodyMarkup ? n.bannerBodyText :
GLib.markup_escape_text(n.bannerBodyMarkup, -1);
}
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });

View File

@ -9,29 +9,27 @@ const Signals = imports.signals;
const Hash = imports.misc.hash;
const Main = imports.ui.main;
const ScreencastIface = '<node> \
<interface name="org.gnome.Shell.Screencast"> \
<method name="Screencast"> \
<arg type="s" direction="in" name="file_template"/> \
<arg type="a{sv}" direction="in" name="options"/> \
<arg type="b" direction="out" name="success"/> \
<arg type="s" direction="out" name="filename_used"/> \
</method> \
<method name="ScreencastArea"> \
<arg type="i" direction="in" name="x"/> \
<arg type="i" direction="in" name="y"/> \
<arg type="i" direction="in" name="width"/> \
<arg type="i" direction="in" name="height"/> \
<arg type="s" direction="in" name="file_template"/> \
<arg type="a{sv}" direction="in" name="options"/> \
<arg type="b" direction="out" name="success"/> \
<arg type="s" direction="out" name="filename_used"/> \
</method> \
<method name="StopScreencast"> \
<arg type="b" direction="out" name="success"/> \
</method> \
</interface> \
</node>';
const ScreencastIface = <interface name="org.gnome.Shell.Screencast">
<method name="Screencast">
<arg type="s" direction="in" name="file_template"/>
<arg type="a{sv}" direction="in" name="options"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="ScreencastArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="s" direction="in" name="file_template"/>
<arg type="a{sv}" direction="in" name="options"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="StopScreencast">
<arg type="b" direction="out" name="success"/>
</method>
</interface>;
const ScreencastService = new Lang.Class({
Name: 'ScreencastService',

View File

@ -15,47 +15,45 @@ const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const ScreenshotIface = '<node> \
<interface name="org.gnome.Shell.Screenshot"> \
<method name="ScreenshotArea"> \
<arg type="i" direction="in" name="x"/> \
<arg type="i" direction="in" name="y"/> \
<arg type="i" direction="in" name="width"/> \
<arg type="i" direction="in" name="height"/> \
<arg type="b" direction="in" name="flash"/> \
<arg type="s" direction="in" name="filename"/> \
<arg type="b" direction="out" name="success"/> \
<arg type="s" direction="out" name="filename_used"/> \
</method> \
<method name="ScreenshotWindow"> \
<arg type="b" direction="in" name="include_frame"/> \
<arg type="b" direction="in" name="include_cursor"/> \
<arg type="b" direction="in" name="flash"/> \
<arg type="s" direction="in" name="filename"/> \
<arg type="b" direction="out" name="success"/> \
<arg type="s" direction="out" name="filename_used"/> \
</method> \
<method name="Screenshot"> \
<arg type="b" direction="in" name="include_cursor"/> \
<arg type="b" direction="in" name="flash"/> \
<arg type="s" direction="in" name="filename"/> \
<arg type="b" direction="out" name="success"/> \
<arg type="s" direction="out" name="filename_used"/> \
</method> \
<method name="SelectArea"> \
<arg type="i" direction="out" name="x"/> \
<arg type="i" direction="out" name="y"/> \
<arg type="i" direction="out" name="width"/> \
<arg type="i" direction="out" name="height"/> \
</method> \
<method name="FlashArea"> \
<arg type="i" direction="in" name="x"/> \
<arg type="i" direction="in" name="y"/> \
<arg type="i" direction="in" name="width"/> \
<arg type="i" direction="in" name="height"/> \
</method> \
</interface> \
</node>';
const ScreenshotIface = <interface name="org.gnome.Shell.Screenshot">
<method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="ScreenshotWindow">
<arg type="b" direction="in" name="include_frame"/>
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="Screenshot">
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="SelectArea">
<arg type="i" direction="out" name="x"/>
<arg type="i" direction="out" name="y"/>
<arg type="i" direction="out" name="width"/>
<arg type="i" direction="out" name="height"/>
</method>
<method name="FlashArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
</method>
</interface>;
const ScreenshotService = new Lang.Class({
Name: 'ScreenshotService',

View File

@ -69,18 +69,16 @@ function waitLeisure() {
};
}
const PerfHelperIface = '<node> \
<interface name="org.gnome.Shell.PerfHelper"> \
<method name="CreateWindow"> \
<arg type="i" direction="in" /> \
<arg type="i" direction="in" /> \
<arg type="b" direction="in" /> \
<arg type="b" direction="in" /> \
</method> \
<method name="WaitWindows" /> \
<method name="DestroyWindows" /> \
</interface> \
</node>';
const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
<method name="CreateWindow">
<arg type="i" direction="in" />
<arg type="i" direction="in" />
<arg type="b" direction="in" />
<arg type="b" direction="in" />
</method>
<method name="WaitWindows" />
<method name="DestroyWindows" />
</interface>;
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
function PerfHelper() {

View File

@ -1,706 +1,105 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const AppDisplay = imports.ui.appDisplay;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const RemoteSearch = imports.ui.remoteSearch;
const Separator = imports.ui.separator;
const Util = imports.misc.util;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const SearchSystem = new Lang.Class({
Name: 'SearchSystem',
_init: function() {
this._providers = [];
this._registerProvider(new AppDisplay.AppSearchProvider());
this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
this._reloadRemoteProviders();
this._cancellable = new Gio.Cancellable();
this._remoteProviders = [];
this.reset();
},
addProvider: function(provider) {
registerProvider: function (provider) {
provider.searchSystem = this;
this._providers.push(provider);
this.emit('providers-changed');
if (provider.isRemoteProvider)
this._remoteProviders.push(provider);
},
_reloadRemoteProviders: function() {
let remoteProviders = this._providers.filter(function(provider) {
return provider.isRemoteProvider;
});
remoteProviders.forEach(Lang.bind(this, function(provider) {
this._unregisterProvider(provider);
}));
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, function(providers) {
providers.forEach(Lang.bind(this, this._registerProvider));
}));
this.emit('providers-changed');
},
_registerProvider: function (provider) {
this._providers.push(provider);
},
_unregisterProvider: function (provider) {
unregisterProvider: function (provider) {
let index = this._providers.indexOf(provider);
if (index == -1)
return;
provider.searchSystem = null;
this._providers.splice(index, 1);
let remoteIndex = this._remoteProviders.indexOf(provider);
if (remoteIndex != -1)
this._remoteProviders.splice(remoteIndex, 1);
},
getProviders: function() {
return this._providers;
},
getRemoteProviders: function() {
return this._remoteProviders;
},
getTerms: function() {
return this._terms;
return this._previousTerms;
},
reset: function() {
this._terms = [];
this._results = {};
this._previousTerms = [];
this._previousResults = [];
},
_gotResults: function(results, provider) {
this._results[provider.id] = results;
this.emit('search-updated', provider, results);
setResults: function(provider, results) {
let i = this._providers.indexOf(provider);
if (i == -1)
return;
this._previousResults[i] = [provider, results];
this.emit('search-updated', this._previousResults[i]);
},
setTerms: function(terms) {
this._cancellable.cancel();
this._cancellable.reset();
let previousResults = this._results;
let previousTerms = this._terms;
this.reset();
updateSearchResults: function(terms) {
if (!terms)
return;
let searchString = terms.join(' ');
let previousSearchString = previousTerms.join(' ');
let previousSearchString = this._previousTerms.join(' ');
if (searchString == previousSearchString)
return;
let isSubSearch = false;
if (previousTerms.length > 0)
if (this._previousTerms.length > 0)
isSubSearch = searchString.indexOf(previousSearchString) == 0;
this._terms = terms;
let previousResultsArr = this._previousResults;
this._providers.forEach(Lang.bind(this, function(provider) {
let previousProviderResults = previousResults[provider.id];
if (isSubSearch && previousProviderResults)
provider.getSubsearchResultSet(previousProviderResults, terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
else
provider.getInitialResultSet(terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
}));
let results = [];
this._previousTerms = terms;
this._previousResults = results;
if (isSubSearch) {
for (let i = 0; i < this._providers.length; i++) {
let [provider, previousResults] = previousResultsArr[i];
try {
results.push([provider, []]);
provider.getSubsearchResultSet(previousResults, terms);
} catch (error) {
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
}
}
} else {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
try {
results.push([provider, []]);
provider.getInitialResultSet(terms);
} catch (error) {
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
}
}
}
}
});
Signals.addSignalMethods(SearchSystem.prototype);
const MaxWidthBin = new Lang.Class({
Name: 'MaxWidthBin',
Extends: St.Bin,
vfunc_allocate: function(box, flags) {
let themeNode = this.get_theme_node();
let maxWidth = themeNode.get_max_width();
let availWidth = box.x2 - box.x1;
let adjustedBox = box;
if (availWidth > maxWidth) {
let excessWidth = availWidth - maxWidth;
adjustedBox.x1 += Math.floor(excessWidth / 2);
adjustedBox.x2 -= Math.floor(excessWidth / 2);
}
this.parent(adjustedBox, flags);
}
});
const SearchResult = new Lang.Class({
Name: 'SearchResult',
_init: function(provider, metaInfo) {
this.provider = provider;
this.metaInfo = metaInfo;
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('clicked', Lang.bind(this, this.activate));
},
activate: function() {
this.emit('activate', this.metaInfo.id);
},
setSelected: function(selected) {
if (selected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
}
});
Signals.addSignalMethods(SearchResult.prototype);
const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
if (icon) {
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let title = new St.Label({ style_class: 'list-search-result-title',
text: this.metaInfo['name'] })
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.label_actor = title;
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description' });
description.clutter_text.set_markup(this.metaInfo['description']);
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
}
}
});
const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
this.actor.style_class = 'grid-search-result';
let content = provider.createResultObject(metaInfo);
let dragSource = null;
if (content == null) {
let actor = new St.Bin();
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
actor.set_child(icon.actor);
actor.label_actor = icon.label;
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
}
this.actor.set_child(content.actor);
this.actor.label_actor = content.actor.label_actor;
this.icon = content.icon;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
if (!dragSource)
// not exactly right, but alignment problems are hard to notice
dragSource = content;
this._dragActorSource = dragSource;
},
getDragActorSource: function() {
return this._dragActorSource;
},
getDragActor: function() {
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
},
shellWorkspaceLaunch: function(params) {
if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id, params);
else
this.provider.activateResult(this.metaInfo.id, this.terms);
}
});
const SearchResultsBase = new Lang.Class({
Name: 'SearchResultsBase',
_init: function(provider) {
this.provider = provider;
this._terms = [];
this.actor = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
this._resultDisplayBin = new St.Bin({ x_fill: true,
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
this.actor.add(separator.actor);
this._resultDisplays = {};
this._cancellable = new Gio.Cancellable();
},
destroy: function() {
this.actor.destroy();
this._terms = [];
},
_clearResultDisplay: function() {
},
clear: function() {
this._resultDisplays = {};
this._clearResultDisplay();
this.actor.hide();
},
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor);
},
_activateResult: function(result, id) {
this.provider.activateResult(id, this._terms);
Main.overview.toggle();
},
_setMoreIconVisible: function(visible) {
},
_ensureResultActors: function(results, callback) {
let metasNeeded = results.filter(Lang.bind(this, function(resultId) {
return this._resultDisplays[resultId] === undefined;
}));
if (metasNeeded.length === 0) {
callback();
} else {
this._cancellable.cancel();
this._cancellable.reset();
this.provider.getResultMetas(metasNeeded, Lang.bind(this, function(metas) {
metasNeeded.forEach(Lang.bind(this, function(resultId, i) {
let meta = metas[i];
let display = this._createResultDisplay(meta);
display.connect('activate', Lang.bind(this, this._activateResult));
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._resultDisplays[resultId] = display;
}));
callback();
}), this._cancellable);
}
},
updateSearch: function(providerResults, terms, callback) {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
let results = this.provider.filterResults(providerResults, maxResults);
let hasMoreResults = results.length < providerResults.length;
this._ensureResultActors(results, Lang.bind(this, function() {
this._clearResultDisplay();
// To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the
// content while filling in the results.
this.actor.hide();
this._clearResultDisplay();
results.forEach(Lang.bind(this, function(resultId) {
this._addItem(this._resultDisplays[resultId]);
}));
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
this.actor.show();
callback();
}));
}
}
});
const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
function() {
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this._container.add(this.providerIcon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this._container.add(this._content, { expand: true });
this._resultDisplayBin.set_child(this._container);
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = true;
},
_getMaxDisplayedResults: function() {
return MAX_LIST_SEARCH_RESULTS_ROWS;
},
_clearResultDisplay: function () {
this._content.remove_all_children();
},
_createResultDisplay: function(meta) {
return new ListSearchResult(this.provider, meta);
},
_addItem: function(display) {
this._content.add_actor(display.actor);
},
getFirstResult: function() {
if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(ListSearchResults.prototype);
const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._bin.set_child(this._grid.actor);
this._resultDisplayBin.set_child(this._bin);
},
_getMaxDisplayedResults: function() {
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i]);
display.connect('activate', Lang.bind(this, this._activateResult));
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display);
}
},
_clearResultDisplay: function () {
this._grid.removeAll();
},
_createResultDisplay: function(meta) {
return new GridSearchResult(this.provider, meta);
},
_addItem: function(display) {
this._grid.addItem(display);
},
getFirstResult: function() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(GridSearchResults.prototype);
const SearchResults = new Lang.Class({
Name: 'SearchResults',
_init: function() {
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true });
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
x_fill: true,
y_fill: true,
child: this._content });
let scrollChild = new St.BoxLayout();
scrollChild.add(this._contentBin, { expand: true });
this._scrollView = new St.ScrollView({ x_fill: true,
y_fill: false,
overlay_scrollbars: true,
style_class: 'search-display vfade' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.add_actor(scrollChild);
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this._scrollView.add_action(action);
this.actor.add(this._scrollView, { x_fill: true,
y_fill: true,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._content.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._highlightDefault = false;
this._defaultResult = null;
this._searchSystem = new SearchSystem();
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
this._searchSystem.connect('providers-changed', Lang.bind(this, this._updateProviderDisplays));
this._updateProviderDisplays();
},
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
_keyFocusIn: function(provider, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
_ensureProviderDisplay: function(provider) {
if (provider.display)
return;
let providerDisplay;
if (provider.appInfo)
providerDisplay = new ListSearchResults(provider);
else
providerDisplay = new GridSearchResults(provider);
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._content.add(providerDisplay.actor);
provider.display = providerDisplay;
},
_updateProviderDisplays: function() {
this._searchSystem.getProviders().forEach(Lang.bind(this, this._ensureProviderDisplay));
},
_clearDisplay: function() {
this._searchSystem.getProviders().forEach(function(provider) {
provider.display.clear();
});
},
reset: function() {
this._searchSystem.reset();
this._statusBin.hide();
this._clearDisplay();
this._defaultResult = null;
},
startingSearch: function() {
this.reset();
this._statusText.set_text(_("Searching…"));
this._statusBin.show();
},
setTerms: function(terms) {
this._searchSystem.setTerms(terms);
},
_maybeSetInitialSelection: function() {
let newDefaultResult = null;
let providers = this._searchSystem.getProviders();
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
let display = provider.display;
if (!display.actor.visible)
continue;
let firstResult = display.getFirstResult();
if (firstResult) {
newDefaultResult = firstResult;
break; // select this one!
}
}
if (newDefaultResult != this._defaultResult) {
if (this._defaultResult)
this._defaultResult.setSelected(false);
if (newDefaultResult)
newDefaultResult.setSelected(this._highlightDefault);
this._defaultResult = newDefaultResult;
}
},
_updateStatusText: function () {
let haveResults = this._searchSystem.getProviders().some(function(provider) {
let display = provider.display;
return (display.getFirstResult() != null);
});
if (!haveResults) {
this._statusText.set_text(_("No results."));
this._statusBin.show();
} else {
this._statusBin.hide();
}
},
_updateResults: function(searchSystem, provider, results) {
let terms = searchSystem.getTerms();
let display = provider.display;
display.updateSearch(results, terms, Lang.bind(this, function() {
this._maybeSetInitialSelection();
this._updateStatusText();
}));
},
activateDefault: function() {
if (this._defaultResult)
this._defaultResult.activate();
},
highlightDefault: function(highlight) {
this._highlightDefault = highlight;
if (this._defaultResult)
this._defaultResult.setSelected(highlight);
},
navigateFocus: function(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
direction == (rtl ? Gtk.DirectionType.RIGHT
: Gtk.DirectionType.LEFT) ||
direction == Gtk.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false);
return;
}
let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false);
}
});
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
_init: function(provider) {
this.provider = provider;
this.parent({ style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
}
});

567
js/ui/searchDisplay.js Normal file
View File

@ -0,0 +1,567 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const Separator = imports.ui.separator;
const Search = imports.ui.search;
const Util = imports.misc.util;
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const MaxWidthBin = new Lang.Class({
Name: 'MaxWidthBin',
Extends: St.Bin,
vfunc_allocate: function(box, flags) {
let themeNode = this.get_theme_node();
let maxWidth = themeNode.get_max_width();
let availWidth = box.x2 - box.x1;
let adjustedBox = box;
if (availWidth > maxWidth) {
let excessWidth = availWidth - maxWidth;
adjustedBox.x1 += Math.floor(excessWidth / 2);
adjustedBox.x2 -= Math.floor(excessWidth / 2);
}
this.parent(adjustedBox, flags);
}
});
const SearchResult = new Lang.Class({
Name: 'SearchResult',
_init: function(provider, metaInfo, terms) {
this.provider = provider;
this.metaInfo = metaInfo;
this.terms = terms;
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('clicked', Lang.bind(this, this.activate));
},
activate: function() {
this.provider.activateResult(this.metaInfo.id, this.terms);
Main.overview.toggle();
},
setSelected: function(selected) {
if (selected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
}
});
const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
_init: function(provider, metaInfo, terms) {
this.parent(provider, metaInfo, terms);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
if (icon) {
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let title = new St.Label({ style_class: 'list-search-result-title',
text: this.metaInfo['name'] })
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.label_actor = title;
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description' });
description.clutter_text.set_markup(this.metaInfo['description']);
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
}
}
});
const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo, terms) {
this.parent(provider, metaInfo, terms);
this.actor.style_class = 'grid-search-result';
let content = provider.createResultObject(metaInfo, terms);
let dragSource = null;
if (content == null) {
let actor = new St.Bin();
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
actor.set_child(icon.actor);
actor.label_actor = icon.label;
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
}
this.actor.set_child(content.actor);
this.actor.label_actor = content.actor.label_actor;
this.icon = content.icon;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
if (!dragSource)
// not exactly right, but alignment problems are hard to notice
dragSource = content;
this._dragActorSource = dragSource;
},
getDragActorSource: function() {
return this._dragActorSource;
},
getDragActor: function() {
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
},
shellWorkspaceLaunch: function(params) {
if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id, params);
else
this.provider.activateResult(this.metaInfo.id, this.terms);
}
});
const SearchResultsBase = new Lang.Class({
Name: 'SearchResultsBase',
_init: function(provider) {
this.provider = provider;
this._terms = [];
this.actor = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
this._resultDisplayBin = new St.Bin({ x_fill: true,
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
this.actor.add(separator.actor);
},
destroy: function() {
this.actor.destroy();
this._terms = [];
},
_clearResultDisplay: function() {
},
clear: function() {
this._clearResultDisplay();
this.actor.hide();
},
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor);
},
_setMoreIconVisible: function(visible) {
},
updateSearch: function(providerResults, terms, callback) {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
let results = this.provider.filterResults(providerResults, maxResults);
let hasMoreResults = results.length < providerResults.length;
this.provider.getResultMetas(results, Lang.bind(this, function(metas) {
this.clear();
// To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the
// content while filling in the results.
this.actor.hide();
this._clearResultDisplay();
this._renderResults(metas);
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
this.actor.show();
callback();
}));
}
}
});
const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
function() {
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this._container.add(this.providerIcon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this._container.add(this._content, { expand: true });
this._resultDisplayBin.set_child(this._container);
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = true;
},
_getMaxDisplayedResults: function() {
return MAX_LIST_SEARCH_RESULTS_ROWS;
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new ListSearchResult(this.provider, metas[i], this._terms);
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._content.add_actor(display.actor);
}
},
_clearResultDisplay: function () {
this._content.destroy_all_children();
},
getFirstResult: function() {
if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(ListSearchResults.prototype);
const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._bin.set_child(this._grid.actor);
this._resultDisplayBin.set_child(this._bin);
},
_getMaxDisplayedResults: function() {
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i], this._terms);
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display);
}
},
_clearResultDisplay: function () {
this._grid.removeAll();
},
getFirstResult: function() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(GridSearchResults.prototype);
const SearchResults = new Lang.Class({
Name: 'SearchResults',
_init: function(searchSystem) {
this._searchSystem = searchSystem;
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true });
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
x_fill: true,
y_fill: true,
child: this._content });
let scrollChild = new St.BoxLayout();
scrollChild.add(this._contentBin, { expand: true });
this._scrollView = new St.ScrollView({ x_fill: true,
y_fill: false,
overlay_scrollbars: true,
style_class: 'search-display vfade' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.add_actor(scrollChild);
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this._scrollView.add_action(action);
this.actor.add(this._scrollView, { x_fill: true,
y_fill: true,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._content.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._providers = this._searchSystem.getProviders();
this._providerDisplays = {};
for (let i = 0; i < this._providers.length; i++) {
this.createProviderDisplay(this._providers[i]);
}
this._highlightDefault = false;
this._defaultResult = null;
},
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
_keyFocusIn: function(provider, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
createProviderDisplay: function(provider) {
let providerDisplay = null;
if (provider.appInfo) {
providerDisplay = new ListSearchResults(provider);
} else {
providerDisplay = new GridSearchResults(provider);
}
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._providerDisplays[provider.id] = providerDisplay;
this._content.add(providerDisplay.actor);
},
destroyProviderDisplay: function(provider) {
this._providerDisplays[provider.id].destroy();
delete this._providerDisplays[provider.id];
},
_clearDisplay: function() {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let providerDisplay = this._providerDisplays[provider.id];
providerDisplay.clear();
}
},
reset: function() {
this._searchSystem.reset();
this._statusBin.hide();
this._clearDisplay();
this._defaultResult = null;
},
startingSearch: function() {
this.reset();
this._statusText.set_text(_("Searching…"));
this._statusBin.show();
},
_maybeSetInitialSelection: function() {
let newDefaultResult = null;
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let display = this._providerDisplays[provider.id];
if (!display.actor.visible)
continue;
let firstResult = display.getFirstResult();
if (firstResult) {
newDefaultResult = firstResult;
break; // select this one!
}
}
if (newDefaultResult != this._defaultResult) {
if (this._defaultResult)
this._defaultResult.setSelected(false);
if (newDefaultResult)
newDefaultResult.setSelected(this._highlightDefault);
this._defaultResult = newDefaultResult;
}
},
_updateStatusText: function () {
let haveResults = false;
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let display = this._providerDisplays[provider.id];
if (display.getFirstResult()) {
haveResults = true;
break;
}
}
if (!haveResults) {
this._statusText.set_text(_("No results."));
this._statusBin.show();
} else {
this._statusBin.hide();
}
},
_updateResults: function(searchSystem, results) {
let terms = searchSystem.getTerms();
let [provider, providerResults] = results;
let display = this._providerDisplays[provider.id];
display.updateSearch(providerResults, terms, Lang.bind(this, function() {
this._maybeSetInitialSelection();
this._updateStatusText();
}));
},
activateDefault: function() {
if (this._defaultResult)
this._defaultResult.activate();
},
highlightDefault: function(highlight) {
this._highlightDefault = highlight;
if (this._defaultResult)
this._defaultResult.setSelected(highlight);
},
navigateFocus: function(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
direction == (rtl ? Gtk.DirectionType.RIGHT
: Gtk.DirectionType.LEFT) ||
direction == Gtk.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false);
return;
}
let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false);
}
});
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
_init: function(provider) {
this.provider = provider;
this.parent({ style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
}
});

View File

@ -102,12 +102,19 @@ const _modes = {
}
};
function _loadMode(file, info) {
function _getModes(modesLoadedCallback) {
FileUtils.collectFromDatadirsAsync('modes',
{ processFile: _loadMode,
loadedCallback: modesLoadedCallback,
data: _modes });
}
function _loadMode(file, info, loadedData) {
let name = info.get_name();
let suffix = name.indexOf('.json');
let modeName = suffix == -1 ? name : name.slice(name, suffix);
if (_modes.hasOwnProperty(modeName))
if (loadedData.hasOwnProperty(modeName))
return;
let fileContent, success, tag, newMode;
@ -118,23 +125,18 @@ function _loadMode(file, info) {
return;
}
_modes[modeName] = {};
loadedData[modeName] = {};
let propBlacklist = ['unlockDialog'];
for (let prop in loadedData[DEFAULT_MODE]) {
if (newMode[prop] !== undefined &&
propBlacklist.indexOf(prop) == -1)
loadedData[modeName][prop] = newMode[prop];
loadedData[modeName][prop]= newMode[prop];
}
_modes[modeName]['isPrimary'] = true;
}
function _getModes() {
FileUtils.collectFromDatadirs('modes', false, _loadMode);
loadedData[modeName]['isPrimary'] = true;
}
function listModes() {
let modes = _getModes();
modes.forEach(function() {
_getModes(function(modes) {
let names = Object.getOwnPropertyNames(modes);
for (let i = 0; i < names.length; i++)
if (_modes[names[i]].isPrimary)
@ -147,12 +149,17 @@ function listModes() {
const SessionMode = new Lang.Class({
Name: 'SessionMode',
_init: function() {
let isPrimary = (_modes[global.session_mode] &&
_modes[global.session_mode].isPrimary);
let mode = isPrimary ? global.session_mode : 'user';
this._modeStack = [mode];
this._sync();
init: function() {
_getModes(Lang.bind(this, function(modes) {
this._modes = modes;
let primary = modes[global.session_mode] &&
modes[global.session_mode].isPrimary;
let mode = primary ? global.session_mode : 'user';
this._modeStack = [mode];
this._sync();
this.emit('sessions-loaded');
}));
},
pushMode: function(mode) {
@ -179,13 +186,13 @@ const SessionMode = new Lang.Class({
},
_sync: function() {
let params = _modes[this.currentMode];
let params = this._modes[this.currentMode];
let defaults;
if (params.parentMode)
defaults = Params.parse(_modes[params.parentMode],
_modes[DEFAULT_MODE]);
defaults = Params.parse(this._modes[params.parentMode],
this._modes[DEFAULT_MODE]);
else
defaults = _modes[DEFAULT_MODE];
defaults = this._modes[DEFAULT_MODE];
params = Params.parse(params, defaults);
// A simplified version of Lang.copyProperties, handles

View File

@ -15,63 +15,59 @@ const Main = imports.ui.main;
const Screenshot = imports.ui.screenshot;
const ViewSelector = imports.ui.viewSelector;
const GnomeShellIface = '<node> \
<interface name="org.gnome.Shell"> \
<method name="Eval"> \
<arg type="s" direction="in" name="script" /> \
<arg type="b" direction="out" name="success" /> \
<arg type="s" direction="out" name="result" /> \
</method> \
<method name="FocusSearch"/> \
<method name="ShowOSD"> \
<arg type="a{sv}" direction="in" name="params"/> \
</method> \
<method name="FocusApp"> \
<arg type="s" direction="in" name="id"/> \
</method> \
<method name="ShowApplications" /> \
<method name="GrabAccelerator"> \
<arg type="s" direction="in" name="accelerator"/> \
<arg type="u" direction="in" name="flags"/> \
<arg type="u" direction="out" name="action"/> \
</method> \
<method name="GrabAccelerators"> \
<arg type="a(su)" direction="in" name="accelerators"/> \
<arg type="au" direction="out" name="actions"/> \
</method> \
<method name="UngrabAccelerator"> \
<arg type="u" direction="in" name="action"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<signal name="AcceleratorActivated"> \
<arg name="action" type="u" /> \
<arg name="deviceid" type="u" /> \
<arg name="timestamp" type="u" /> \
</signal> \
<property name="Mode" type="s" access="read" /> \
<property name="OverviewActive" type="b" access="readwrite" /> \
<property name="ShellVersion" type="s" access="read" /> \
</interface> \
</node>';
const GnomeShellIface = <interface name="org.gnome.Shell">
<method name="Eval">
<arg type="s" direction="in" name="script" />
<arg type="b" direction="out" name="success" />
<arg type="s" direction="out" name="result" />
</method>
<method name="FocusSearch"/>
<method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="FocusApp">
<arg type="s" direction="in" name="id"/>
</method>
<method name="ShowApplications" />
<method name="GrabAccelerator">
<arg type="s" direction="in" name="accelerator"/>
<arg type="u" direction="in" name="flags"/>
<arg type="u" direction="out" name="action"/>
</method>
<method name="GrabAccelerators">
<arg type="a(su)" direction="in" name="accelerators"/>
<arg type="au" direction="out" name="actions"/>
</method>
<method name="UngrabAccelerator">
<arg type="u" direction="in" name="action"/>
<arg type="b" direction="out" name="success"/>
</method>
<signal name="AcceleratorActivated">
<arg name="action" type="u" />
<arg name="deviceid" type="u" />
<arg name="timestamp" type="u" />
</signal>
<property name="Mode" type="s" access="read" />
<property name="OverviewActive" type="b" access="readwrite" />
<property name="ShellVersion" type="s" access="read" />
</interface>;
const ScreenSaverIface = '<node> \
<interface name="org.gnome.ScreenSaver"> \
<method name="Lock"> \
</method> \
<method name="GetActive"> \
<arg name="active" direction="out" type="b" /> \
</method> \
<method name="SetActive"> \
<arg name="value" direction="in" type="b" /> \
</method> \
<method name="GetActiveTime"> \
<arg name="value" direction="out" type="u" /> \
</method> \
<signal name="ActiveChanged"> \
<arg name="new_value" type="b" /> \
</signal> \
</interface> \
</node>';
const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
<method name="Lock">
</method>
<method name="GetActive">
<arg name="active" direction="out" type="b" />
</method>
<method name="SetActive">
<arg name="value" direction="in" type="b" />
</method>
<method name="GetActiveTime">
<arg name="value" direction="out" type="u" />
</method>
<signal name="ActiveChanged">
<arg name="new_value" type="b" />
</signal>
</interface>;
const GnomeShell = new Lang.Class({
Name: 'GnomeShellDBus',
@ -119,7 +115,7 @@ const GnomeShell = new Lang.Class({
returnValue = '';
success = true;
} catch (e) {
returnValue = '' + e;
returnValue = JSON.stringify(e);
success = false;
}
return [success, returnValue];
@ -250,43 +246,41 @@ const GnomeShell = new Lang.Class({
ShellVersion: Config.PACKAGE_VERSION
});
const GnomeShellExtensionsIface = '<node> \
<interface name="org.gnome.Shell.Extensions"> \
<method name="ListExtensions"> \
<arg type="a{sa{sv}}" direction="out" name="extensions" /> \
</method> \
<method name="GetExtensionInfo"> \
<arg type="s" direction="in" name="extension" /> \
<arg type="a{sv}" direction="out" name="info" /> \
</method> \
<method name="GetExtensionErrors"> \
<arg type="s" direction="in" name="extension" /> \
<arg type="as" direction="out" name="errors" /> \
</method> \
<signal name="ExtensionStatusChanged"> \
<arg type="s" name="uuid"/> \
<arg type="i" name="state"/> \
<arg type="s" name="error"/> \
</signal> \
<method name="InstallRemoteExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="s" direction="out" name="result"/> \
</method> \
<method name="UninstallExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<method name="LaunchExtensionPrefs"> \
<arg type="s" direction="in" name="uuid"/> \
</method> \
<method name="ReloadExtension"> \
<arg type="s" direction="in" name="uuid"/> \
</method> \
<method name="CheckForUpdates"> \
</method> \
<property name="ShellVersion" type="s" access="read" /> \
</interface> \
</node>';
const GnomeShellExtensionsIface = <interface name="org.gnome.Shell.Extensions">
<method name="ListExtensions">
<arg type="a{sa{sv}}" direction="out" name="extensions" />
</method>
<method name="GetExtensionInfo">
<arg type="s" direction="in" name="extension" />
<arg type="a{sv}" direction="out" name="info" />
</method>
<method name="GetExtensionErrors">
<arg type="s" direction="in" name="extension" />
<arg type="as" direction="out" name="errors" />
</method>
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
<method name="InstallRemoteExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="out" name="result"/>
</method>
<method name="UninstallExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="LaunchExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="ReloadExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="CheckForUpdates">
</method>
<property name="ShellVersion" type="s" access="read" />
</interface>;
const GnomeShellExtensions = new Lang.Class({
Name: 'GnomeShellExtensionsDBus',

View File

@ -521,38 +521,36 @@ const ShellProcessesDialog = new Lang.Class({
});
Signals.addSignalMethods(ShellProcessesDialog.prototype);
const GnomeShellMountOpIface = '<node> \
<interface name="org.Gtk.MountOperationHandler"> \
<method name="AskPassword"> \
<arg type="s" direction="in" name="object_id"/> \
<arg type="s" direction="in" name="message"/> \
<arg type="s" direction="in" name="icon_name"/> \
<arg type="s" direction="in" name="default_user"/> \
<arg type="s" direction="in" name="default_domain"/> \
<arg type="u" direction="in" name="flags"/> \
<arg type="u" direction="out" name="response"/> \
<arg type="a{sv}" direction="out" name="response_details"/> \
</method> \
<method name="AskQuestion"> \
<arg type="s" direction="in" name="object_id"/> \
<arg type="s" direction="in" name="message"/> \
<arg type="s" direction="in" name="icon_name"/> \
<arg type="as" direction="in" name="choices"/> \
<arg type="u" direction="out" name="response"/> \
<arg type="a{sv}" direction="out" name="response_details"/> \
</method> \
<method name="ShowProcesses"> \
<arg type="s" direction="in" name="object_id"/> \
<arg type="s" direction="in" name="message"/> \
<arg type="s" direction="in" name="icon_name"/> \
<arg type="ai" direction="in" name="application_pids"/> \
<arg type="as" direction="in" name="choices"/> \
<arg type="u" direction="out" name="response"/> \
<arg type="a{sv}" direction="out" name="response_details"/> \
</method> \
<method name="Close"/> \
</interface> \
</node>';
const GnomeShellMountOpIface = <interface name="org.Gtk.MountOperationHandler">
<method name="AskPassword">
<arg type="s" direction="in" name="object_id"/>
<arg type="s" direction="in" name="message"/>
<arg type="s" direction="in" name="icon_name"/>
<arg type="s" direction="in" name="default_user"/>
<arg type="s" direction="in" name="default_domain"/>
<arg type="u" direction="in" name="flags"/>
<arg type="u" direction="out" name="response"/>
<arg type="a{sv}" direction="out" name="response_details"/>
</method>
<method name="AskQuestion">
<arg type="s" direction="in" name="object_id"/>
<arg type="s" direction="in" name="message"/>
<arg type="s" direction="in" name="icon_name"/>
<arg type="as" direction="in" name="choices"/>
<arg type="u" direction="out" name="response"/>
<arg type="a{sv}" direction="out" name="response_details"/>
</method>
<method name="ShowProcesses">
<arg type="s" direction="in" name="object_id"/>
<arg type="s" direction="in" name="message"/>
<arg type="s" direction="in" name="icon_name"/>
<arg type="ai" direction="in" name="application_pids"/>
<arg type="as" direction="in" name="choices"/>
<arg type="u" direction="out" name="response"/>
<arg type="a{sv}" direction="out" name="response_details"/>
</method>
<method name="Close"/>
</interface>;
const ShellMountOperationType = {
NONE: 0,

View File

@ -105,8 +105,8 @@ const AuthNotification = new Lang.Class({
this._devicePath = device_path;
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
this.addAction('allow', _("Allow"));
this.addAction('deny', _("Deny"));
this.addButton('allow', _("Allow"));
this.addButton('deny', _("Deny"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
if (action == 'allow')
@ -133,9 +133,9 @@ const AuthServiceNotification = new Lang.Class({
this._devicePath = device_path;
this.addBody(_("Device %s wants access to the service '%s'").format(long_name, uuid));
this.addAction('always-grant', _("Always grant access"));
this.addAction('grant', _("Grant this time only"));
this.addAction('reject', _("Reject"));
this.addButton('always-grant', _("Always grant access"));
this.addButton('grant', _("Grant this time only"));
this.addButton('reject', _("Reject"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
@ -172,8 +172,8 @@ const ConfirmNotification = new Lang.Class({
this.addBody(_("Please confirm whether the Passkey '%06d' matches the one on the device.").format(pin));
/* Translators: this is the verb, not the noun */
this.addAction('matches', _("Matches"));
this.addAction('does-not-match', _("Does not match"));
this.addButton('matches', _("Matches"));
this.addButton('does-not-match', _("Does not match"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
if (action == 'matches')
@ -207,46 +207,45 @@ const PinNotification = new Lang.Class({
let key = event.get_key_symbol();
if (key == Clutter.KEY_Return) {
if (this._canActivateOkButton())
this._ok();
this.emit('action-invoked', 'ok');
return true;
} else if (key == Clutter.KEY_Escape) {
this._cancel();
this.emit('action-invoked', 'cancel');
return true;
}
return false;
}));
this.addActor(this._entry);
let okButton = this.addAction(_("OK"), Lang.bind(this, this._ok));
this.addAction(_("Cancel"), Lang.bind(this, this._cancel));
this.addButton('ok', _("OK"));
this.addButton('cancel', _("Cancel"));
okButton.reactive = this._canActivateOkButton();
this._entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
okButton.reactive = this._canActivateOkButton();
}));
},
this.setButtonSensitive('ok', this._canActivateOkButton());
this._entry.clutter_text.connect('text-changed', Lang.bind(this,
function() {
this.setButtonSensitive('ok', this._canActivateOkButton());
}));
_ok: function() {
if (this._numeric) {
let num = parseInt(this._entry.text, 10);
if (isNaN(num)) {
// user reply was empty, or was invalid
// cancel the operation
num = -1;
this.connect('action-invoked', Lang.bind(this, function(self, action) {
if (action == 'ok') {
if (this._numeric) {
let num = parseInt(this._entry.text);
if (isNaN(num)) {
// user reply was empty, or was invalid
// cancel the operation
num = -1;
}
this._applet.agent_reply_passkey(this._devicePath, num);
} else
this._applet.agent_reply_pincode(this._devicePath, this._entry.text);
} else {
if (this._numeric)
this._applet.agent_reply_passkey(this._devicePath, -1);
else
this._applet.agent_reply_pincode(this._devicePath, null);
}
this._applet.agent_reply_passkey(this._devicePath, num);
} else {
this._applet.agent_reply_pincode(this._devicePath, this._entry.text);
}
this.destroy();
},
_cancel: function() {
if (this._numeric)
this._applet.agent_reply_passkey(this._devicePath, -1);
else
this._applet.agent_reply_pincode(this._devicePath, null);
this.destroy();
this.destroy();
}));
},
_canActivateOkButton: function() {

View File

@ -11,11 +11,9 @@ const Slider = imports.ui.slider;
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const BrightnessInterface = '<node> \
<interface name="org.gnome.SettingsDaemon.Power.Screen"> \
<property name="Brightness" type="i" access="readwrite"/> \
</interface> \
</node>';
const BrightnessInterface = <interface name="org.gnome.SettingsDaemon.Power.Screen">
<property name='Brightness' type='i' access='readwrite'/>
</interface>;
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);

View File

@ -41,13 +41,11 @@ const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard';
const KeyboardManagerInterface = '<node> \
<interface name="org.gnome.SettingsDaemon.Keyboard"> \
<method name="SetInputSource"> \
<arg type="u" direction="in" /> \
</method> \
</interface> \
</node>';
const KeyboardManagerInterface = <interface name="org.gnome.SettingsDaemon.Keyboard">
<method name="SetInputSource">
<arg type="u" direction="in" />
</method>
</interface>;
const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface);

View File

@ -549,30 +549,33 @@ const NMWirelessDialogItem = new Lang.Class({
this._network = network;
this._ap = network.accessPoints[0];
this.actor = new St.BoxLayout({ style_class: 'nm-dialog-item',
can_focus: true,
reactive: true });
this.actor = new St.Button({ style_class: 'nm-dialog-item',
can_focus: true,
x_fill: true });
this.actor.connect('key-focus-in', Lang.bind(this, function() {
this.emit('selected');
}));
let action = new Clutter.ClickAction();
action.connect('clicked', Lang.bind(this, function() {
this.actor.connect('clicked', Lang.bind(this, function() {
this.actor.grab_key_focus();
}));
this.actor.add_action(action);
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._content = new St.BoxLayout({ style_class: 'nm-dialog-item-box' });
this.actor.set_child(this._content);
let title = ssidToLabel(this._ap.get_ssid());
this._label = new St.Label({ text: title });
this.actor.label_actor = this._label;
this.actor.add(this._label, { x_align: St.Align.START });
this._content.add(this._label, { x_align: St.Align.START });
this._selectedIcon = new St.Icon({ style_class: 'nm-dialog-icon',
icon_name: 'object-select-symbolic' });
this.actor.add(this._selectedIcon);
this._content.add(this._selectedIcon);
this._icons = new St.BoxLayout({ style_class: 'nm-dialog-icons' });
this.actor.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END });
this._content.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END });
this._secureIcon = new St.Icon({ style_class: 'nm-dialog-icon' });
if (this._ap._secType != NMAccessPointSecurity.NONE)
@ -603,6 +606,16 @@ const NMWirelessDialogItem = new Lang.Class({
return 'network-workgroup-symbolic';
else
return 'network-wireless-signal-' + signalToIcon(this._ap.strength) + '-symbolic';
},
_onKeyPressEvent: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return
|| symbol == Clutter.KEY_KP_Enter) {
this.emit('connect');
return true;
}
return false;
}
});
Signals.addSignalMethods(NMWirelessDialogItem.prototype);
@ -955,13 +968,13 @@ const NMWirelessDialog = new Lang.Class({
_selectNetwork: function(network) {
if (this._selectedNetwork)
this._selectedNetwork.item.actor.remove_style_pseudo_class('selected');
this._selectedNetwork.item.actor.checked = false;
this._selectedNetwork = network;
this._updateSensitivity();
if (this._selectedNetwork)
this._selectedNetwork.item.actor.add_style_pseudo_class('selected');
this._selectedNetwork.item.actor.checked = true;
},
_createNetworkItem: function(network) {
@ -971,6 +984,9 @@ const NMWirelessDialog = new Lang.Class({
Util.ensureActorVisibleInScrollView(this._scrollView, network.item.actor);
this._selectNetwork(network);
}));
network.item.connect('connect', Lang.bind(this, function() {
this._connect();
}));
},
});

View File

@ -8,22 +8,20 @@ const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const BUS_NAME = 'org.freedesktop.UPower';
const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const DisplayDeviceInterface = '<node> \
<interface name="org.freedesktop.UPower.Device"> \
<property name="Type" type="u" access="read"/> \
<property name="State" type="u" access="read"/> \
<property name="Percentage" type="d" access="read"/> \
<property name="TimeToEmpty" type="x" access="read"/> \
<property name="TimeToFull" type="x" access="read"/> \
<property name="IsPresent" type="b" access="read"/> \
<property name="IconName" type="s" access="read"/> \
</interface> \
</node>';
const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
<method name="GetDevices">
<arg type="a(susdut)" direction="out" />
</method>
<method name="GetPrimaryDevice">
<arg type="(susdut)" direction="out" />
</method>
<property name="Icon" type="s" access="read" />
</interface>;
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface);
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
const Indicator = new Lang.Class({
Name: 'PowerIndicator',
@ -34,7 +32,7 @@ const Indicator = new Lang.Class({
this._indicator = this._addIndicator();
this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
Lang.bind(this, function(proxy, error) {
if (error) {
log(error.message);
@ -45,7 +43,7 @@ const Indicator = new Lang.Class({
this._sync();
}));
this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Battery"), true);
this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
this.menu.addMenuItem(this._item);
@ -58,18 +56,11 @@ const Indicator = new Lang.Class({
this.menu.setSensitive(sensitive);
},
_getStatus: function() {
let seconds = 0;
_statusForDevice: function(device) {
let [device_id, device_type, icon, percentage, state, seconds] = device;
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED)
if (state == UPower.DeviceState.FULLY_CHARGED)
return _("Fully Charged");
else if (this._proxy.State == UPower.DeviceState.CHARGING)
seconds = this._proxy.TimeToFull;
else if (this._proxy.State == UPower.DeviceState.DISCHARGING)
seconds = this._proxy.TimeToEmpty;
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
else
return _("Estimating…");
let time = Math.round(seconds / 60);
if (time == 0) {
@ -81,43 +72,44 @@ const Indicator = new Lang.Class({
let minutes = time % 60;
let hours = Math.floor(time / 60);
if (this._proxy.State == UPower.DeviceState.DISCHARGING) {
if (state == UPower.DeviceState.DISCHARGING) {
// Translators: this is <hours>:<minutes> Remaining (<percentage>)
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, this._proxy.Percentage);
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, percentage);
}
if (this._proxy.State == UPower.DeviceState.CHARGING) {
if (state == UPower.DeviceState.CHARGING) {
// Translators: this is <hours>:<minutes> Until Full (<percentage>)
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, this._proxy.Percentage);
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, percentage);
}
return null;
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
return _("Estimating…");
},
_sync: function() {
// Do we have batteries or a UPS?
let visible = this._proxy.IsPresent;
if (visible) {
this._item.actor.show();
} else {
// If there's no battery, then we use the power icon.
this._item.actor.hide();
this._indicator.icon_name = 'system-shutdown-symbolic';
return;
function isBattery(result) {
if (!result)
return false;
let [device] = result;
let [, deviceType] = device;
return (deviceType == UPower.DeviceKind.BATTERY);
}
// The icons
let icon = this._proxy.IconName;
this._indicator.icon_name = icon;
this._item.icon.icon_name = icon;
// The status label
this._item.status.text = this._getStatus();
// The sub-menu heading
if (this._proxy.Type == UPower.DeviceKind.UPS)
this._item.label.text = _("UPS");
else
this._item.label.text = _("Battery");
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
if (isBattery(result)) {
let [device] = result;
let [,, icon] = device;
let gicon = Gio.icon_new_for_string(icon);
this._indicator.gicon = gicon;
this._item.icon.gicon = gicon;
this._item.status.text = this._statusForDevice(device);
this._item.actor.show();
} else {
// If there's no battery, then we use the power icon.
this._indicator.icon_name = 'system-shutdown-symbolic';
this._item.actor.hide();
}
}));
},
});

View File

@ -9,11 +9,9 @@ const PopupMenu = imports.ui.popupMenu;
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
const RfkillManagerInterface = '<node> \
<interface name="org.gnome.SettingsDaemon.Rfkill"> \
<property name="AirplaneMode" type="b" access="readwrite" /> \
</interface> \
</node>';
const RfkillManagerInterface = <interface name="org.gnome.SettingsDaemon.Rfkill">
<property name="AirplaneMode" type="b" access="readwrite" />
</interface>;
const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface);

View File

@ -11,8 +11,29 @@ const Signals = imports.signals;
const Tweener = imports.tweener.tweener;
// This is a wrapper around imports.tweener.tweener that adds a bit of
// Clutter integration. If the tweening target is a Clutter.Actor, then
// the tweenings will automatically be removed if the actor is destroyed.
// Clutter integration and some additional callbacks:
//
// 1. If the tweening target is a Clutter.Actor, then the tweenings
// will automatically be removed if the actor is destroyed
//
// 2. If target._delegate.onAnimationStart() exists, it will be
// called when the target starts being animated.
//
// 3. If target._delegate.onAnimationComplete() exists, it will be
// called once the target is no longer being animated.
//
// The onAnimationStart() and onAnimationComplete() callbacks differ
// from the tweener onStart and onComplete parameters, in that (1)
// they track whether or not the target has *any* tweens attached to
// it, as opposed to be called for *each* tween, and (2)
// onAnimationComplete() is always called when the object stops being
// animated, regardless of whether it stopped normally or abnormally.
//
// onAnimationComplete() is called at idle time, which means that if a
// tween completes and then another is added before returning to the
// main loop, the complete callback will not be called (until the new
// tween finishes).
// ActionScript Tweener methods that imports.tweener.tweener doesn't
// currently implement: getTweens, getVersion, registerTransition,
@ -56,6 +77,7 @@ function _wrapTweening(target, tweeningParameters) {
if (!Gtk.Settings.get_default().gtk_enable_animations)
tweeningParameters['time'] = 0.000001;
_addHandler(target, tweeningParameters, 'onStart', _tweenStarted);
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
}
@ -63,7 +85,7 @@ function _getTweenState(target) {
// If we were paranoid, we could keep a plist mapping targets to
// states... but we're not that paranoid.
if (!target.__ShellTweenerState)
target.__ShellTweenerState = {};
_resetTweenState(target);
return target.__ShellTweenerState;
}
@ -73,6 +95,8 @@ function _resetTweenState(target) {
if (state) {
if (state.destroyedId)
state.actor.disconnect(state.destroyedId);
if (state.idleCompletedId)
Mainloop.source_remove(state.idleCompletedId);
}
target.__ShellTweenerState = {};
@ -98,9 +122,32 @@ function _actorDestroyed(target) {
Tweener.removeTweens(target);
}
function _tweenStarted(target) {
let state = _getTweenState(target);
let delegate = target._delegate;
if (!state.running && delegate && delegate.onAnimationStart)
delegate.onAnimationStart();
state.running = true;
}
function _tweenCompleted(target) {
if (!isTweening(target))
let state = _getTweenState(target);
if (!state.idleCompletedId)
state.idleCompletedId = Mainloop.idle_add(Lang.bind(null, _idleCompleted, target));
}
function _idleCompleted(target) {
let state = _getTweenState(target);
let delegate = target._delegate;
if (!isTweening(target)) {
_resetTweenState(target);
if (delegate && delegate.onAnimationComplete)
delegate.onAnimationComplete();
}
return false;
}
function getTweenCount(scope) {

View File

@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// A widget showing the user avatar and name
const Clutter = imports.gi.Clutter;
const AccountsService = imports.gi.AccountsService;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
@ -57,83 +56,6 @@ const Avatar = new Lang.Class({
}
});
const UserWidgetLabel = new Lang.Class({
Name: 'UserWidgetLabel',
Extends: St.Widget,
_init: function(user) {
this.parent({ layout_manager: new Clutter.BinLayout() });
this._user = user;
this._realNameLabel = new St.Label({ style_class: 'user-widget-label',
y_align: Clutter.ActorAlign.CENTER });
this.add_child(this._realNameLabel);
this._userNameLabel = new St.Label({ style_class: 'user-widget-label',
y_align: Clutter.ActorAlign.CENTER });
this.add_child(this._userNameLabel);
this._currentLabel = null;
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._updateUser();
},
vfunc_destroy: function() {
if (this._userLoadedId != 0) {
this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0;
}
if (this._userChangedId != 0) {
this._user.disconnect(this._userChangedId);
this._userChangedId = 0;
}
},
vfunc_allocate: function(box, flags) {
this.set_allocation(box, flags);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [minRealNameWidth, minRealNameHeight,
natRealNameWidth, natRealNameHeight] = this._realNameLabel.get_preferred_size();
let [minUserNameWidth, minUserNameHeight,
natUserNameWidth, natUserNameHeight] = this._userNameLabel.get_preferred_size();
if (natRealNameWidth <= availWidth)
this._currentLabel = this._realNameLabel;
else
this._currentLabel = this._userNameLabel;
let childBox = new Clutter.ActorBox();
childBox.x1 = 0;
childBox.y1 = 0;
childBox.x2 = availWidth;
childBox.y2 = availHeight;
this._currentLabel.allocate(childBox, flags);
},
vfunc_paint: function() {
this._currentLabel.paint();
},
_updateUser: function() {
if (this._user.is_loaded) {
this._realNameLabel.text = this._user.get_real_name();
this._userNameLabel.text = this._user.get_user_name();
} else {
this._realNameLabel.text = '';
this._userNameLabel.text = '';
}
},
});
const UserWidget = new Lang.Class({
Name: 'UserWidget',
@ -145,14 +67,22 @@ const UserWidget = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._avatar = new Avatar(user);
this.actor.add_child(this._avatar.actor);
this.actor.add(this._avatar.actor,
{ x_fill: true, y_fill: true });
this._label = new UserWidgetLabel(user);
this.actor.add_child(this._label);
this._label = new St.Label({ style_class: 'user-widget-label' });
this.actor.add(this._label,
{ expand: true,
x_fill: true,
y_fill: false,
y_align: St.Align.MIDDLE });
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._updateUser();
this._userLoadedId = this._user.connect('notify::is-loaded',
Lang.bind(this, this._updateUser));
this._userChangedId = this._user.connect('changed',
Lang.bind(this, this._updateUser));
if (this._user.is_loaded)
this._updateUser();
},
_onDestroy: function() {
@ -168,6 +98,11 @@ const UserWidget = new Lang.Class({
},
_updateUser: function() {
if (this._user.is_loaded)
this._label.text = this._user.get_real_name();
else
this._label.text = '';
this._avatar.update();
}
});

View File

@ -14,9 +14,12 @@ const AppDisplay = imports.ui.appDisplay;
const Main = imports.ui.main;
const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const RemoteSearch = imports.ui.remoteSearch;
const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Wanda = imports.ui.wanda;
const WorkspacesView = imports.ui.workspacesView;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@ -63,6 +66,8 @@ const ViewSelector = new Lang.Class({
this._searchActive = false;
this._searchTimeoutId = 0;
this._searchSystem = new Search.SearchSystem();
this._entry = searchEntry;
ShellEntry.addContextMenu(this._entry);
@ -98,11 +103,24 @@ const ViewSelector = new Lang.Class({
this._appsPage = this._addPage(this.appDisplay.actor,
_("Applications"), 'view-grid-symbolic');
this._searchResults = new Search.SearchResults();
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
this._searchPage = this._addPage(this._searchResults.actor,
_("Search"), 'edit-find-symbolic',
{ a11yFocus: this._entry });
this._searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
// Default search providers
// Wanda comes obviously first
this.addSearchProvider(new Wanda.WandaSearchProvider());
this.addSearchProvider(new AppDisplay.AppSearchProvider());
// Load remote search providers provided by applications
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
// Since the entry isn't inside the results container we install this
// dummy widget as the last results container child so that we can
// include the entry in the keynav tab path
@ -468,10 +486,45 @@ const ViewSelector = new Lang.Class({
let terms = getTermsForSearchString(this._entry.get_text());
this._searchResults.setTerms(terms);
this._searchSystem.updateSearchResults(terms);
this._showPage(this._searchPage);
},
_shouldUseSearchProvider: function(provider) {
// the disable-external GSetting only affects remote providers
if (!provider.isRemoteProvider)
return true;
if (this._searchSettings.get_boolean('disable-external'))
return false;
let appId = provider.appInfo.get_id();
let disable = this._searchSettings.get_strv('disabled');
return disable.indexOf(appId) == -1;
},
_reloadRemoteProviders: function() {
// removeSearchProvider() modifies the provider list we iterate on,
// so make a copy first
let remoteProviders = this._searchSystem.getRemoteProviders().slice(0);
remoteProviders.forEach(Lang.bind(this, this.removeSearchProvider));
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
},
addSearchProvider: function(provider) {
if (!this._shouldUseSearchProvider(provider))
return;
this._searchSystem.registerProvider(provider);
this._searchResults.createProviderDisplay(provider);
},
removeSearchProvider: function(provider) {
this._searchSystem.unregisterProvider(provider);
this._searchResults.destroyProviderDisplay(provider);
},
getActivePage: function() {
if (this._activePage == this._workspacesPage)
return ViewPage.WINDOWS;

160
js/ui/wanda.js Normal file
View File

@ -0,0 +1,160 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GdkPixbuf = imports.gi.GdkPixbuf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const FISH_NAME = 'wanda';
const FISH_FILENAME = 'wanda.png';
const FISH_SPEED = 300;
const FISH_COMMAND = 'fortune';
// The size of an individual frame in the animation
const FISH_HEIGHT = 22;
const FISH_WIDTH = 36;
const FISH_GROUP = 'Fish Animation';
const MAGIC_FISH_KEY = 'free the fish';
const WandaIcon = new Lang.Class({
Name: 'WandaIcon',
Extends: IconGrid.BaseIcon,
_init : function(fish, label, params) {
this.parent(label, params);
this._fish = fish;
this._imageFile = GLib.build_filenamev([global.datadir, fish + '.png']);
this._imgHeight = FISH_HEIGHT;
this._imgWidth = FISH_WIDTH;
},
createIcon: function(iconSize) {
this._animations = new Panel.Animation(this._imageFile, this._imgWidth, this._imgHeight, FISH_SPEED);
this._animations.play();
return this._animations.actor;
},
_createIconTexture: function(size) {
if (size == this.iconSize)
return;
this.parent(size);
}
});
const WandaIconBin = new Lang.Class({
Name: 'WandaIconBin',
_init: function(fish, label, params) {
this.actor = new St.Bin({ reactive: true,
track_hover: true });
this.icon = new WandaIcon(fish, label, params);
this.actor.child = this.icon.actor;
this.actor.label_actor = this.icon.label;
},
});
const FortuneDialog = new Lang.Class({
Name: 'FortuneDialog',
_init: function(name, command) {
let text;
try {
let [res, stdout, stderr, status] = GLib.spawn_command_line_sync(command);
text = String.fromCharCode.apply(null, stdout);
} catch(e) {
text = _("Sorry, no wisdom for you today:\n%s").format(e.message);
}
this._title = new St.Label({ style_class: 'prompt-dialog-headline',
text: _("%s the Oracle says").format(name) });
this._label = new St.Label({ style_class: 'prompt-dialog-description',
text: text });
this._label.clutter_text.line_wrap = true;
this._box = new St.BoxLayout({ vertical: true,
style_class: 'prompt-dialog' // this is just to force a reasonable width
});
this._box.add(this._title, { align: St.Align.MIDDLE });
this._box.add(this._label, { expand: true });
this._button = new St.Button({ button_mask: St.ButtonMask.ONE,
style_class: 'modal-dialog',
reactive: true });
this._button.connect('clicked', Lang.bind(this, this.destroy));
this._button.child = this._box;
this._bin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._bin.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this._bin.add_actor(this._button);
Main.layoutManager.addChrome(this._bin);
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, Lang.bind(this, this.destroy));
},
destroy: function() {
this._bin.destroy();
}
});
function capitalize(str) {
return str[0].toUpperCase() + str.substring(1, str.length);
}
const WandaSearchProvider = new Lang.Class({
Name: 'WandaSearchProvider',
_init: function() {
this.id = 'wanda';
},
getResultMetas: function(fish, callback) {
callback([{ 'id': fish[0], // there may be many fish in the sea, but
// only one which speaks the truth!
'name': capitalize(fish[0]),
'createIcon': function(iconSize) {
return new St.Icon({ gicon: Gio.icon_new_for_string('face-smile'),
icon_size: iconSize });
}
}]);
},
filterResults: function(results) {
return results;
},
getInitialResultSet: function(terms) {
if (terms.join(' ') == MAGIC_FISH_KEY) {
this.searchSystem.setResults(this, [ FISH_NAME ]);
} else {
this.searchSystem.setResults(this, []);
}
},
getSubsearchResultSet: function(previousResults, terms) {
this.getInitialResultSet(terms);
},
activateResult: function(fish) {
if (this._dialog)
this._dialog.destroy();
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
},
createResultObject: function (resultMeta, terms) {
return new WandaIconBin(resultMeta.id, resultMeta.name);
}
});

View File

@ -39,9 +39,6 @@ const WindowAttentionHandler = new Lang.Class({
let [title, banner] = this._getTitleAndBanner(app, window);
let notification = new MessageTray.Notification(source, title, banner);
notification.connect('clicked', function() {
source.open();
});
notification.setForFeedback(true);
source.notify(notification);
@ -82,7 +79,7 @@ const Source = new Lang.Class({
return this._app.create_icon_texture(size);
},
open: function() {
open : function(notification) {
Main.activateWindow(this._window);
this.destroy();
}

View File

@ -10,14 +10,19 @@ const St = imports.gi.St;
const Signals = imports.signals;
const DND = imports.ui.dnd;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const Tweener = imports.ui.tweener;
const FOCUS_ANIMATION_TIME = 0.15;
const WINDOW_DND_SIZE = 256;
const WINDOW_CLONE_MAXIMUM_SCALE = 0.7;
const LIGHTBOX_FADE_TIME = 0.1;
const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100;
@ -887,19 +892,6 @@ function padArea(area, padding) {
};
}
function rectEqual(one, two) {
if (one == two)
return true;
if (!one || !two)
return false;
return (one.x == two.x &&
one.y == two.y &&
one.width == two.width &&
one.height == two.height);
}
/**
* @metaWorkspace: a #Meta.Workspace, or null
*/
@ -975,17 +967,11 @@ const Workspace = new Lang.Class({
},
setFullGeometry: function(geom) {
if (rectEqual(this._fullGeometry, geom))
return;
this._fullGeometry = geom;
this._recalculateWindowPositions(WindowPositionFlags.NONE);
},
setActualGeometry: function(geom) {
if (rectEqual(this._actualGeometry, geom))
return;
this._actualGeometry = geom;
if (this._actualGeometryLater)
@ -1208,7 +1194,6 @@ const Workspace = new Lang.Class({
}
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
this._repositionWindowsId = 0;
return false;
},
@ -1464,17 +1449,17 @@ const Workspace = new Lang.Class({
clone.connect('selected',
Lang.bind(this, this._onCloneSelected));
clone.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginWindowDrag(clone);
Lang.bind(this, function(clone) {
Main.overview.beginWindowDrag();
overlay.hide();
}));
clone.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledWindowDrag(clone);
Lang.bind(this, function(clone) {
Main.overview.cancelledWindowDrag();
}));
clone.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endWindowDrag(clone);
Lang.bind(this, function(clone) {
Main.overview.endWindowDrag();
overlay.show();
}));
clone.connect('size-changed',
@ -1636,7 +1621,9 @@ const Workspace = new Lang.Class({
metaWindow.move_to_monitor(this.monitorIndex);
let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index();
metaWindow.change_workspace_by_index(index, false);
metaWindow.change_workspace_by_index(index,
false, // don't create workspace
time);
return true;
} else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,

View File

@ -438,16 +438,16 @@ const WorkspaceThumbnail = new Lang.Class({
this.activate(time);
}));
clone.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginWindowDrag(clone);
Lang.bind(this, function(clone) {
Main.overview.beginWindowDrag();
}));
clone.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledWindowDrag(clone);
Lang.bind(this, function(clone) {
Main.overview.cancelledWindowDrag();
}));
clone.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endWindowDrag(clone);
Lang.bind(this, function(clone) {
Main.overview.endWindowDrag();
}));
this._contents.add_actor(clone.actor);
@ -507,7 +507,9 @@ const WorkspaceThumbnail = new Lang.Class({
if (metaWindow.get_monitor() != this.monitorIndex)
metaWindow.move_to_monitor(this.monitorIndex);
metaWindow.change_workspace_by_index(this.metaWorkspace.index(), false);
metaWindow.change_workspace_by_index(this.metaWorkspace.index(),
false, // don't create workspace
time);
return true;
} else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
@ -737,12 +739,14 @@ const ThumbnailsBox = new Lang.Class({
// ... move them down one.
windows.forEach(function(win) {
win.meta_window.change_workspace_by_index(win.get_workspace() + 1, true);
win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
true, time);
});
if (isWindow)
// ... and bam, a workspace, good as new.
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true);
source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
true, time);
else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time });

View File

@ -23,92 +23,75 @@ const MAX_WORKSPACES = 16;
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
const WorkspacesViewBase = new Lang.Class({
Name: 'WorkspacesViewBase',
function rectEqual(one, two) {
if (one == two)
return true;
_init: function(monitorIndex) {
if (!one || !two)
return false;
return (one.x == two.x &&
one.y == two.y &&
one.width == two.width &&
one.height == two.height);
}
const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView',
_init: function(workspaces) {
this.actor = new St.Widget({ style_class: 'workspaces-view',
reactive: true });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
// The actor itself isn't a drop target, so we don't want to pick on its area
this.actor.set_size(0, 0);
this._monitorIndex = monitorIndex;
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('style-changed', Lang.bind(this,
function() {
let node = this.actor.get_theme_node();
this._spacing = node.get_length('spacing');
this._updateWorkspaceActors(false);
}));
this._fullGeometry = null;
this._actualGeometry = null;
this._inDrag = false;
this._windowDragBeginId = Main.overview.connect('window-drag-begin', Lang.bind(this, this._dragBegin));
this._windowDragEndId = Main.overview.connect('window-drag-end', Lang.bind(this, this._dragEnd));
},
_onDestroy: function() {
this._dragEnd();
if (this._windowDragBeginId > 0) {
Main.overview.disconnect(this._windowDragBeginId);
this._windowDragBeginId = 0;
}
if (this._windowDragEndId > 0) {
Main.overview.disconnect(this._windowDragEndId);
this._windowDragEndId = 0;
}
},
_dragBegin: function(overview, clone) {
this._inDrag = true;
this._setReservedSlot(clone);
},
_dragEnd: function() {
this._inDrag = false;
this._setReservedSlot(null);
},
destroy: function() {
this.actor.destroy();
},
setFullGeometry: function(geom) {
this._fullGeometry = geom;
this._syncGeometry();
},
setActualGeometry: function(geom) {
this._actualGeometry = geom;
this._syncGeometry();
},
});
const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView',
Extends: WorkspacesViewBase,
_init: function(monitorIndex) {
this.parent(monitorIndex);
this._spacing = 0;
this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling
this._animatingScroll = false; // programatically updating the adjustment
this._inDrag = false; // dragging a window
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._updateExtraWorkspacesId =
this._settings.connect('changed::workspaces-only-on-primary',
Lang.bind(this, this._updateExtraWorkspaces));
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: 0 });
this.scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
this._workspaces = workspaces;
this._workspaces = [];
this._updateWorkspaces();
this._updateWorkspacesId = global.screen.connect('notify::n-workspaces', Lang.bind(this, this._updateWorkspaces));
// Add workspace actors
for (let w = 0; w < global.screen.n_workspaces; w++)
this.actor.add_actor(this._workspaces[w].actor);
this._workspaces[activeWorkspaceIndex].actor.raise_top();
this._extraWorkspaces = [];
this._updateExtraWorkspaces();
// Position/scale the desktop windows and their children after the
// workspaces have been created. This cannot be done first because
// window movement depends on the Workspaces object being accessible
// as an Overview member.
this._overviewShowingId =
Main.overview.connect('showing',
Lang.bind(this, function() {
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomToOverview();
for (let w = 0; w < this._extraWorkspaces.length; w++)
this._extraWorkspaces[w].zoomToOverview();
}));
this._overviewShownId =
Main.overview.connect('shown',
Lang.bind(this, function() {
@ -116,21 +99,72 @@ const WorkspacesView = new Lang.Class({
this._fullGeometry.width, this._fullGeometry.height);
}));
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: this._workspaces.length });
this.scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
Lang.bind(this, this._activeWorkspaceChanged));
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
Lang.bind(this, this._dragBegin));
this._itemDragEndId = Main.overview.connect('item-drag-end',
Lang.bind(this, this._dragEnd));
this._windowDragBeginId = Main.overview.connect('window-drag-begin',
Lang.bind(this, this._dragBegin));
this._windowDragEndId = Main.overview.connect('window-drag-end',
Lang.bind(this, this._dragEnd));
},
_setReservedSlot: function(clone) {
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(clone);
_updateExtraWorkspaces: function() {
this._destroyExtraWorkspaces();
if (!this._settings.get_boolean('workspaces-only-on-primary'))
return;
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
if (i == Main.layoutManager.primaryIndex)
continue;
let ws = new Workspace.Workspace(null, i);
ws.setFullGeometry(monitors[i]);
ws.setActualGeometry(monitors[i]);
Main.layoutManager.overviewGroup.add_actor(ws.actor);
this._extraWorkspaces.push(ws);
}
},
_syncGeometry: function() {
_destroyExtraWorkspaces: function() {
for (let m = 0; m < this._extraWorkspaces.length; m++)
this._extraWorkspaces[m].destroy();
this._extraWorkspaces = [];
},
setFullGeometry: function(geom) {
if (rectEqual(this._fullGeometry, geom))
return;
this._fullGeometry = geom;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setFullGeometry(this._fullGeometry);
this._workspaces[i].setFullGeometry(geom);
},
setActualGeometry: function(geom) {
if (rectEqual(this._actualGeometry, geom))
return;
this._actualGeometry = geom;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setActualGeometry(this._actualGeometry);
this._workspaces[i].setActualGeometry(geom);
},
getActiveWorkspace: function() {
@ -138,22 +172,29 @@ const WorkspacesView = new Lang.Class({
return this._workspaces[active];
},
zoomToOverview: function() {
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomToOverview();
this._updateWorkspaceActors(false);
},
hide: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
activeWorkspace.actor.raise_top();
zoomFromOverview: function() {
this.actor.remove_clip();
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomFromOverview();
for (let w = 0; w < this._extraWorkspaces.length; w++)
this._extraWorkspaces[w].zoomFromOverview();
},
destroy: function() {
this.actor.destroy();
},
syncStacking: function(stackIndices) {
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].syncStacking(stackIndices);
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].syncStacking(stackIndices);
},
_scrollToActive: function() {
@ -175,7 +216,7 @@ const WorkspacesView = new Lang.Class({
Tweener.removeTweens(workspace.actor);
let y = (w - active) * this._fullGeometry.height;
let y = (w - active) * (this._fullGeometry.height + this._spacing);
if (showAnimation) {
let params = { y: y,
@ -235,31 +276,25 @@ const WorkspacesView = new Lang.Class({
});
},
_updateWorkspaces: function() {
let oldNumWorkspaces = this._workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
let active = global.screen.get_active_workspace_index();
this.scrollAdjustment.upper = newNumWorkspaces;
Tweener.addTween(this.scrollAdjustment,
{ upper: newNumWorkspaces,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad'
});
if (newNumWorkspaces > oldNumWorkspaces) {
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
let workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
this._workspaces.push(workspace);
this.actor.add_actor(workspace.actor);
this._workspaces[w].setFullGeometry(this._fullGeometry);
if (this._actualGeometry)
this._workspaces[w].setActualGeometry(this._actualGeometry);
this.actor.add_actor(this._workspaces[w].actor);
}
if (this._fullGeometry)
this._updateWorkspaceActors(false);
} else if (newNumWorkspaces < oldNumWorkspaces) {
let nRemoved = (newNumWorkspaces - oldNumWorkspaces);
let removed = this._workspaces.splice(oldNumWorkspaces, nRemoved);
removed.forEach(function(workspace) {
workspace.destroy();
});
this._updateWorkspaceActors(false);
}
this._syncGeometry();
},
_activeWorkspaceChanged: function(wm, from, to, direction) {
@ -270,12 +305,70 @@ const WorkspacesView = new Lang.Class({
},
_onDestroy: function() {
this.parent();
this._destroyExtraWorkspaces();
this.scrollAdjustment.run_dispose();
Main.overview.disconnect(this._overviewShowingId);
Main.overview.disconnect(this._overviewShownId);
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
global.screen.disconnect(this._updateWorkspacesId);
this._settings.disconnect(this._updateExtraWorkspacesId);
if (this._inDrag)
this._dragEnd();
if (this._itemDragBeginId > 0) {
Main.overview.disconnect(this._itemDragBeginId);
this._itemDragBeginId = 0;
}
if (this._itemDragEndId > 0) {
Main.overview.disconnect(this._itemDragEndId);
this._itemDragEndId = 0;
}
if (this._windowDragBeginId > 0) {
Main.overview.disconnect(this._windowDragBeginId);
this._windowDragBeginId = 0;
}
if (this._windowDragEndId > 0) {
Main.overview.disconnect(this._windowDragEndId);
this._windowDragEndId = 0;
}
},
_dragBegin: function() {
if (this._scrolling)
return;
this._inDrag = true;
this._firstDragMotion = true;
this._dragMonitor = {
dragMotion: Lang.bind(this, this._onDragMotion)
};
DND.addDragMonitor(this._dragMonitor);
},
_onDragMotion: function(dragEvent) {
if (Main.overview.animationInProgress)
return DND.DragMotionResult.CONTINUE;
if (this._firstDragMotion) {
this._firstDragMotion = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
}
return DND.DragMotionResult.CONTINUE;
},
_dragEnd: function() {
DND.removeDragMonitor(this._dragMonitor);
this._inDrag = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(null);
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].setReservedSlot(null);
},
startSwipeScroll: function() {
@ -334,42 +427,6 @@ const WorkspacesView = new Lang.Class({
});
Signals.addSignalMethods(WorkspacesView.prototype);
const ExtraWorkspaceView = new Lang.Class({
Name: 'ExtraWorkspaceView',
Extends: WorkspacesViewBase,
_init: function(monitorIndex) {
this.parent(monitorIndex);
this._workspace = new Workspace.Workspace(null, monitorIndex);
this.actor.add_actor(this._workspace.actor);
},
_setReservedSlot: function(clone) {
this._workspace.setReservedSlot(clone);
},
_syncGeometry: function() {
this._workspace.setFullGeometry(this._fullGeometry);
this._workspace.setActualGeometry(this._actualGeometry);
},
zoomToOverview: function() {
this._workspace.zoomToOverview();
},
zoomFromOverview: function() {
this._workspace.zoomFromOverview();
},
syncStacking: function(stackIndices) {
this._workspace.syncStacking(stackIndices);
},
startSwipeScroll: function() {
},
endSwipeScroll: function() {
},
});
const WorkspacesDisplay = new Lang.Class({
Name: 'WorkspacesDisplay',
@ -414,6 +471,7 @@ const WorkspacesDisplay = new Lang.Class({
this._primaryIndex = Main.layoutManager.primaryIndex;
this._workspacesViews = [];
this._workspaces = [];
this._primaryScrollAdjustment = null;
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
@ -422,6 +480,9 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesOnlyOnPrimaryChanged));
this._workspacesOnlyOnPrimaryChanged();
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
this._switchWorkspaceNotifyId = 0;
this._notifyOpacityId = 0;
@ -439,8 +500,6 @@ const WorkspacesDisplay = new Lang.Class({
show: function() {
this._updateWorkspacesViews();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].zoomToOverview();
this._restackedNotifyId =
Main.overview.connect('windows-restacked',
@ -450,8 +509,9 @@ const WorkspacesDisplay = new Lang.Class({
},
zoomFromOverview: function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].zoomFromOverview();
for (let i = 0; i < this._workspacesViews.length; i++) {
this._workspacesViews[i].hide();
}
},
hide: function() {
@ -483,38 +543,46 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesViews[i].destroy();
this._workspacesViews = [];
this._workspaces = [];
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
let view;
if (this._workspacesOnlyOnPrimary && i != this._primaryIndex)
view = new ExtraWorkspaceView(i);
else
view = new WorkspacesView(i);
continue; // we are only interested in the primary monitor
let monitorWorkspaces = [];
for (let w = 0; w < global.screen.n_workspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
monitorWorkspaces.push(new Workspace.Workspace(metaWorkspace, i));
}
this._workspaces.push(monitorWorkspaces);
let view = new WorkspacesView(monitorWorkspaces);
view.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
if (i == this._primaryIndex) {
if (this._workspacesOnlyOnPrimary || i == this._primaryIndex) {
this._scrollAdjustment = view.scrollAdjustment;
this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._scrollValueChanged));
}
this._workspacesViews.push(view);
Main.layoutManager.overviewGroup.add_actor(view.actor);
}
this._updateWorkspacesFullGeometry();
this._updateWorkspacesActualGeometry();
for (let i = 0; i < this._workspacesViews.length; i++)
Main.layoutManager.overviewGroup.add_actor(this._workspacesViews[i].actor);
},
_scrollValueChanged: function() {
if (this._workspacesOnlyOnPrimary)
return;
for (let i = 0; i < this._workspacesViews.length; i++) {
if (i == this._primaryIndex)
continue;
let adjustment = this._workspacesViews[i].scrollAdjustment;
if (!adjustment)
continue;
// the adjustments work in terms of workspaces, so the
// values map directly
adjustment.value = this._scrollAdjustment.value;
@ -524,7 +592,10 @@ const WorkspacesDisplay = new Lang.Class({
_getPrimaryView: function() {
if (!this._workspacesViews.length)
return null;
return this._workspacesViews[this._primaryIndex];
if (this._workspacesOnlyOnPrimary)
return this._workspacesViews[0];
else
return this._workspacesViews[this._primaryIndex];
},
activeWorkspaceHasMaximizedWindows: function() {
@ -570,9 +641,15 @@ const WorkspacesDisplay = new Lang.Class({
return;
let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
let geometry = (i == this._primaryIndex) ? this._fullGeometry : monitors[i];
this._workspacesViews[i].setFullGeometry(geometry);
if (i == this._primaryIndex) {
this._workspacesViews[m].setFullGeometry(this._fullGeometry);
m++;
} else if (!this._workspacesOnlyOnPrimary) {
this._workspacesViews[m].setFullGeometry(monitors[i]);
m++;
}
}
},
@ -583,12 +660,18 @@ const WorkspacesDisplay = new Lang.Class({
let [x, y] = this.actor.get_transformed_position();
let width = this.actor.allocation.x2 - this.actor.allocation.x1;
let height = this.actor.allocation.y2 - this.actor.allocation.y1;
let primaryGeometry = { x: x, y: y, width: width, height: height };
let geometry = { x: x, y: y, width: width, height: height };
let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
let geometry = (i == this._primaryIndex) ? primaryGeometry : monitors[i];
this._workspacesViews[i].setActualGeometry(geometry);
if (i == this._primaryIndex) {
this._workspacesViews[m].setActualGeometry(geometry);
m++;
} else if (!this._workspacesOnlyOnPrimary) {
this._workspacesViews[m].setActualGeometry(monitors[i]);
m++;
}
}
},
@ -597,6 +680,60 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesViews[i].syncStacking(stackIndices);
},
_workspacesChanged: function() {
if (!this._workspacesViews.length)
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;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
if (this._workspacesOnlyOnPrimary &&
i != this._primaryIndex)
continue;
// Assume workspaces are only added at the end
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
this._workspaces[m][w] =
new Workspace.Workspace(metaWorkspace, i);
}
m++;
}
} else {
// Assume workspaces are only removed sequentially
// (e.g. 2,3,4 - not 2,4,7)
let removedIndex;
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
if (this._workspaces[0][w].metaWorkspace != metaWorkspace) {
removedIndex = w;
break;
}
}
for (let i = 0; i < this._workspaces.length; i++) {
lostWorkspaces = this._workspaces[i].splice(removedIndex,
removedNum);
for (let l = 0; l < lostWorkspaces.length; l++) {
lostWorkspaces[l].disconnectAll();
lostWorkspaces[l].destroy();
}
}
}
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces,
newNumWorkspaces);
},
_onScrollEvent: function(actor, event) {
if (!this.actor.mapped)
return false;

View File

@ -38,7 +38,7 @@ js/ui/panel.js
js/ui/popupMenu.js
js/ui/runDialog.js
js/ui/screenShield.js
js/ui/search.js
js/ui/searchDisplay.js
js/ui/shellEntry.js
js/ui/shellMountOperation.js
js/ui/status/accessibility.js
@ -52,6 +52,7 @@ js/ui/status/system.js
js/ui/status/volume.js
js/ui/unlockDialog.js
js/ui/viewSelector.js
js/ui/wanda.js
js/ui/windowAttentionHandler.js
js/ui/windowManager.js
src/calendar-server/evolution-calendar.desktop.in.in

320
po/be.po
View File

@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: gnome-shell.master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-10-02 17:58+0000\n"
"POT-Creation-Date: 2013-10-15 18:32+0000\n"
"PO-Revision-Date: 2012-10-16 12:05+0300\n"
"Last-Translator: Kasia Bondarava <kasia.bondarava@gmail.com>\n"
"Language-Team: Belarusian <i18n-bel-gnome@googlegroups.com>\n"
@ -273,23 +273,23 @@ msgstr ""
"Абярыце пашырэнне, каб настроіць графу з выплыўным спісам, якая знаходзіцца "
"вышэй."
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:136
#: ../js/gdm/authPrompt.js:146 ../js/ui/components/networkAgent.js:136
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/network.js:692
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:739
msgid "Cancel"
msgstr "Скасаваць"
#: ../js/gdm/authPrompt.js:167 ../js/gdm/authPrompt.js:215
#: ../js/gdm/authPrompt.js:168 ../js/gdm/authPrompt.js:216
msgid "Next"
msgstr "Далей"
#: ../js/gdm/authPrompt.js:211 ../js/ui/shellMountOperation.js:403
#: ../js/gdm/authPrompt.js:212 ../js/ui/shellMountOperation.js:403
#: ../js/ui/unlockDialog.js:59
msgid "Unlock"
msgstr "Разблакіраваць"
#: ../js/gdm/authPrompt.js:213
#: ../js/gdm/authPrompt.js:214
msgctxt "button"
msgid "Sign In"
msgstr "Увайсці"
@ -316,23 +316,23 @@ msgstr "Імя карыстальніка: "
msgid "Login Window"
msgstr "Акно ўваходу"
#: ../js/gdm/util.js:306
#: ../js/gdm/util.js:321
msgid "Authentication error"
msgstr "Памылка ідэнтыфікацыі"
#: ../js/gdm/util.js:436
#: ../js/gdm/util.js:451
msgid "(or swipe finger)"
msgstr "(або правядзіце пальцам)"
#: ../js/misc/util.js:98
#: ../js/misc/util.js:115
msgid "Command not found"
msgstr "Загад не знойдзены"
#: ../js/misc/util.js:131
#: ../js/misc/util.js:148
msgid "Could not parse command:"
msgstr "Не ўдалося разабраць загад:"
#: ../js/misc/util.js:139
#: ../js/misc/util.js:156
#, javascript-format
msgid "Execution of '%s' failed:"
msgstr "Не ўдалося выканаць \"%s\":"
@ -349,15 +349,15 @@ msgstr "Часта"
msgid "All"
msgstr "Усе"
#: ../js/ui/appDisplay.js:1514
#: ../js/ui/appDisplay.js:1523
msgid "New Window"
msgstr "Новае акно"
#: ../js/ui/appDisplay.js:1517 ../js/ui/dash.js:284
#: ../js/ui/appDisplay.js:1526 ../js/ui/dash.js:284
msgid "Remove from Favorites"
msgstr "Выдаліць са спіса ўпадабанага"
#: ../js/ui/appDisplay.js:1518
#: ../js/ui/appDisplay.js:1527
msgid "Add to Favorites"
msgstr "Дадаць у спіс упадабанага"
@ -371,7 +371,7 @@ msgstr "%s дададзены ў ваш спіс упадабанага."
msgid "%s has been removed from your favorites."
msgstr "%s выдалены з вашага спіса ўпадабанага."
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:808
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:806
#: ../js/ui/status/system.js:325
msgid "Settings"
msgstr "Настройкі"
@ -562,16 +562,16 @@ msgstr "Адкрыць у %s"
msgid "Eject"
msgstr "Выняць"
#: ../js/ui/components/keyring.js:91 ../js/ui/components/polkitAgent.js:280
#: ../js/ui/components/keyring.js:89 ../js/ui/components/polkitAgent.js:280
msgid "Password:"
msgstr "Пароль:"
#: ../js/ui/components/keyring.js:110
#: ../js/ui/components/keyring.js:108
msgid "Type again:"
msgstr "Паўтарыце пароль:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:112
#: ../js/ui/status/network.js:275 ../js/ui/status/network.js:695
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:742
msgid "Connect"
msgstr "Злучыць"
@ -667,60 +667,60 @@ msgstr "Ідэнтыфікаваць"
msgid "Sorry, that didn't work. Please try again."
msgstr "На жаль, ідэнтыфікацыя не адбылася. Паўтарыце спробу."
#: ../js/ui/components/telepathyClient.js:238
#: ../js/ui/components/telepathyClient.js:237
msgid "Invitation"
msgstr "Запрашэнне"
#: ../js/ui/components/telepathyClient.js:298
#: ../js/ui/components/telepathyClient.js:297
msgid "Call"
msgstr "Званок"
#: ../js/ui/components/telepathyClient.js:314
#: ../js/ui/components/telepathyClient.js:313
msgid "File Transfer"
msgstr "Перадача файла"
#: ../js/ui/components/telepathyClient.js:418
#: ../js/ui/components/telepathyClient.js:417
msgid "Chat"
msgstr "Чат"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Unmute"
msgstr "Вярнуць гук"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Mute"
msgstr "Абязгучыць"
#. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/
#: ../js/ui/components/telepathyClient.js:942
#: ../js/ui/components/telepathyClient.js:941
msgid "<b>Yesterday</b>, <b>%H:%M</b>"
msgstr "<b>Учора</b>, <b>%H:%M</b>"
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/
#: ../js/ui/components/telepathyClient.js:948
#: ../js/ui/components/telepathyClient.js:947
msgid "<b>%A</b>, <b>%H:%M</b>"
msgstr "<b>%A</b>, <b>%H:%M</b>"
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/
#: ../js/ui/components/telepathyClient.js:953
#: ../js/ui/components/telepathyClient.js:952
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>"
msgstr "<b>%d</b> <b>%B</b>, <b>%H:%M</b>"
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/
#: ../js/ui/components/telepathyClient.js:957
#: ../js/ui/components/telepathyClient.js:956
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "
msgstr "<b>%d</b> <b>%B</b> <b>%Y</b>, <b>%H:%M</b> "
#. Translators: this is the other person changing their old IM name to their new
#. IM name. */
#: ../js/ui/components/telepathyClient.js:986
#: ../js/ui/components/telepathyClient.js:985
#, javascript-format
msgid "%s is now known as %s"
msgstr "%s змяніў імя на %s"
#. translators: argument is a room name like
#. * room@jabber.org for example. */
#: ../js/ui/components/telepathyClient.js:1089
#: ../js/ui/components/telepathyClient.js:1088
#, javascript-format
msgid "Invitation to %s"
msgstr "Запрашэнне ў %s"
@ -728,38 +728,38 @@ msgstr "Запрашэнне ў %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example. */
#: ../js/ui/components/telepathyClient.js:1097
#: ../js/ui/components/telepathyClient.js:1096
#, javascript-format
msgid "%s is inviting you to join %s"
msgstr "Удзельнік %s запрашае вас далучыцца да %s"
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1140
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
msgid "Decline"
msgstr "Адмовіцца"
#: ../js/ui/components/telepathyClient.js:1100
#: ../js/ui/components/telepathyClient.js:1181
#: ../js/ui/components/telepathyClient.js:1244
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
msgid "Accept"
msgstr "Прыняць"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1130
#: ../js/ui/components/telepathyClient.js:1129
#, javascript-format
msgid "Video call from %s"
msgstr "Відэазванок ад %s"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1133
#: ../js/ui/components/telepathyClient.js:1132
#, javascript-format
msgid "Call from %s"
msgstr "Званок ад %s"
#. translators: this is a button label (verb), not a noun */
#: ../js/ui/components/telepathyClient.js:1142
#: ../js/ui/components/telepathyClient.js:1141
msgid "Answer"
msgstr "Адказаць"
@ -768,108 +768,108 @@ msgstr "Адказаць"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#. */
#: ../js/ui/components/telepathyClient.js:1174
#: ../js/ui/components/telepathyClient.js:1173
#, javascript-format
msgid "%s is sending you %s"
msgstr "%s пасылае вам %s"
#. To translators: The parameter is the contact's alias */
#: ../js/ui/components/telepathyClient.js:1209
#: ../js/ui/components/telepathyClient.js:1208
#, javascript-format
msgid "%s would like permission to see when you are online"
msgstr "%s просіць дазволу на прагляд вашага сеткавага стану"
#: ../js/ui/components/telepathyClient.js:1301
#: ../js/ui/components/telepathyClient.js:1300
msgid "Network error"
msgstr "Сеткавая памылка"
#: ../js/ui/components/telepathyClient.js:1303
#: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed"
msgstr "Няўдалая ідэнтыфікацыя"
#: ../js/ui/components/telepathyClient.js:1305
#: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error"
msgstr "Памылка шыфравання"
#: ../js/ui/components/telepathyClient.js:1307
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided"
msgstr "Сертыфікат не пададзены"
#: ../js/ui/components/telepathyClient.js:1309
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted"
msgstr "Сертыфікат не заслугоўвае даверу"
#: ../js/ui/components/telepathyClient.js:1311
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired"
msgstr "Сертыфікат састарэў"
#: ../js/ui/components/telepathyClient.js:1313
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated"
msgstr "Сертыфікат не актывізаваны"
#: ../js/ui/components/telepathyClient.js:1315
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch"
msgstr "Назва камп'ютара ў сертыфікаце не адпавядае патрэбнай"
#: ../js/ui/components/telepathyClient.js:1317
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch"
msgstr "Адбітак сертыфіката не адпавядае патрэбнаму"
#: ../js/ui/components/telepathyClient.js:1319
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed"
msgstr "Сертыфікат уласнаручна падпісаны"
#: ../js/ui/components/telepathyClient.js:1321
#: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline"
msgstr "Уключаны рэжым па-за сеткай"
#: ../js/ui/components/telepathyClient.js:1323
#: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available"
msgstr "Шыфраванне недаступнае"
#: ../js/ui/components/telepathyClient.js:1325
#: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid"
msgstr "Хібны сертыфікат"
#: ../js/ui/components/telepathyClient.js:1327
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused"
msgstr "Адмоўлена ў злучэнні"
#: ../js/ui/components/telepathyClient.js:1329
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established"
msgstr "Не ўдалося ўсталяваць злучэнне"
#: ../js/ui/components/telepathyClient.js:1331
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost"
msgstr "Злучэнне страчана"
#: ../js/ui/components/telepathyClient.js:1333
#: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server"
msgstr "Гэты конт ужо злучаны з серверам"
#: ../js/ui/components/telepathyClient.js:1335
#: ../js/ui/components/telepathyClient.js:1334
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr "Злучэнне заменена новым для таго ж самага рэсурсу"
#: ../js/ui/components/telepathyClient.js:1337
#: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server"
msgstr "Такі конт ужо існуе на серверы"
#: ../js/ui/components/telepathyClient.js:1339
#: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection"
msgstr "Сервер надта заняты і не можа абслужыць гэта злучэнне"
#: ../js/ui/components/telepathyClient.js:1341
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked"
msgstr "Сертыфікат быў адкліканы"
#: ../js/ui/components/telepathyClient.js:1343
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "Для сертыфіката выкарыстаны слабы або небяспечны алгарытм шыфравання"
#: ../js/ui/components/telepathyClient.js:1345
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -877,22 +877,22 @@ msgstr ""
"Даўжыня сертыфіката сервера або глыбіня яго ланцуга перавышае абмежаванне, "
"выстаўленае крыптаграфічнай бібліятэкай"
#: ../js/ui/components/telepathyClient.js:1347
#: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error"
msgstr "Унутраная памылка"
#. translators: argument is the account name, like
#. * name@jabber.org for example. */
#: ../js/ui/components/telepathyClient.js:1357
#: ../js/ui/components/telepathyClient.js:1356
#, javascript-format
msgid "Unable to connect to %s"
msgstr "Не ўдалося злучыцца з %s"
#: ../js/ui/components/telepathyClient.js:1362
#: ../js/ui/components/telepathyClient.js:1361
msgid "View account"
msgstr "Праглядзець конт"
#: ../js/ui/components/telepathyClient.js:1401
#: ../js/ui/components/telepathyClient.js:1400
msgid "Unknown reason"
msgstr "Невядомая прычына"
@ -1072,9 +1072,12 @@ msgstr "Паказваць памылкі"
msgid "Enabled"
msgstr "Уключана"
#. Translators: this is for a network device that cannot be activated
#. because it's disabled by rfkill (airplane mode) */
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:765 ../src/gvc/gvc-mixer-control.c:1830
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:472
#: ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Выключана"
@ -1098,44 +1101,48 @@ msgstr "Паглядзець выточны код"
msgid "Web Page"
msgstr "Сеціўная старонка"
#: ../js/ui/messageTray.js:1222
#: ../js/ui/messageTray.js:1347
msgid "Open"
msgstr "Адкрыць"
#: ../js/ui/messageTray.js:1229
#: ../js/ui/messageTray.js:1354
msgid "Remove"
msgstr "Выдаліць"
#: ../js/ui/messageTray.js:1513
#: ../js/ui/messageTray.js:1657
msgid "Notifications"
msgstr "Апавяшчэнні"
#: ../js/ui/messageTray.js:1664
msgid "Clear Messages"
msgstr "Ачысціць спіс апавяшчэнняў"
#: ../js/ui/messageTray.js:1540
#: ../js/ui/messageTray.js:1683
msgid "Notification Settings"
msgstr "Настройкі апавяшчэння"
#: ../js/ui/messageTray.js:1559
#: ../js/ui/messageTray.js:1736
msgid "Tray Menu"
msgstr "Меню трэя"
#: ../js/ui/messageTray.js:1775
#: ../js/ui/messageTray.js:1952
msgid "No Messages"
msgstr "Апавяшчэнні адсутнічаюць"
#: ../js/ui/messageTray.js:1813
#: ../js/ui/messageTray.js:1990
msgid "Message Tray"
msgstr "Абшар апавяшчэнняў"
#: ../js/ui/messageTray.js:2788
#: ../js/ui/messageTray.js:2965
msgid "System Information"
msgstr "Сістэмная інфармацыя"
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:396
#: ../js/ui/notificationDaemon.js:510 ../src/shell-app.c:396
msgctxt "program"
msgid "Unknown"
msgstr "Невядомая"
#: ../js/ui/overviewControls.js:491 ../js/ui/screenShield.js:152
#: ../js/ui/overviewControls.js:488 ../js/ui/screenShield.js:153
#, javascript-format
msgid "%d new message"
msgid_plural "%d new messages"
@ -1159,21 +1166,21 @@ msgstr "Агляд"
msgid "Type to search…"
msgstr "Увядзіце тэкст для пошуку..."
#: ../js/ui/panel.js:518
#: ../js/ui/panel.js:516
msgid "Quit"
msgstr "Выйсці"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". */
#: ../js/ui/panel.js:570
#: ../js/ui/panel.js:568
msgid "Activities"
msgstr "Заняткі"
#: ../js/ui/panel.js:904
#: ../js/ui/panel.js:900
msgid "Top Bar"
msgstr "Верхняя панэль"
#: ../js/ui/popupMenu.js:233
#: ../js/ui/popupMenu.js:260
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
@ -1187,11 +1194,11 @@ msgstr "Закрыць"
#. Translators: This is a time format for a date in
#. long format */
#: ../js/ui/screenShield.js:88
#: ../js/ui/screenShield.js:89
msgid "%A, %B %d"
msgstr "%A, %d %B"
#: ../js/ui/screenShield.js:154
#: ../js/ui/screenShield.js:155
#, javascript-format
msgid "%d new notification"
msgid_plural "%d new notifications"
@ -1199,19 +1206,19 @@ msgstr[0] "%d новае апавяшчэнне"
msgstr[1] "%d новыя апавяшчэнні"
msgstr[2] "%d новых апавяшчэнняў"
#: ../js/ui/screenShield.js:477 ../js/ui/status/system.js:333
#: ../js/ui/screenShield.js:478 ../js/ui/status/system.js:333
msgid "Lock"
msgstr "Заблакіраваць"
#: ../js/ui/screenShield.js:704
#: ../js/ui/screenShield.js:712
msgid "GNOME needs to lock the screen"
msgstr "GNOME патрабуе блакіравання экрана"
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
#: ../js/ui/screenShield.js:839 ../js/ui/screenShield.js:1305
msgid "Unable to lock"
msgstr "Не ўдалося заблакіраваць"
#: ../js/ui/screenShield.js:832 ../js/ui/screenShield.js:1298
#: ../js/ui/screenShield.js:840 ../js/ui/screenShield.js:1306
msgid "Lock was blocked by an application"
msgstr "Блакіраванне стрымана праграмай"
@ -1251,62 +1258,62 @@ msgstr "Запомніць пароль"
msgid "Accessibility"
msgstr "Даступнасць"
#: ../js/ui/status/accessibility.js:58
#: ../js/ui/status/accessibility.js:56
msgid "Zoom"
msgstr "Маштабаванне"
#: ../js/ui/status/accessibility.js:65
#: ../js/ui/status/accessibility.js:63
msgid "Screen Reader"
msgstr "Чытальнік з экрана"
#: ../js/ui/status/accessibility.js:69
#: ../js/ui/status/accessibility.js:67
msgid "Screen Keyboard"
msgstr "Экранная клавіятура"
#: ../js/ui/status/accessibility.js:73
#: ../js/ui/status/accessibility.js:71
msgid "Visual Alerts"
msgstr "Візуальныя сігналы"
#: ../js/ui/status/accessibility.js:76
#: ../js/ui/status/accessibility.js:74
msgid "Sticky Keys"
msgstr "Грузкія клавішы"
#: ../js/ui/status/accessibility.js:79
#: ../js/ui/status/accessibility.js:77
msgid "Slow Keys"
msgstr "Марудныя клавішы"
#: ../js/ui/status/accessibility.js:82
#: ../js/ui/status/accessibility.js:80
msgid "Bounce Keys"
msgstr "Рыкашэтныя клавішы"
#: ../js/ui/status/accessibility.js:85
#: ../js/ui/status/accessibility.js:83
msgid "Mouse Keys"
msgstr "Мышыныя клавішы"
#: ../js/ui/status/accessibility.js:144
#: ../js/ui/status/accessibility.js:142
msgid "High Contrast"
msgstr "Высокая кантраснасць"
#: ../js/ui/status/accessibility.js:193
#: ../js/ui/status/accessibility.js:191
msgid "Large Text"
msgstr "Буйны тэкст"
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:63
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
#: ../js/ui/status/bluetooth.js:164 ../js/ui/status/bluetooth.js:195
#: ../js/ui/status/bluetooth.js:27 ../js/ui/status/bluetooth.js:62
#: ../js/ui/status/bluetooth.js:99 ../js/ui/status/bluetooth.js:127
#: ../js/ui/status/bluetooth.js:163 ../js/ui/status/bluetooth.js:194
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:30 ../js/ui/status/network.js:112
#: ../js/ui/status/network.js:1040 ../js/ui/status/rfkill.js:46
#: ../js/ui/status/bluetooth.js:29 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:1099 ../js/ui/status/rfkill.js:46
msgid "Turn Off"
msgstr "Выключыць"
#: ../js/ui/status/bluetooth.js:33
#: ../js/ui/status/bluetooth.js:32
msgid "Bluetooth Settings"
msgstr "Настройкі Bluetooth"
#: ../js/ui/status/bluetooth.js:58
#: ../js/ui/status/bluetooth.js:57
#, javascript-format
msgid "%d Connected Device"
msgid_plural "%d Connected Devices"
@ -1314,73 +1321,73 @@ msgstr[0] "%d злучанае прыстасаванне"
msgstr[1] "%d злучаныя прыстасаванні"
msgstr[2] "%d злучаных прыстасаванняў"
#: ../js/ui/status/bluetooth.js:101 ../js/ui/status/bluetooth.js:129
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
#, javascript-format
msgid "Authorization request from %s"
msgstr "Запыт на ўпаўнаважанне ад %s"
#: ../js/ui/status/bluetooth.js:107 ../js/ui/status/bluetooth.js:172
#: ../js/ui/status/bluetooth.js:203
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/bluetooth.js:171
#: ../js/ui/status/bluetooth.js:202
#, javascript-format
msgid "Device %s wants to pair with this computer"
msgstr "Прыстасаванне %s хоча спарыцца з гэтым камп'ютарам"
#: ../js/ui/status/bluetooth.js:109
#: ../js/ui/status/bluetooth.js:108
msgid "Allow"
msgstr "Дазволіць"
#: ../js/ui/status/bluetooth.js:110
#: ../js/ui/status/bluetooth.js:109
msgid "Deny"
msgstr "Адмовіць"
#: ../js/ui/status/bluetooth.js:135
#: ../js/ui/status/bluetooth.js:134
#, javascript-format
msgid "Device %s wants access to the service '%s'"
msgstr "Прыстасаванне %s хоча даступіцца да паслугі \"%s\""
#: ../js/ui/status/bluetooth.js:137
#: ../js/ui/status/bluetooth.js:136
msgid "Always grant access"
msgstr "Заўсёды даваць дазвол"
#: ../js/ui/status/bluetooth.js:138
#: ../js/ui/status/bluetooth.js:137
msgid "Grant this time only"
msgstr "Даць дазвол аднойчы"
#: ../js/ui/status/bluetooth.js:139
#: ../js/ui/status/bluetooth.js:138
msgid "Reject"
msgstr "Адмовіць"
#. Translators: argument is the device short name */
#: ../js/ui/status/bluetooth.js:166
#: ../js/ui/status/bluetooth.js:165
#, javascript-format
msgid "Pairing confirmation for %s"
msgstr "Пацвярджэнне спарвання з %s"
#: ../js/ui/status/bluetooth.js:173
#: ../js/ui/status/bluetooth.js:172
#, javascript-format
msgid ""
"Please confirm whether the Passkey '%06d' matches the one on the device."
msgstr "Праверце, ці супадае пароль \"%06d\" з нумарам на прыстасаванні."
#. Translators: this is the verb, not the noun */
#: ../js/ui/status/bluetooth.js:176
#: ../js/ui/status/bluetooth.js:175
msgid "Matches"
msgstr "Супадае"
#: ../js/ui/status/bluetooth.js:177
#: ../js/ui/status/bluetooth.js:176
msgid "Does not match"
msgstr "Не супадае"
#: ../js/ui/status/bluetooth.js:196
#: ../js/ui/status/bluetooth.js:195
#, javascript-format
msgid "Pairing request for %s"
msgstr "Запыт на спарванне з %s"
#: ../js/ui/status/bluetooth.js:204
#: ../js/ui/status/bluetooth.js:203
msgid "Please enter the PIN mentioned on the device."
msgstr "Увядзіце PIN, які паказвае прыстасаванне."
#: ../js/ui/status/bluetooth.js:221
#: ../js/ui/status/bluetooth.js:220
msgid "OK"
msgstr "Добра"
@ -1388,87 +1395,99 @@ msgstr "Добра"
msgid "Brightness"
msgstr "Яркасць"
#: ../js/ui/status/network.js:72
#: ../js/ui/status/network.js:71
msgid "<unknown>"
msgstr "<невядома>"
#: ../js/ui/status/network.js:203 ../js/ui/status/network.js:1055
#: ../js/ui/status/network.js:222 ../js/ui/status/network.js:379
#: ../js/ui/status/network.js:1120
msgid "Off"
msgstr "Выключана"
#: ../js/ui/status/network.js:276 ../js/ui/status/network.js:961
#: ../js/ui/status/rfkill.js:49
msgid "Network Settings"
msgstr "Сеткавыя настройкі"
#. 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:364
#: ../js/ui/status/network.js:385
msgid "unmanaged"
msgstr "непадкантрольна"
#: ../js/ui/status/network.js:366
#: ../js/ui/status/network.js:387
msgid "disconnecting..."
msgstr "адлучэнне..."
#: ../js/ui/status/network.js:372 ../js/ui/status/network.js:1106
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1174
msgid "connecting..."
msgstr "усталяванне злучэння..."
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:375 ../js/ui/status/network.js:1109
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1177
msgid "authentication required"
msgstr "патрэбная ідэнтыфікацыя"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing */
#: ../js/ui/status/network.js:383
#: ../js/ui/status/network.js:404
msgid "firmware missing"
msgstr "няма апаратнага апраграмавання"
#. 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:387
#: ../js/ui/status/network.js:408
msgid "unavailable"
msgstr "недаступна"
#: ../js/ui/status/network.js:389 ../js/ui/status/network.js:1111
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1179
msgid "connection failed"
msgstr "не ўдалося злучыцца"
#: ../js/ui/status/network.js:660
#: ../js/ui/status/network.js:426 ../js/ui/status/network.js:512
msgid "Mobile Broadband Settings"
msgstr "Настройкі шырокапалоснай мабільнай сеткі"
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1118
msgid "Hardware Disabled"
msgstr "Апаратура выключана"
#: ../js/ui/status/network.js:707
msgid "Wi-Fi Networks"
msgstr "Сеткі Wi-Fi"
#: ../js/ui/status/network.js:662
#: ../js/ui/status/network.js:709
msgid "Select a network"
msgstr "Выберыце сетку"
#: ../js/ui/status/network.js:686
#: ../js/ui/status/network.js:733
msgid "No Networks"
msgstr "Няма сетак"
#: ../js/ui/status/network.js:955
#: ../js/ui/status/network.js:1005
msgid "Select Network"
msgstr "Выбраць сетку"
#: ../js/ui/status/network.js:1040
#: ../js/ui/status/network.js:1011
msgid "Wi-Fi Settings"
msgstr "Настройкі Wi-Fi"
#: ../js/ui/status/network.js:1099
msgid "Turn On"
msgstr "Уключыць"
#: ../js/ui/status/network.js:1174
#: ../js/ui/status/network.js:1122
msgid "Not Connected"
msgstr "Няма злучэння"
#: ../js/ui/status/network.js:1242
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1314
#: ../js/ui/status/network.js:1382
msgid "Network Manager"
msgstr "Сеткавы кіраўнік"
#: ../js/ui/status/network.js:1353
#: ../js/ui/status/network.js:1421
msgid "Connection failed"
msgstr "Не ўдалося злучыцца"
#: ../js/ui/status/network.js:1354
#: ../js/ui/status/network.js:1422
msgid "Activation of network connection failed"
msgstr "Не ўдалося ўключыць сеткавае злучэнне"
@ -1506,6 +1525,10 @@ msgstr "Рэжым самалёта"
msgid "On"
msgstr "Укл."
#: ../js/ui/status/rfkill.js:49
msgid "Network Settings"
msgstr "Сеткавыя настройкі"
#: ../js/ui/status/system.js:305
msgid "Switch User"
msgstr "Перамяніць карыстальніка"
@ -1656,4 +1679,3 @@ msgstr "Пароль не можа быць пустым"
#: ../src/shell-polkit-authentication-agent.c:343
msgid "Authentication dialog was dismissed by the user"
msgstr "Карыстальнік праігнараваў дыялогавае акенца ідэнтыфікацыі"

856
po/de.po

File diff suppressed because it is too large Load Diff

433
po/el.po

File diff suppressed because it is too large Load Diff

452
po/he.po

File diff suppressed because it is too large Load Diff

352
po/nb.po
View File

@ -6,10 +6,10 @@
# Torstein Adolf Winterseth <kvikende@fsfe.org>, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 3.11.x\n"
"Project-Id-Version: gnome-shell 3.10.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-11-03 16:01+0100\n"
"PO-Revision-Date: 2013-11-03 16:03+0100\n"
"POT-Creation-Date: 2013-10-20 13:05+0200\n"
"PO-Revision-Date: 2013-10-26 15:17+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
"Language: \n"
@ -52,7 +52,6 @@ msgid "Window management and application launching"
msgstr "Vindushåndtering og oppstart av programmer"
#: ../data/gnome-shell-extension-prefs.desktop.in.in.h:1
#: ../js/extensionPrefs/main.js:155
msgid "GNOME Shell Extension Preferences"
msgstr "Brukervalg for GNOME Shell utvidelser"
@ -252,23 +251,14 @@ msgstr "Arbeidsområder vises kun på hovedskjerm"
msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr ""
#: ../js/extensionPrefs/main.js:127
#, javascript-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "Det oppsto en feil ved lasting av brukervalgdialog for %s:"
#: ../js/extensionPrefs/main.js:167
msgid "Extension"
msgstr "Utvidelse"
#: ../js/extensionPrefs/main.js:191
#: ../js/extensionPrefs/main.js:189
msgid "Select an extension to configure using the combobox above."
msgstr "Velg en utvidelse som skal konfigureres med komboboksen over."
#: ../js/gdm/authPrompt.js:146 ../js/ui/components/networkAgent.js:136
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:357
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:726
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:739
msgid "Cancel"
msgstr "Avbryt"
@ -286,25 +276,25 @@ msgctxt "button"
msgid "Sign In"
msgstr "Logg inn"
#: ../js/gdm/loginDialog.js:272
#: ../js/gdm/loginDialog.js:294
msgid "Choose Session"
msgstr "Velg økt"
#: ../js/gdm/loginDialog.js:432
#: ../js/gdm/loginDialog.js:454
msgid "Not listed?"
msgstr "Ikke listet?"
#: ../js/gdm/loginDialog.js:600
#: ../js/gdm/loginDialog.js:622
#, javascript-format
msgid "(e.g., user or %s)"
msgstr "(f.eks. bruker eller %s)"
#: ../js/gdm/loginDialog.js:605 ../js/ui/components/networkAgent.js:259
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:259
#: ../js/ui/components/networkAgent.js:277
msgid "Username: "
msgstr "Brukernavn: "
#: ../js/gdm/loginDialog.js:869
#: ../js/gdm/loginDialog.js:891
msgid "Login Window"
msgstr "Innloggingsvindu"
@ -333,23 +323,23 @@ msgstr "Kjøring av «%s» feilet:"
msgid "Frequently used applications will appear here"
msgstr "Ofte brukte programmer vil vises her"
#: ../js/ui/appDisplay.js:715
#: ../js/ui/appDisplay.js:712
msgid "Frequent"
msgstr "Ofte"
#: ../js/ui/appDisplay.js:722
#: ../js/ui/appDisplay.js:719
msgid "All"
msgstr "Alle"
#: ../js/ui/appDisplay.js:1526
#: ../js/ui/appDisplay.js:1523
msgid "New Window"
msgstr "Nytt vindu"
#: ../js/ui/appDisplay.js:1529 ../js/ui/dash.js:284
#: ../js/ui/appDisplay.js:1526 ../js/ui/dash.js:284
msgid "Remove from Favorites"
msgstr "Fjern fra favoritter"
#: ../js/ui/appDisplay.js:1530
#: ../js/ui/appDisplay.js:1527
msgid "Add to Favorites"
msgstr "Legg til i favoritter"
@ -364,7 +354,7 @@ msgid "%s has been removed from your favorites."
msgstr "%s ble fjernet fra dine favoritter."
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:806
#: ../js/ui/status/system.js:334
#: ../js/ui/status/system.js:325
msgid "Settings"
msgstr "Innstillinger"
@ -488,48 +478,48 @@ msgctxt "list saturday"
msgid "S"
msgstr "Lø"
#: ../js/ui/calendar.js:391
#: ../js/ui/calendar.js:389
msgid "calendar:MY"
msgstr ""
#: ../js/ui/calendar.js:449
#: ../js/ui/calendar.js:447
msgid "Previous month"
msgstr "Forrige måned"
#: ../js/ui/calendar.js:459
#: ../js/ui/calendar.js:457
msgid "Next month"
msgstr "Neste måned"
#. Translators: Text to show if there are no events */
#: ../js/ui/calendar.js:755
#: ../js/ui/calendar.js:753
msgid "Nothing Scheduled"
msgstr "Ingenting planlagt"
#. Translators: Shown on calendar heading when selected day occurs on current year */
#: ../js/ui/calendar.js:773
#: ../js/ui/calendar.js:771
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A %B %d"
#. Translators: Shown on calendar heading when selected day occurs on different year */
#: ../js/ui/calendar.js:776
#: ../js/ui/calendar.js:774
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A %B %d, %Y"
#: ../js/ui/calendar.js:787
#: ../js/ui/calendar.js:785
msgid "Today"
msgstr "I dag"
#: ../js/ui/calendar.js:791
#: ../js/ui/calendar.js:789
msgid "Tomorrow"
msgstr "I morgen"
#: ../js/ui/calendar.js:802
#: ../js/ui/calendar.js:800
msgid "This week"
msgstr "Denne uken"
#: ../js/ui/calendar.js:810
#: ../js/ui/calendar.js:808
msgid "Next week"
msgstr "Neste uke"
@ -541,16 +531,16 @@ msgstr "Ekstern stasjon koblet til"
msgid "External drive disconnected"
msgstr "Ekstern stasjon koblet fra"
#: ../js/ui/components/autorunManager.js:296
#: ../js/ui/components/autorunManager.js:294
msgid "Removable Devices"
msgstr "Avtagbare enheter"
#: ../js/ui/components/autorunManager.js:596
#: ../js/ui/components/autorunManager.js:594
#, javascript-format
msgid "Open with %s"
msgstr "Åpne med %s"
#: ../js/ui/components/autorunManager.js:622
#: ../js/ui/components/autorunManager.js:620
msgid "Eject"
msgstr "Løs ut"
@ -563,7 +553,7 @@ msgid "Type again:"
msgstr "Skriv på nytt:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:729
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:742
msgid "Connect"
msgstr "Koble til"
@ -673,11 +663,11 @@ msgstr "Filoverføring"
msgid "Chat"
msgstr "Prat"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Unmute"
msgstr "Fjern demping"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Mute"
msgstr "Demp"
@ -724,32 +714,32 @@ msgid "%s is inviting you to join %s"
msgstr "%s inviterer deg til å bli med i %s"
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1133
#: ../js/ui/components/telepathyClient.js:1167
#: ../js/ui/components/telepathyClient.js:1224
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
msgid "Decline"
msgstr "Avslå"
#: ../js/ui/components/telepathyClient.js:1104
#: ../js/ui/components/telepathyClient.js:1173
#: ../js/ui/components/telepathyClient.js:1229
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
msgid "Accept"
msgstr "Godta"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1123
#: ../js/ui/components/telepathyClient.js:1129
#, javascript-format
msgid "Video call from %s"
msgstr "Videosamtale fra %s"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1126
#: ../js/ui/components/telepathyClient.js:1132
#, javascript-format
msgid "Call from %s"
msgstr "Samtale fra %s"
#. translators: this is a button label (verb), not a noun */
#: ../js/ui/components/telepathyClient.js:1140
#: ../js/ui/components/telepathyClient.js:1141
msgid "Answer"
msgstr "Svar"
@ -758,110 +748,110 @@ msgstr "Svar"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#. */
#: ../js/ui/components/telepathyClient.js:1161
#: ../js/ui/components/telepathyClient.js:1173
#, javascript-format
msgid "%s is sending you %s"
msgstr "%s sender deg %s"
#. To translators: The parameter is the contact's alias */
#: ../js/ui/components/telepathyClient.js:1190
#: ../js/ui/components/telepathyClient.js:1208
#, javascript-format
msgid "%s would like permission to see when you are online"
msgstr "%s vil ha rettigheter til å se når du er tilkoblet"
#: ../js/ui/components/telepathyClient.js:1275
#: ../js/ui/components/telepathyClient.js:1300
msgid "Network error"
msgstr "Nettverksfeil"
#: ../js/ui/components/telepathyClient.js:1277
#: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed"
msgstr "Autentisering feilet"
#: ../js/ui/components/telepathyClient.js:1279
#: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error"
msgstr "Feil ved kryptering"
#: ../js/ui/components/telepathyClient.js:1281
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided"
msgstr "Sertifikat ikke oppgitt"
#: ../js/ui/components/telepathyClient.js:1283
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted"
msgstr "Stoler ikke på sertifikatet"
#: ../js/ui/components/telepathyClient.js:1285
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired"
msgstr "Sertifikatet er utløpt"
#: ../js/ui/components/telepathyClient.js:1287
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated"
msgstr "Sertifikatet er ikke aktivert"
#: ../js/ui/components/telepathyClient.js:1289
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch"
msgstr "Feil vertsnavn for sertifikat"
#: ../js/ui/components/telepathyClient.js:1291
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch"
msgstr "Feil fingeravtrykk for sertifikat"
#: ../js/ui/components/telepathyClient.js:1293
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed"
msgstr "Sertifikatet er selvsignert"
#: ../js/ui/components/telepathyClient.js:1295
#: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline"
msgstr "Status er satt til frakoblet"
#: ../js/ui/components/telepathyClient.js:1297
#: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available"
msgstr "Kryptering er ikke tilgjengelig"
#: ../js/ui/components/telepathyClient.js:1299
#: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid"
msgstr "Sertifikatet er ugyldig"
#: ../js/ui/components/telepathyClient.js:1301
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused"
msgstr "Tilkobling ble nektet"
#: ../js/ui/components/telepathyClient.js:1303
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established"
msgstr "Tilkobling kan ikke etableres"
#: ../js/ui/components/telepathyClient.js:1305
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost"
msgstr "Tilkobling tapt"
#: ../js/ui/components/telepathyClient.js:1307
#: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server"
msgstr "Denne kontoen er allerede koblet til tjeneren"
#: ../js/ui/components/telepathyClient.js:1309
#: ../js/ui/components/telepathyClient.js:1334
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Tilkoblingen har blitt erstattet av en ny tilkobling som bruker samme ressurs"
#: ../js/ui/components/telepathyClient.js:1311
#: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server"
msgstr "Kontoen eksisterer allerede på tjeneren"
#: ../js/ui/components/telepathyClient.js:1313
#: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection"
msgstr "Tjener er for opptatt til å håndtere tilkoblingen"
#: ../js/ui/components/telepathyClient.js:1315
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked"
msgstr "Sertifikatet er tilbaketrukket"
#: ../js/ui/components/telepathyClient.js:1317
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Sertifikatet bruker en usikker sifferalgoritme eller er krytografisk svakt"
#: ../js/ui/components/telepathyClient.js:1319
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -869,26 +859,26 @@ msgstr ""
"Lengden eller dybden på tjenersertifikatet oversteg grensen som er satt i "
"kryptografibiblioteket"
#: ../js/ui/components/telepathyClient.js:1321
#: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error"
msgstr "Intern feil"
#. translators: argument is the account name, like
#. * name@jabber.org for example. */
#: ../js/ui/components/telepathyClient.js:1331
#: ../js/ui/components/telepathyClient.js:1356
#, javascript-format
msgid "Unable to connect to %s"
msgstr "Kan ikke koble til %s"
#: ../js/ui/components/telepathyClient.js:1336
#: ../js/ui/components/telepathyClient.js:1361
msgid "View account"
msgstr "Vis konto"
#: ../js/ui/components/telepathyClient.js:1368
#: ../js/ui/components/telepathyClient.js:1400
msgid "Unknown reason"
msgstr "Ukjent årsak"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:95
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:100
msgid "Windows"
msgstr "Vinduer"
@ -919,76 +909,76 @@ msgstr "Innstillinger for dato og klokkeslett"
msgid "%A %B %e, %Y"
msgstr "%a %e %B, %Y"
#: ../js/ui/endSessionDialog.js:64
#: ../js/ui/endSessionDialog.js:62
#, javascript-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Logg ut %s"
#: ../js/ui/endSessionDialog.js:65
#: ../js/ui/endSessionDialog.js:63
msgctxt "title"
msgid "Log Out"
msgstr "Logg ut"
#: ../js/ui/endSessionDialog.js:67
#: ../js/ui/endSessionDialog.js:65
#, javascript-format
msgid "%s will be logged out automatically in %d second."
msgid_plural "%s will be logged out automatically in %d seconds."
msgstr[0] "%s vil bli logget ut automatisk om %d sekund."
msgstr[1] "%s vil bli logget ut automatisk om %d sekunder."
#: ../js/ui/endSessionDialog.js:72
#: ../js/ui/endSessionDialog.js:70
#, javascript-format
msgid "You will be logged out automatically in %d second."
msgid_plural "You will be logged out automatically in %d seconds."
msgstr[0] "Du vil bli logget ut automatisk om %d sekund."
msgstr[1] "Du vil bli logget ut automatisk om %d sekunder."
#: ../js/ui/endSessionDialog.js:77
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "Logg ut"
#: ../js/ui/endSessionDialog.js:83
#: ../js/ui/endSessionDialog.js:81
msgctxt "title"
msgid "Power Off"
msgstr "Slå av"
#: ../js/ui/endSessionDialog.js:85
#: ../js/ui/endSessionDialog.js:83
#, javascript-format
msgid "The system will power off automatically in %d second."
msgid_plural "The system will power off automatically in %d seconds."
msgstr[0] "Systemet vil slås av automatisk om %d sekund."
msgstr[1] "Systemet vil slås av automatisk om %d sekunder."
#: ../js/ui/endSessionDialog.js:90 ../js/ui/endSessionDialog.js:106
#: ../js/ui/endSessionDialog.js:88 ../js/ui/endSessionDialog.js:104
msgctxt "button"
msgid "Restart"
msgstr "Start på nytt"
#: ../js/ui/endSessionDialog.js:92
#: ../js/ui/endSessionDialog.js:90
msgctxt "button"
msgid "Power Off"
msgstr "Slå av"
#: ../js/ui/endSessionDialog.js:99
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "Start på nytt"
#: ../js/ui/endSessionDialog.js:101
#: ../js/ui/endSessionDialog.js:99
#, javascript-format
msgid "The system will restart automatically in %d second."
msgid_plural "The system will restart automatically in %d seconds."
msgstr[0] "Systemet vil starte på nytt automatisk om %d sekund."
msgstr[1] "Systemet vil starte på nytt automatisk om %d sekunder."
#: ../js/ui/endSessionDialog.js:114
#: ../js/ui/endSessionDialog.js:112
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Start på nytt og installer oppdateringer"
#: ../js/ui/endSessionDialog.js:116
#: ../js/ui/endSessionDialog.js:114
#, javascript-format
msgid "The system will automatically restart and install updates in %d second."
msgid_plural ""
@ -1000,27 +990,27 @@ msgstr[1] ""
"Systemet vil starte på nytt og installere oppdateringer automatisk om %d "
"sekunder."
#: ../js/ui/endSessionDialog.js:121
#: ../js/ui/endSessionDialog.js:119
msgctxt "button"
msgid "Restart & Install"
msgstr "Start på nytt og installer"
#: ../js/ui/endSessionDialog.js:275
#: ../js/ui/endSessionDialog.js:271
msgid "Some applications are busy or have unsaved work."
msgstr "Noen programmer er opptatt eller har arbeid som ikke er lagret."
#: ../js/ui/endSessionDialog.js:282
#: ../js/ui/endSessionDialog.js:277
msgid "Other users are logged in."
msgstr "Andre brukere er logget inn."
#. Translators: Remote here refers to a remote session, like a ssh login */
#: ../js/ui/endSessionDialog.js:485
#: ../js/ui/endSessionDialog.js:479
#, javascript-format
msgid "%s (remote)"
msgstr "%s (ekstern)"
#. Translators: Console here refers to a tty like a VT console */
#: ../js/ui/endSessionDialog.js:488
#: ../js/ui/endSessionDialog.js:482
#, javascript-format
msgid "%s (console)"
msgstr "%s (konsoll)"
@ -1034,29 +1024,29 @@ msgstr "Installer"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Last ned og installer «%s» fra extensions.gnome.org?"
#: ../js/ui/keyboard.js:621 ../js/ui/status/keyboard.js:335
#: ../js/ui/keyboard.js:619
msgid "Keyboard"
msgstr "Tastatur"
#: ../js/ui/lookingGlass.js:640
#: ../js/ui/lookingGlass.js:689
msgid "No extensions installed"
msgstr "Ingen utvidelser installert"
#. Translators: argument is an extension UUID. */
#: ../js/ui/lookingGlass.js:694
#: ../js/ui/lookingGlass.js:743
#, javascript-format
msgid "%s has not emitted any errors."
msgstr "%s har ikke avgitt noen feil."
#: ../js/ui/lookingGlass.js:700
#: ../js/ui/lookingGlass.js:749
msgid "Hide Errors"
msgstr "Skjul feil"
#: ../js/ui/lookingGlass.js:704 ../js/ui/lookingGlass.js:764
#: ../js/ui/lookingGlass.js:753 ../js/ui/lookingGlass.js:813
msgid "Show Errors"
msgstr "Vis feil"
#: ../js/ui/lookingGlass.js:713
#: ../js/ui/lookingGlass.js:762
msgid "Enabled"
msgstr "Aktivert"
@ -1064,73 +1054,73 @@ msgstr "Aktivert"
#. because it's disabled by rfkill (airplane mode) */
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:716 ../js/ui/status/network.js:472
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:472
#: ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Deaktivert"
#: ../js/ui/lookingGlass.js:718
#: ../js/ui/lookingGlass.js:767
msgid "Error"
msgstr "Feil"
#: ../js/ui/lookingGlass.js:720
#: ../js/ui/lookingGlass.js:769
msgid "Out of date"
msgstr "Utdatert"
#: ../js/ui/lookingGlass.js:722
#: ../js/ui/lookingGlass.js:771
msgid "Downloading"
msgstr "Laster ned"
#: ../js/ui/lookingGlass.js:746
#: ../js/ui/lookingGlass.js:795
msgid "View Source"
msgstr "Vis kildekode"
#: ../js/ui/lookingGlass.js:755
#: ../js/ui/lookingGlass.js:804
msgid "Web Page"
msgstr "Nettside"
#: ../js/ui/messageTray.js:1310
#: ../js/ui/messageTray.js:1347
msgid "Open"
msgstr "Åpne"
#: ../js/ui/messageTray.js:1317
#: ../js/ui/messageTray.js:1354
msgid "Remove"
msgstr "Fjern"
#: ../js/ui/messageTray.js:1618
#: ../js/ui/messageTray.js:1657
msgid "Notifications"
msgstr "Varslinger"
#: ../js/ui/messageTray.js:1625
#: ../js/ui/messageTray.js:1664
msgid "Clear Messages"
msgstr "Tøm meldinger"
#: ../js/ui/messageTray.js:1644
#: ../js/ui/messageTray.js:1683
msgid "Notification Settings"
msgstr "Innstillinger for varsling"
#: ../js/ui/messageTray.js:1697
#: ../js/ui/messageTray.js:1736
msgid "Tray Menu"
msgstr "Meny for varslingsområde"
#: ../js/ui/messageTray.js:1913
#: ../js/ui/messageTray.js:1952
msgid "No Messages"
msgstr "Ingen meldinger"
#: ../js/ui/messageTray.js:1951
#: ../js/ui/messageTray.js:1990
msgid "Message Tray"
msgstr "Meldingstrau"
#: ../js/ui/messageTray.js:2929
#: ../js/ui/messageTray.js:2965
msgid "System Information"
msgstr "Systeminformasjon"
#: ../js/ui/notificationDaemon.js:539 ../src/shell-app.c:396
#: ../js/ui/notificationDaemon.js:510 ../src/shell-app.c:396
msgctxt "program"
msgid "Unknown"
msgstr "Ukjent"
#: ../js/ui/overviewControls.js:486 ../js/ui/screenShield.js:153
#: ../js/ui/overviewControls.js:488 ../js/ui/screenShield.js:153
#, javascript-format
msgid "%d new message"
msgid_plural "%d new messages"
@ -1141,7 +1131,7 @@ msgstr[1] "%d nye meldinger"
msgid "Undo"
msgstr "Angre"
#: ../js/ui/overview.js:125
#: ../js/ui/overview.js:127
msgid "Overview"
msgstr "Oversikt"
@ -1149,7 +1139,7 @@ msgstr "Oversikt"
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters. */
#: ../js/ui/overview.js:256
#: ../js/ui/overview.js:258
msgid "Type to search…"
msgstr "Skriv for å søke …"
@ -1192,7 +1182,7 @@ msgid_plural "%d new notifications"
msgstr[0] "%d ny varsling"
msgstr[1] "%d nye varslinger"
#: ../js/ui/screenShield.js:478 ../js/ui/status/system.js:342
#: ../js/ui/screenShield.js:478 ../js/ui/status/system.js:333
msgid "Lock"
msgstr "Lås"
@ -1208,11 +1198,11 @@ msgstr "Kan ikke låse"
msgid "Lock was blocked by an application"
msgstr "Låsing ble stoppet av et program"
#: ../js/ui/search.js:592
#: ../js/ui/searchDisplay.js:448
msgid "Searching…"
msgstr "Søker …"
#: ../js/ui/search.js:635
#: ../js/ui/searchDisplay.js:492
msgid "No results."
msgstr "Ingen resultater."
@ -1291,7 +1281,7 @@ msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:29 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:1083 ../js/ui/status/rfkill.js:48
#: ../js/ui/status/network.js:1099 ../js/ui/status/rfkill.js:46
msgid "Turn Off"
msgstr "Slå av"
@ -1376,20 +1366,16 @@ msgstr "Vennligst oppgi PIN som oppgitt på enheten."
msgid "OK"
msgstr "OK"
#: ../js/ui/status/brightness.js:44
#: ../js/ui/status/brightness.js:42
msgid "Brightness"
msgstr "Lysstyrke"
#: ../js/ui/status/keyboard.js:403
msgid "Show Keyboard Layout"
msgstr "Vis tastaturutforming"
#: ../js/ui/status/network.js:71
msgid "<unknown>"
msgstr "<ukjent>"
#: ../js/ui/status/network.js:222 ../js/ui/status/network.js:379
#: ../js/ui/status/network.js:1104
#: ../js/ui/status/network.js:1120
msgid "Off"
msgstr "Av"
@ -1403,12 +1389,12 @@ msgstr "ikke håndtert"
msgid "disconnecting..."
msgstr "kobler fra …"
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1158
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1174
msgid "connecting..."
msgstr "kobler til …"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1161
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1177
msgid "authentication required"
msgstr "autentisering kreves"
@ -1424,7 +1410,7 @@ msgstr "fastvare mangler"
msgid "unavailable"
msgstr "ikke tilgjengelig"
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1163
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1179
msgid "connection failed"
msgstr "tilkobling feilet"
@ -1432,113 +1418,109 @@ msgstr "tilkobling feilet"
msgid "Mobile Broadband Settings"
msgstr "Innstillinger for mobilt bredbånd"
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1102
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1118
msgid "Hardware Disabled"
msgstr "Maskinvare slått av"
#: ../js/ui/status/network.js:694
#: ../js/ui/status/network.js:707
msgid "Wi-Fi Networks"
msgstr "Wi-Fi nettverk"
#: ../js/ui/status/network.js:696
#: ../js/ui/status/network.js:709
msgid "Select a network"
msgstr "Velg et nettverk"
#: ../js/ui/status/network.js:720
#: ../js/ui/status/network.js:733
msgid "No Networks"
msgstr "Ingen nettverk"
#: ../js/ui/status/network.js:989
#: ../js/ui/status/network.js:1005
msgid "Select Network"
msgstr "Velg nettverk"
#: ../js/ui/status/network.js:995
#: ../js/ui/status/network.js:1011
msgid "Wi-Fi Settings"
msgstr "Innstillinger"
#: ../js/ui/status/network.js:1083
#: ../js/ui/status/network.js:1099
msgid "Turn On"
msgstr "Slå på"
#: ../js/ui/status/network.js:1106
#: ../js/ui/status/network.js:1122
msgid "Not Connected"
msgstr "Ikke koblet til"
#: ../js/ui/status/network.js:1226
#: ../js/ui/status/network.js:1242
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1366
#: ../js/ui/status/network.js:1382
msgid "Network Manager"
msgstr "Nettverkshåndtering"
#: ../js/ui/status/network.js:1405
#: ../js/ui/status/network.js:1421
msgid "Connection failed"
msgstr "Tilkobling feilet"
#: ../js/ui/status/network.js:1406
#: ../js/ui/status/network.js:1422
msgid "Activation of network connection failed"
msgstr "Aktivering av nettverkstilkobling feilet"
#: ../js/ui/status/power.js:49
#: ../js/ui/status/power.js:46
msgid "Battery"
msgstr "Batteri"
#: ../js/ui/status/power.js:47
msgid "Power Settings"
msgstr "Innstillinger for strøm"
#: ../js/ui/status/power.js:65
#: ../js/ui/status/power.js:63
msgid "Fully Charged"
msgstr "Fullt oppladet"
#: ../js/ui/status/power.js:72 ../js/ui/status/power.js:78
#: ../js/ui/status/power.js:69 ../js/ui/status/power.js:86
msgid "Estimating…"
msgstr "Estimerer …"
#: ../js/ui/status/power.js:86
#: ../js/ui/status/power.js:77
#, javascript-format
msgid "%d%02d Remaining (%d%%)"
msgstr "%d:%02d gjenstår (%d%%)"
#: ../js/ui/status/power.js:91
#: ../js/ui/status/power.js:82
#, javascript-format
msgid "%d%02d Until Full (%d%%)"
msgstr "%d:%02d til batteriet er fullt (%d%%)"
#: ../js/ui/status/power.js:119
msgid "UPS"
msgstr "UPS"
#: ../js/ui/status/power.js:121
msgid "Battery"
msgstr "Batteri"
#: ../js/ui/status/rfkill.js:45
#: ../js/ui/status/rfkill.js:43
msgid "Airplane Mode"
msgstr "Flymodus"
#: ../js/ui/status/rfkill.js:47
#: ../js/ui/status/rfkill.js:45
msgid "On"
msgstr "På"
#: ../js/ui/status/rfkill.js:51
#: ../js/ui/status/rfkill.js:49
msgid "Network Settings"
msgstr "Innstillinger for nettverk"
#: ../js/ui/status/system.js:314
#: ../js/ui/status/system.js:305
msgid "Switch User"
msgstr "Bytt bruker"
#: ../js/ui/status/system.js:319
#: ../js/ui/status/system.js:310
msgid "Log Out"
msgstr "Logg ut"
#: ../js/ui/status/system.js:338
#: ../js/ui/status/system.js:329
msgid "Orientation Lock"
msgstr "Lås for orientering"
#: ../js/ui/status/system.js:346
#: ../js/ui/status/system.js:337
msgid "Suspend"
msgstr "Hvilemodus"
#: ../js/ui/status/system.js:349
#: ../js/ui/status/system.js:340
msgid "Power Off"
msgstr "Slå av"
@ -1562,14 +1544,28 @@ msgstr "Logg inn som en annen bruker"
msgid "Unlock Window"
msgstr "Lås opp vindu"
#: ../js/ui/viewSelector.js:99
#: ../js/ui/viewSelector.js:104
msgid "Applications"
msgstr "Programmer"
#: ../js/ui/viewSelector.js:103
#: ../js/ui/viewSelector.js:108
msgid "Search"
msgstr "Søk"
#: ../js/ui/wanda.js:77
#, javascript-format
msgid ""
"Sorry, no wisdom for you today:\n"
"%s"
msgstr ""
"Beklager, ingen visdom til deg i dag:\n"
"%s"
#: ../js/ui/wanda.js:81
#, javascript-format
msgid "%s the Oracle says"
msgstr "Orakelet sier %s"
#: ../js/ui/windowAttentionHandler.js:19
#, javascript-format
msgid "'%s' is ready"
@ -1623,23 +1619,23 @@ msgstr[1] "%u innganger"
msgid "System Sounds"
msgstr "Systemlyder"
#: ../src/main.c:351
#: ../src/main.c:353
msgid "Print version"
msgstr "Skriv ut versjon"
#: ../src/main.c:357
#: ../src/main.c:359
msgid "Mode used by GDM for login screen"
msgstr "Modus som brukes av GDM for innloggingsskjermen"
#: ../src/main.c:363
#: ../src/main.c:365
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "Bruk spesifikt modus, f.eks «gdm» for innloggingsskjerm"
#: ../src/main.c:369
#: ../src/main.c:371
msgid "List possible modes"
msgstr "Vis mulige modi"
#: ../src/shell-app.c:639
#: ../src/shell-app.c:644
#, c-format
msgid "Failed to launch '%s'"
msgstr "Klarte ikke å starte «%s»"

346
po/ru.po
View File

@ -16,8 +16,8 @@ msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-11-01 12:08+0000\n"
"PO-Revision-Date: 2013-11-01 23:32+0400\n"
"POT-Creation-Date: 2013-11-01 12:09+0000\n"
"PO-Revision-Date: 2013-11-01 23:30+0400\n"
"Last-Translator: Yuri Myasoedov <ymyasoedov@yandex.ru>\n"
"Language-Team: Russian <gnome-cyr@gnome.org>\n"
"Language: ru\n"
@ -62,7 +62,6 @@ msgid "Window management and application launching"
msgstr "Управление окнами и запуск приложений"
#: ../data/gnome-shell-extension-prefs.desktop.in.in.h:1
#: ../js/extensionPrefs/main.js:155
msgid "GNOME Shell Extension Preferences"
msgstr "Параметры расширений GNOME Shell"
@ -277,23 +276,14 @@ msgstr "Рабочие места только на основном монит
msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr "Задержка изменения фокуса в режиме мыши после остановки указателя"
#: ../js/extensionPrefs/main.js:127
#, javascript-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "Ошибка загрузки диалога параметров для %s:"
#: ../js/extensionPrefs/main.js:167
msgid "Extension"
msgstr "Расширение"
#: ../js/extensionPrefs/main.js:191
#: ../js/extensionPrefs/main.js:189
msgid "Select an extension to configure using the combobox above."
msgstr "Выберите расширение из выпадающего списка."
#: ../js/gdm/authPrompt.js:146 ../js/ui/components/networkAgent.js:136
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:357
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:726
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:739
msgid "Cancel"
msgstr "Отмена"
@ -311,25 +301,25 @@ msgctxt "button"
msgid "Sign In"
msgstr "Войти"
#: ../js/gdm/loginDialog.js:272
#: ../js/gdm/loginDialog.js:294
msgid "Choose Session"
msgstr "Выбрать сеанс"
#: ../js/gdm/loginDialog.js:432
#: ../js/gdm/loginDialog.js:454
msgid "Not listed?"
msgstr "Нет в списке?"
#: ../js/gdm/loginDialog.js:600
#: ../js/gdm/loginDialog.js:622
#, javascript-format
msgid "(e.g., user or %s)"
msgstr "(например, пользователь или %s)"
#: ../js/gdm/loginDialog.js:605 ../js/ui/components/networkAgent.js:259
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:259
#: ../js/ui/components/networkAgent.js:277
msgid "Username: "
msgstr "Имя пользователя: "
#: ../js/gdm/loginDialog.js:869
#: ../js/gdm/loginDialog.js:891
msgid "Login Window"
msgstr "Окно входа в систему"
@ -358,23 +348,23 @@ msgstr "Не удалось выполнить «%s»:"
msgid "Frequently used applications will appear here"
msgstr "Здесь появляются часто используемые приложения"
#: ../js/ui/appDisplay.js:716
#: ../js/ui/appDisplay.js:712
msgid "Frequent"
msgstr "Популярные"
#: ../js/ui/appDisplay.js:723
#: ../js/ui/appDisplay.js:719
msgid "All"
msgstr "Все"
#: ../js/ui/appDisplay.js:1528
#: ../js/ui/appDisplay.js:1523
msgid "New Window"
msgstr "Новое окно"
#: ../js/ui/appDisplay.js:1531 ../js/ui/dash.js:284
#: ../js/ui/appDisplay.js:1526 ../js/ui/dash.js:284
msgid "Remove from Favorites"
msgstr "Удалить из избранного"
#: ../js/ui/appDisplay.js:1532
#: ../js/ui/appDisplay.js:1527
msgid "Add to Favorites"
msgstr "Добавить в избранное"
@ -513,48 +503,48 @@ msgctxt "list saturday"
msgid "S"
msgstr "Сб"
#: ../js/ui/calendar.js:391
#: ../js/ui/calendar.js:389
msgid "calendar:MY"
msgstr "calendar:MY"
#: ../js/ui/calendar.js:449
#: ../js/ui/calendar.js:447
msgid "Previous month"
msgstr "Предыдущий месяц"
#: ../js/ui/calendar.js:459
#: ../js/ui/calendar.js:457
msgid "Next month"
msgstr "Следующий месяц"
#. Translators: Text to show if there are no events */
#: ../js/ui/calendar.js:755
#: ../js/ui/calendar.js:753
msgid "Nothing Scheduled"
msgstr "Нет событий"
#. Translators: Shown on calendar heading when selected day occurs on current year */
#: ../js/ui/calendar.js:773
#: ../js/ui/calendar.js:771
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %B %d"
#. Translators: Shown on calendar heading when selected day occurs on different year */
#: ../js/ui/calendar.js:776
#: ../js/ui/calendar.js:774
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A, %B %d, %Y"
#: ../js/ui/calendar.js:787
#: ../js/ui/calendar.js:785
msgid "Today"
msgstr "Сегодня"
#: ../js/ui/calendar.js:791
#: ../js/ui/calendar.js:789
msgid "Tomorrow"
msgstr "Завтра"
#: ../js/ui/calendar.js:802
#: ../js/ui/calendar.js:800
msgid "This week"
msgstr "Эта неделя"
#: ../js/ui/calendar.js:810
#: ../js/ui/calendar.js:808
msgid "Next week"
msgstr "Следующая неделя"
@ -566,16 +556,16 @@ msgstr "Внешний диск подключён"
msgid "External drive disconnected"
msgstr "Внешний диск отключён"
#: ../js/ui/components/autorunManager.js:296
#: ../js/ui/components/autorunManager.js:294
msgid "Removable Devices"
msgstr "Съёмные устройства"
#: ../js/ui/components/autorunManager.js:596
#: ../js/ui/components/autorunManager.js:594
#, javascript-format
msgid "Open with %s"
msgstr "Открыть с помощью %s"
#: ../js/ui/components/autorunManager.js:622
#: ../js/ui/components/autorunManager.js:620
msgid "Eject"
msgstr "Извлечь"
@ -588,7 +578,7 @@ msgid "Type again:"
msgstr "Введите ещё раз:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:729
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:742
msgid "Connect"
msgstr "Соединиться"
@ -697,11 +687,11 @@ msgstr "Передача файлов"
msgid "Chat"
msgstr "Чат"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Unmute"
msgstr "Восстановить громкость"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Mute"
msgstr "Приглушить звук"
@ -748,32 +738,32 @@ msgid "%s is inviting you to join %s"
msgstr "%s приглашает вас присоединиться к %s"
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1133
#: ../js/ui/components/telepathyClient.js:1167
#: ../js/ui/components/telepathyClient.js:1224
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
msgid "Decline"
msgstr "Отказаться"
#: ../js/ui/components/telepathyClient.js:1104
#: ../js/ui/components/telepathyClient.js:1173
#: ../js/ui/components/telepathyClient.js:1229
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
msgid "Accept"
msgstr "Принять"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1123
#: ../js/ui/components/telepathyClient.js:1129
#, javascript-format
msgid "Video call from %s"
msgstr "Вас вызывает %s по видео"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1126
#: ../js/ui/components/telepathyClient.js:1132
#, javascript-format
msgid "Call from %s"
msgstr "Вас вызывает %s"
#. translators: this is a button label (verb), not a noun */
#: ../js/ui/components/telepathyClient.js:1140
#: ../js/ui/components/telepathyClient.js:1141
msgid "Answer"
msgstr "Ответить"
@ -782,111 +772,111 @@ msgstr "Ответить"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#. */
#: ../js/ui/components/telepathyClient.js:1161
#: ../js/ui/components/telepathyClient.js:1173
#, javascript-format
msgid "%s is sending you %s"
msgstr "%s отправляет вам %s"
#. To translators: The parameter is the contact's alias */
#: ../js/ui/components/telepathyClient.js:1190
#: ../js/ui/components/telepathyClient.js:1208
#, javascript-format
msgid "%s would like permission to see when you are online"
msgstr "%s хотел бы получить разрешение видеть, когда вы в сети"
#: ../js/ui/components/telepathyClient.js:1275
#: ../js/ui/components/telepathyClient.js:1300
msgid "Network error"
msgstr "Ошибка сети"
#: ../js/ui/components/telepathyClient.js:1277
#: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed"
msgstr "Ошибка аутентификации"
#: ../js/ui/components/telepathyClient.js:1279
#: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error"
msgstr "Ошибка шифрования"
#: ../js/ui/components/telepathyClient.js:1281
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided"
msgstr "Сертификат не предоставляется"
#: ../js/ui/components/telepathyClient.js:1283
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted"
msgstr "Недоверенный сертификат"
#: ../js/ui/components/telepathyClient.js:1285
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired"
msgstr "Срок действия сертификата истёк"
#: ../js/ui/components/telepathyClient.js:1287
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated"
msgstr "Сертификат не активирован"
#: ../js/ui/components/telepathyClient.js:1289
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch"
msgstr "Имя узла сертификата не совпадает"
#: ../js/ui/components/telepathyClient.js:1291
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch"
msgstr "Отпечаток сертификата не совпадает"
#: ../js/ui/components/telepathyClient.js:1293
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed"
msgstr "Самоподписанный сертификат"
#: ../js/ui/components/telepathyClient.js:1295
#: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline"
msgstr "Установлен статус «не в сети»"
#: ../js/ui/components/telepathyClient.js:1297
#: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available"
msgstr "Шифрование недоступно"
#: ../js/ui/components/telepathyClient.js:1299
#: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid"
msgstr "Недействительный сертификат"
#: ../js/ui/components/telepathyClient.js:1301
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused"
msgstr "В соединении отказано"
#: ../js/ui/components/telepathyClient.js:1303
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established"
msgstr "Соединение не может быть установлено"
#: ../js/ui/components/telepathyClient.js:1305
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost"
msgstr "Соединение потеряно"
#: ../js/ui/components/telepathyClient.js:1307
#: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server"
msgstr "Эта учётная запись уже подключена к серверу"
#: ../js/ui/components/telepathyClient.js:1309
#: ../js/ui/components/telepathyClient.js:1334
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr "Соединение было заменено новым, используя тот же источник"
#: ../js/ui/components/telepathyClient.js:1311
#: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server"
msgstr "Учётная запись уже существует на сервере"
#: ../js/ui/components/telepathyClient.js:1313
#: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection"
msgstr ""
"Сервер в настоящее время сильно перегружен, чтобы обработать соединение"
#: ../js/ui/components/telepathyClient.js:1315
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked"
msgstr "Сертификат аннулирован"
#: ../js/ui/components/telepathyClient.js:1317
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Сертификат использует небезопасный алгоритм шифрования или он "
"криптографически нестоек"
#: ../js/ui/components/telepathyClient.js:1319
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -894,26 +884,26 @@ msgstr ""
"Длина сертификата сервера, или глубина цепочки сертификатов сервера, "
"превышает пределы, установленные библиотекой криптографии"
#: ../js/ui/components/telepathyClient.js:1321
#: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error"
msgstr "Внутренняя ошибка"
#. translators: argument is the account name, like
#. * name@jabber.org for example. */
#: ../js/ui/components/telepathyClient.js:1331
#: ../js/ui/components/telepathyClient.js:1356
#, javascript-format
msgid "Unable to connect to %s"
msgstr "Не удалось подключиться к %s"
#: ../js/ui/components/telepathyClient.js:1336
#: ../js/ui/components/telepathyClient.js:1361
msgid "View account"
msgstr "Показать учётную запись"
#: ../js/ui/components/telepathyClient.js:1368
#: ../js/ui/components/telepathyClient.js:1400
msgid "Unknown reason"
msgstr "Неизвестная причина"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:95
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:100
msgid "Windows"
msgstr "Окна"
@ -944,18 +934,18 @@ msgstr "Настроить дату и время"
msgid "%A %B %e, %Y"
msgstr "%A, %e %B, %Y"
#: ../js/ui/endSessionDialog.js:64
#: ../js/ui/endSessionDialog.js:62
#, javascript-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Завершение сеанса пользователя %s"
#: ../js/ui/endSessionDialog.js:65
#: ../js/ui/endSessionDialog.js:63
msgctxt "title"
msgid "Log Out"
msgstr "Завершение сеанса"
#: ../js/ui/endSessionDialog.js:67
#: ../js/ui/endSessionDialog.js:65
#, javascript-format
msgid "%s will be logged out automatically in %d second."
msgid_plural "%s will be logged out automatically in %d seconds."
@ -965,7 +955,7 @@ msgstr[1] ""
"Сеанс пользователя %s будет автоматически завершён через %d секунды."
msgstr[2] "Сеанс пользователя %s будет автоматически завершён через %d секунд."
#: ../js/ui/endSessionDialog.js:72
#: ../js/ui/endSessionDialog.js:70
#, javascript-format
msgid "You will be logged out automatically in %d second."
msgid_plural "You will be logged out automatically in %d seconds."
@ -973,17 +963,17 @@ msgstr[0] "Сеанс будет автоматически завершён ч
msgstr[1] "Сеанс будет автоматически завершён через %d секунды."
msgstr[2] "Сеанс будет автоматически завершён через %d секунд."
#: ../js/ui/endSessionDialog.js:77
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "Завершить сеанс"
#: ../js/ui/endSessionDialog.js:83
#: ../js/ui/endSessionDialog.js:81
msgctxt "title"
msgid "Power Off"
msgstr "Выключение"
#: ../js/ui/endSessionDialog.js:85
#: ../js/ui/endSessionDialog.js:83
#, javascript-format
msgid "The system will power off automatically in %d second."
msgid_plural "The system will power off automatically in %d seconds."
@ -991,22 +981,22 @@ msgstr[0] "Система будет автоматически выключен
msgstr[1] "Система будет автоматически выключена через %d секунды."
msgstr[2] "Система будет автоматически выключена через %d секунд."
#: ../js/ui/endSessionDialog.js:90 ../js/ui/endSessionDialog.js:106
#: ../js/ui/endSessionDialog.js:88 ../js/ui/endSessionDialog.js:104
msgctxt "button"
msgid "Restart"
msgstr "Перезапустить"
#: ../js/ui/endSessionDialog.js:92
#: ../js/ui/endSessionDialog.js:90
msgctxt "button"
msgid "Power Off"
msgstr "Выключить"
#: ../js/ui/endSessionDialog.js:99
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "Перезапуск"
#: ../js/ui/endSessionDialog.js:101
#: ../js/ui/endSessionDialog.js:99
#, javascript-format
msgid "The system will restart automatically in %d second."
msgid_plural "The system will restart automatically in %d seconds."
@ -1014,12 +1004,12 @@ msgstr[0] "Система будет автоматически перезапу
msgstr[1] "Система будет автоматически перезапущена через %d секунды."
msgstr[2] "Система будет автоматически перезапущена через %d секунд."
#: ../js/ui/endSessionDialog.js:114
#: ../js/ui/endSessionDialog.js:112
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Перезапуск и установка обновлений"
#: ../js/ui/endSessionDialog.js:116
#: ../js/ui/endSessionDialog.js:114
#, javascript-format
msgid "The system will automatically restart and install updates in %d second."
msgid_plural ""
@ -1031,27 +1021,27 @@ msgstr[1] ""
msgstr[2] ""
"Система автоматически перезапустится и установит обновления через %d секунд."
#: ../js/ui/endSessionDialog.js:121
#: ../js/ui/endSessionDialog.js:119
msgctxt "button"
msgid "Restart & Install"
msgstr "Перезапустить и установить"
#: ../js/ui/endSessionDialog.js:275
#: ../js/ui/endSessionDialog.js:271
msgid "Some applications are busy or have unsaved work."
msgstr "Некоторые приложения заняты или результаты их работы не сохранены."
#: ../js/ui/endSessionDialog.js:282
#: ../js/ui/endSessionDialog.js:277
msgid "Other users are logged in."
msgstr "В системе имеются открытые сеансы других пользователей."
#. Translators: Remote here refers to a remote session, like a ssh login */
#: ../js/ui/endSessionDialog.js:485
#: ../js/ui/endSessionDialog.js:479
#, javascript-format
msgid "%s (remote)"
msgstr "%s (удалённый)"
#. Translators: Console here refers to a tty like a VT console */
#: ../js/ui/endSessionDialog.js:488
#: ../js/ui/endSessionDialog.js:482
#, javascript-format
msgid "%s (console)"
msgstr "%s (консоль)"
@ -1065,29 +1055,29 @@ msgstr "Установить"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Загрузить и установить расширение «%s» с extensions.gnome.org?"
#: ../js/ui/keyboard.js:621 ../js/ui/status/keyboard.js:335
#: ../js/ui/keyboard.js:619
msgid "Keyboard"
msgstr "Клавиатура"
#: ../js/ui/lookingGlass.js:640
#: ../js/ui/lookingGlass.js:689
msgid "No extensions installed"
msgstr "Расширения не установлены"
#. Translators: argument is an extension UUID. */
#: ../js/ui/lookingGlass.js:694
#: ../js/ui/lookingGlass.js:743
#, javascript-format
msgid "%s has not emitted any errors."
msgstr "%s не сообщал о каких-либо ошибках."
#: ../js/ui/lookingGlass.js:700
#: ../js/ui/lookingGlass.js:749
msgid "Hide Errors"
msgstr "Скрыть ошибки"
#: ../js/ui/lookingGlass.js:704 ../js/ui/lookingGlass.js:764
#: ../js/ui/lookingGlass.js:753 ../js/ui/lookingGlass.js:813
msgid "Show Errors"
msgstr "Показать ошибки"
#: ../js/ui/lookingGlass.js:713
#: ../js/ui/lookingGlass.js:762
msgid "Enabled"
msgstr "Включено"
@ -1095,73 +1085,73 @@ msgstr "Включено"
#. because it's disabled by rfkill (airplane mode) */
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:716 ../js/ui/status/network.js:472
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:472
#: ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Выключено"
#: ../js/ui/lookingGlass.js:718
#: ../js/ui/lookingGlass.js:767
msgid "Error"
msgstr "Ошибка"
#: ../js/ui/lookingGlass.js:720
#: ../js/ui/lookingGlass.js:769
msgid "Out of date"
msgstr "Устарело"
#: ../js/ui/lookingGlass.js:722
#: ../js/ui/lookingGlass.js:771
msgid "Downloading"
msgstr "Загрузка"
#: ../js/ui/lookingGlass.js:746
#: ../js/ui/lookingGlass.js:795
msgid "View Source"
msgstr "Показать код"
#: ../js/ui/lookingGlass.js:755
#: ../js/ui/lookingGlass.js:804
msgid "Web Page"
msgstr "Веб-страница"
#: ../js/ui/messageTray.js:1310
#: ../js/ui/messageTray.js:1347
msgid "Open"
msgstr "Открыть"
#: ../js/ui/messageTray.js:1317
#: ../js/ui/messageTray.js:1354
msgid "Remove"
msgstr "Удалить"
#: ../js/ui/messageTray.js:1618
#: ../js/ui/messageTray.js:1657
msgid "Notifications"
msgstr "Уведомления"
#: ../js/ui/messageTray.js:1625
#: ../js/ui/messageTray.js:1664
msgid "Clear Messages"
msgstr "Очистить список сообщений"
#: ../js/ui/messageTray.js:1644
#: ../js/ui/messageTray.js:1683
msgid "Notification Settings"
msgstr "Параметры уведомлений"
#: ../js/ui/messageTray.js:1697
#: ../js/ui/messageTray.js:1736
msgid "Tray Menu"
msgstr "Меню панели"
#: ../js/ui/messageTray.js:1913
#: ../js/ui/messageTray.js:1952
msgid "No Messages"
msgstr "Нет сообщений"
#: ../js/ui/messageTray.js:1951
#: ../js/ui/messageTray.js:1990
msgid "Message Tray"
msgstr "Панель сообщений"
#: ../js/ui/messageTray.js:2929
#: ../js/ui/messageTray.js:2965
msgid "System Information"
msgstr "Системная информация"
#: ../js/ui/notificationDaemon.js:539 ../src/shell-app.c:396
#: ../js/ui/notificationDaemon.js:510 ../src/shell-app.c:396
msgctxt "program"
msgid "Unknown"
msgstr "Неизвестно"
#: ../js/ui/overviewControls.js:486 ../js/ui/screenShield.js:153
#: ../js/ui/overviewControls.js:488 ../js/ui/screenShield.js:153
#, javascript-format
msgid "%d new message"
msgid_plural "%d new messages"
@ -1173,7 +1163,7 @@ msgstr[2] "%d новых сообщений"
msgid "Undo"
msgstr "Отменить"
#: ../js/ui/overview.js:125
#: ../js/ui/overview.js:127
msgid "Overview"
msgstr "Обзор"
@ -1181,7 +1171,7 @@ msgstr "Обзор"
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters. */
#: ../js/ui/overview.js:256
#: ../js/ui/overview.js:258
msgid "Type to search…"
msgstr "Найти…"
@ -1241,11 +1231,11 @@ msgstr "Не удалось заблокировать"
msgid "Lock was blocked by an application"
msgstr "Блокировке помешало приложение"
#: ../js/ui/search.js:607
#: ../js/ui/searchDisplay.js:448
msgid "Searching…"
msgstr "Поиск…"
#: ../js/ui/search.js:650
#: ../js/ui/searchDisplay.js:492
msgid "No results."
msgstr "Нет результатов."
@ -1324,7 +1314,7 @@ msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:29 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:1083 ../js/ui/status/rfkill.js:48
#: ../js/ui/status/network.js:1099 ../js/ui/status/rfkill.js:46
msgid "Turn Off"
msgstr "Выключить"
@ -1410,20 +1400,16 @@ msgstr "Введите PIN-код указанный на устройстве."
msgid "OK"
msgstr "OK"
#: ../js/ui/status/brightness.js:44
#: ../js/ui/status/brightness.js:42
msgid "Brightness"
msgstr "Яркость"
#: ../js/ui/status/keyboard.js:403
msgid "Show Keyboard Layout"
msgstr "Показать раскладку клавиатуры"
#: ../js/ui/status/network.js:71
msgid "<unknown>"
msgstr "<неизвестно>"
#: ../js/ui/status/network.js:222 ../js/ui/status/network.js:379
#: ../js/ui/status/network.js:1104
#: ../js/ui/status/network.js:1120
msgid "Off"
msgstr "Выключена"
@ -1437,12 +1423,12 @@ msgstr "не управляется"
msgid "disconnecting..."
msgstr "отключение…"
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1158
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1174
msgid "connecting..."
msgstr "подключение…"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1161
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1177
msgid "authentication required"
msgstr "требуется подтверждение подлинности"
@ -1458,7 +1444,7 @@ msgstr "отсутствует прошивка"
msgid "unavailable"
msgstr "недоступное"
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1163
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1179
msgid "connection failed"
msgstr "сбой подключения"
@ -1466,93 +1452,89 @@ msgstr "сбой подключения"
msgid "Mobile Broadband Settings"
msgstr "Параметры широкополосной мобильной связи"
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1102
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1118
msgid "Hardware Disabled"
msgstr "Оборудование выключено"
#: ../js/ui/status/network.js:694
#: ../js/ui/status/network.js:707
msgid "Wi-Fi Networks"
msgstr "Сети Wi-Fi"
#: ../js/ui/status/network.js:696
#: ../js/ui/status/network.js:709
msgid "Select a network"
msgstr "Выберите сеть"
#: ../js/ui/status/network.js:720
#: ../js/ui/status/network.js:733
msgid "No Networks"
msgstr "Сети отсутствуют"
#: ../js/ui/status/network.js:989
#: ../js/ui/status/network.js:1005
msgid "Select Network"
msgstr "Выбрать сеть"
#: ../js/ui/status/network.js:995
#: ../js/ui/status/network.js:1011
msgid "Wi-Fi Settings"
msgstr "Параметры Wi-Fi"
#: ../js/ui/status/network.js:1083
#: ../js/ui/status/network.js:1099
msgid "Turn On"
msgstr "Включить"
#: ../js/ui/status/network.js:1106
#: ../js/ui/status/network.js:1122
msgid "Not Connected"
msgstr "Не подключено"
#: ../js/ui/status/network.js:1226
#: ../js/ui/status/network.js:1242
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1366
#: ../js/ui/status/network.js:1382
msgid "Network Manager"
msgstr "Диспетчер сети"
#: ../js/ui/status/network.js:1405
#: ../js/ui/status/network.js:1421
msgid "Connection failed"
msgstr "Сбой подключения"
#: ../js/ui/status/network.js:1406
#: ../js/ui/status/network.js:1422
msgid "Activation of network connection failed"
msgstr "Не удалось активировать сетевое подключение"
#: ../js/ui/status/power.js:49
#: ../js/ui/status/power.js:46
msgid "Battery"
msgstr "Батарея"
#: ../js/ui/status/power.js:47
msgid "Power Settings"
msgstr "Параметры электропитания"
#: ../js/ui/status/power.js:65
#: ../js/ui/status/power.js:63
msgid "Fully Charged"
msgstr "Полностью заряжена"
#: ../js/ui/status/power.js:72 ../js/ui/status/power.js:78
#: ../js/ui/status/power.js:69 ../js/ui/status/power.js:86
msgid "Estimating…"
msgstr "Выполняется подсчёт…"
#: ../js/ui/status/power.js:86
#: ../js/ui/status/power.js:77
#, javascript-format
msgid "%d%02d Remaining (%d%%)"
msgstr "Осталось %d%02d (%d%%)"
#: ../js/ui/status/power.js:91
#: ../js/ui/status/power.js:82
#, javascript-format
msgid "%d%02d Until Full (%d%%)"
msgstr "До полного заряда %d%02d (%d%%)"
#: ../js/ui/status/power.js:119
msgid "UPS"
msgstr "ИБП"
#: ../js/ui/status/power.js:121
msgid "Battery"
msgstr "Батарея"
#: ../js/ui/status/rfkill.js:45
#: ../js/ui/status/rfkill.js:43
msgid "Airplane Mode"
msgstr "Режим перелёта"
#: ../js/ui/status/rfkill.js:47
#: ../js/ui/status/rfkill.js:45
msgid "On"
msgstr "Включено"
#: ../js/ui/status/rfkill.js:51
#: ../js/ui/status/rfkill.js:49
msgid "Network Settings"
msgstr "Настроить сеть"
@ -1596,14 +1578,28 @@ msgstr "Войти от имени другого пользователя"
msgid "Unlock Window"
msgstr "Разблокировать окно"
#: ../js/ui/viewSelector.js:99
#: ../js/ui/viewSelector.js:104
msgid "Applications"
msgstr "Приложения"
#: ../js/ui/viewSelector.js:103
#: ../js/ui/viewSelector.js:108
msgid "Search"
msgstr "Поиск"
#: ../js/ui/wanda.js:77
#, javascript-format
msgid ""
"Sorry, no wisdom for you today:\n"
"%s"
msgstr ""
"Извините, на сегодня нет никаких советов:\n"
"%s"
#: ../js/ui/wanda.js:81
#, javascript-format
msgid "%s the Oracle says"
msgstr "Оракул говорит: «%s»"
#: ../js/ui/windowAttentionHandler.js:19
#, javascript-format
msgid "'%s' is ready"
@ -1660,24 +1656,24 @@ msgstr[2] "%u входов"
msgid "System Sounds"
msgstr "Системные звуки"
#: ../src/main.c:351
#: ../src/main.c:353
msgid "Print version"
msgstr "Показать номер версии"
#: ../src/main.c:357
#: ../src/main.c:359
msgid "Mode used by GDM for login screen"
msgstr "Режим, используемый GDM для окна входа в систему"
#: ../src/main.c:363
#: ../src/main.c:365
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr ""
"Использовать для экрана входа в систему определённый режим, например «gdm»"
#: ../src/main.c:369
#: ../src/main.c:371
msgid "List possible modes"
msgstr "Список возможных режимов"
#: ../src/shell-app.c:639
#: ../src/shell-app.c:644
#, c-format
msgid "Failed to launch '%s'"
msgstr "Не удалось запустить «%s»"
@ -1693,13 +1689,3 @@ msgstr "Пароль не может быть пустым"
#: ../src/shell-polkit-authentication-agent.c:343
msgid "Authentication dialog was dismissed by the user"
msgstr "Аутентификация отклонена пользователем"
#~ msgid ""
#~ "Sorry, no wisdom for you today:\n"
#~ "%s"
#~ msgstr ""
#~ "Извините, на сегодня нет никаких советов:\n"
#~ "%s"
#~ msgid "%s the Oracle says"
#~ msgstr "Оракул говорит: «%s»"

363
po/ta.po
View File

@ -9,8 +9,8 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-11-03 00:53+0000\n"
"PO-Revision-Date: 2013-11-11 14:44+0530\n"
"POT-Creation-Date: 2013-11-01 19:31+0000\n"
"PO-Revision-Date: 2013-11-11 15:02+0530\n"
"Last-Translator: Shantha kumar <shkumar@redhat.com>\n"
"Language-Team: American English <>\n"
"Language: ta\n"
@ -54,7 +54,6 @@ msgid "Window management and application launching"
msgstr "சாளர மேலாண்மை மற்றும் பயன்பாடு துவக்கம்"
#: ../data/gnome-shell-extension-prefs.desktop.in.in.h:1
#: ../js/extensionPrefs/main.js:155
msgid "GNOME Shell Extension Preferences"
msgstr "க்னோம் ஷெல் நீட்சி விருப்பங்கள்"
@ -269,22 +268,14 @@ msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr ""
"சொடுக்கி பயன்முறையில் கவனப் பகுதி மாற்றங்களை சுட்டி நகர்வது நிற்கும் வரை தாமதப்படுத்தவும்"
#: ../js/extensionPrefs/main.js:127
msgid "There was an error loading the preferences dialog for %s:"
msgstr "%s க்கு விருப்பங்கள் உரையாடலை ஏற்றுகையில் பிழை நேர்ந்தது:"
#: ../js/extensionPrefs/main.js:167
msgid "Extension"
msgstr "நீட்சி"
#: ../js/extensionPrefs/main.js:191
#: ../js/extensionPrefs/main.js:189
msgid "Select an extension to configure using the combobox above."
msgstr "மேலுள்ள கூட்டுப்பெட்டியை பயன்படுத்தி வடிவமைக்க ஒரு நீட்சியை தேர்ந்தெடுக்கவும்"
#: ../js/gdm/authPrompt.js:146 ../js/ui/components/networkAgent.js:136
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:357
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:726
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:739
msgid "Cancel"
msgstr "ரத்துசெய்க"
@ -302,25 +293,25 @@ msgctxt "button"
msgid "Sign In"
msgstr "உள்நுழை"
#: ../js/gdm/loginDialog.js:272
#: ../js/gdm/loginDialog.js:294
#| msgid "Switch Session"
msgid "Choose Session"
msgstr "அமர்வைத் தேர்வு செய்யவும்"
#: ../js/gdm/loginDialog.js:432
#: ../js/gdm/loginDialog.js:454
msgid "Not listed?"
msgstr "பட்டியலில் இல்லை?"
#: ../js/gdm/loginDialog.js:600
#: ../js/gdm/loginDialog.js:622
msgid "(e.g., user or %s)"
msgstr "(எ.கா., பயனர் அல்லது %s)"
#: ../js/gdm/loginDialog.js:605 ../js/ui/components/networkAgent.js:259
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:259
#: ../js/ui/components/networkAgent.js:277
msgid "Username: "
msgstr "பயனர்பெயர்: "
#: ../js/gdm/loginDialog.js:869
#: ../js/gdm/loginDialog.js:891
msgid "Login Window"
msgstr "உள்புகு சாளரம்"
@ -348,23 +339,23 @@ msgstr "'%s' ஐ நிறைவேற்றுதல் தோல்வி அ
msgid "Frequently used applications will appear here"
msgstr "அதிகம் பயன்படுத்தும் பயன்பாடுகள் இங்கு காண்பிக்கப்படும்"
#: ../js/ui/appDisplay.js:715
#: ../js/ui/appDisplay.js:712
msgid "Frequent"
msgstr "அடிக்கடி"
#: ../js/ui/appDisplay.js:722
#: ../js/ui/appDisplay.js:719
msgid "All"
msgstr "எல்லா"
#: ../js/ui/appDisplay.js:1526
#: ../js/ui/appDisplay.js:1523
msgid "New Window"
msgstr "புதிய சாளரம்"
#: ../js/ui/appDisplay.js:1529 ../js/ui/dash.js:284
#: ../js/ui/appDisplay.js:1526 ../js/ui/dash.js:284
msgid "Remove from Favorites"
msgstr "விருப்பத்தில் இருந்து நீக்கு"
#: ../js/ui/appDisplay.js:1530
#: ../js/ui/appDisplay.js:1527
msgid "Add to Favorites"
msgstr "விருப்பங்களுக்கு சேர்"
@ -501,48 +492,48 @@ msgctxt "list saturday"
msgid "S"
msgstr "ச"
#: ../js/ui/calendar.js:391
#: ../js/ui/calendar.js:389
msgid "calendar:MY"
msgstr "நாள்காட்டி:MY"
#: ../js/ui/calendar.js:449
#: ../js/ui/calendar.js:447
msgid "Previous month"
msgstr "முந்தைய மாதம்"
#: ../js/ui/calendar.js:459
#: ../js/ui/calendar.js:457
msgid "Next month"
msgstr "அடுத்த மாதம்"
#. Translators: Text to show if there are no events */
#: ../js/ui/calendar.js:755
#: ../js/ui/calendar.js:753
msgid "Nothing Scheduled"
msgstr "திட்டம் எதுவுமில்லை"
#. Translators: Shown on calendar heading when selected day occurs on current year */
#: ../js/ui/calendar.js:773
#: ../js/ui/calendar.js:771
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %B %d"
#. Translators: Shown on calendar heading when selected day occurs on different year */
#: ../js/ui/calendar.js:776
#: ../js/ui/calendar.js:774
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A, %B %d, %Y"
#: ../js/ui/calendar.js:787
#: ../js/ui/calendar.js:785
msgid "Today"
msgstr "இன்று"
#: ../js/ui/calendar.js:791
#: ../js/ui/calendar.js:789
msgid "Tomorrow"
msgstr "நாளை"
#: ../js/ui/calendar.js:802
#: ../js/ui/calendar.js:800
msgid "This week"
msgstr "இந்த வாரம்"
#: ../js/ui/calendar.js:810
#: ../js/ui/calendar.js:808
msgid "Next week"
msgstr "அடுத்த வாரம்"
@ -554,15 +545,15 @@ msgstr "வெளிப்புற இயக்கி இணைக்கப்
msgid "External drive disconnected"
msgstr "வெளிப்புற இயக்கி இணைப்பு நீக்கப்பட்டது"
#: ../js/ui/components/autorunManager.js:296
#: ../js/ui/components/autorunManager.js:294
msgid "Removable Devices"
msgstr "நீக்கப்படக்கூடிய சாதனங்கள் "
#: ../js/ui/components/autorunManager.js:596
#: ../js/ui/components/autorunManager.js:594
msgid "Open with %s"
msgstr "%s ஆல் திற"
#: ../js/ui/components/autorunManager.js:622
#: ../js/ui/components/autorunManager.js:620
msgid "Eject"
msgstr "வெளியேற்று"
@ -575,7 +566,7 @@ msgid "Type again:"
msgstr "மீண்டும் உள்ளிடவும்:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:729
#: ../js/ui/status/network.js:295 ../js/ui/status/network.js:742
msgid "Connect"
msgstr "இணை"
@ -681,11 +672,11 @@ msgstr "கோப்பு பறிமாற்றம் "
msgid "Chat"
msgstr "அரட்டை"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Unmute"
msgstr "ஒலி நிறுத்தம் நீக்கு"
#: ../js/ui/components/telepathyClient.js:480
#: ../js/ui/components/telepathyClient.js:479
msgid "Mute"
msgstr "ஒலி நிறுத்தம்"
@ -729,30 +720,30 @@ msgid "%s is inviting you to join %s"
msgstr "%s உங்களை %s உடன் சேர அழைக்கிறார்."
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1133
#: ../js/ui/components/telepathyClient.js:1167
#: ../js/ui/components/telepathyClient.js:1224
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
msgid "Decline"
msgstr "நிராகரி"
#: ../js/ui/components/telepathyClient.js:1104
#: ../js/ui/components/telepathyClient.js:1173
#: ../js/ui/components/telepathyClient.js:1229
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
msgid "Accept"
msgstr "ஏற்றுக்கொள்"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1123
#: ../js/ui/components/telepathyClient.js:1129
msgid "Video call from %s"
msgstr "%s இடமிருந்து விடியோ அழைப்பு"
#. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1126
#: ../js/ui/components/telepathyClient.js:1132
msgid "Call from %s"
msgstr "%s இடமிருந்து அழைப்பு"
#. translators: this is a button label (verb), not a noun */
#: ../js/ui/components/telepathyClient.js:1140
#: ../js/ui/components/telepathyClient.js:1141
msgid "Answer"
msgstr "பதிலளி"
@ -761,108 +752,108 @@ msgstr "பதிலளி"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#. */
#: ../js/ui/components/telepathyClient.js:1161
#: ../js/ui/components/telepathyClient.js:1173
msgid "%s is sending you %s"
msgstr "%s உங்களுக்கு %s அனுப்புகிறார்"
#. To translators: The parameter is the contact's alias */
#: ../js/ui/components/telepathyClient.js:1190
#: ../js/ui/components/telepathyClient.js:1208
msgid "%s would like permission to see when you are online"
msgstr "%s நீங்கள் இணைப்பில் இருக்கும் போது காண அனுமதி வேண்டுகிறார். "
#: ../js/ui/components/telepathyClient.js:1275
#: ../js/ui/components/telepathyClient.js:1300
msgid "Network error"
msgstr "வலையமைப்பு பிழை"
#: ../js/ui/components/telepathyClient.js:1277
#: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed"
msgstr "உறுதி செய்தல் தோல்வி"
#: ../js/ui/components/telepathyClient.js:1279
#: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error"
msgstr "மறையாக்க பிழை"
#: ../js/ui/components/telepathyClient.js:1281
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided"
msgstr "சான்றிதழ் தரப்படவில்லை"
#: ../js/ui/components/telepathyClient.js:1283
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted"
msgstr "சான்றிதழில் நம்பக தன்மை இல்லை"
#: ../js/ui/components/telepathyClient.js:1285
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired"
msgstr "சான்றிதழ் காலாவதியானது"
#: ../js/ui/components/telepathyClient.js:1287
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated"
msgstr "சான்றிதழ் செயல்படுத்தப்படவில்லை"
#: ../js/ui/components/telepathyClient.js:1289
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch"
msgstr "சான்றிதழ் புரவலன் பெயர் ஒத்திசையவில்லை"
#: ../js/ui/components/telepathyClient.js:1291
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch"
msgstr "சான்றிதழ் அடையாளம் ஒத்திசையவில்லை"
#: ../js/ui/components/telepathyClient.js:1293
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed"
msgstr "சான்றிதழ் தானே கையெழுத்திட்டது"
#: ../js/ui/components/telepathyClient.js:1295
#: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline"
msgstr "நிலை இப்போது இணைப்பு விலகி "
#: ../js/ui/components/telepathyClient.js:1297
#: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available"
msgstr "குறீயீட்டுமுறை கிடைப்பில் இல்லை"
#: ../js/ui/components/telepathyClient.js:1299
#: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid"
msgstr "சான்றிதழ் செல்லுபடியாகாது"
#: ../js/ui/components/telepathyClient.js:1301
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused"
msgstr "இணைப்பு மறுக்கப்பட்டது"
#: ../js/ui/components/telepathyClient.js:1303
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established"
msgstr "இணைக்க முடியவில்லை"
#: ../js/ui/components/telepathyClient.js:1305
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost"
msgstr "இணைப்பு அற்றுப்போயிற்று"
#: ../js/ui/components/telepathyClient.js:1307
#: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server"
msgstr "இந்த கணக்கு ஏற்கனவே சேவையகத்துக்கு இணைக்கப்பட்டது"
#: ../js/ui/components/telepathyClient.js:1309
#: ../js/ui/components/telepathyClient.js:1334
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr "இணைப்பு அதே முலத்துடன் புதிய இணைப்பால் மாற்றப்பட்டது."
#: ../js/ui/components/telepathyClient.js:1311
#: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server"
msgstr "இந்த கணக்கு ஏற்கனவே சேவையகத்தில் உள்ளது"
#: ../js/ui/components/telepathyClient.js:1313
#: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection"
msgstr "இணைப்பை கையாள சேவையகம் இப்போது மிகவும் வேலை பளுவில் உள்ளது."
#: ../js/ui/components/telepathyClient.js:1315
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked"
msgstr "சான்றிதழ் ரத்து செய்யப்பட்டது"
#: ../js/ui/components/telepathyClient.js:1317
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"சான்றிதழ் பாதுகாப்பில்லாத சைபர் அல்கோரிதத்தை பயன்படுத்துகிறது. இது மறையாக்கத்தில் "
"பலகீனமானது."
#: ../js/ui/components/telepathyClient.js:1319
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -870,25 +861,25 @@ msgstr ""
"சேவயகத்தின் சான்றிதழின் நீளம் அல்லது சங்கிலியின் ஆழம் மறையாக்க நூலகம் வரயறுத்த மதிப்பை "
"தாண்டியது."
#: ../js/ui/components/telepathyClient.js:1321
#: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error"
msgstr "உள்ளார்ந்த பிழை"
#. translators: argument is the account name, like
#. * name@jabber.org for example. */
#: ../js/ui/components/telepathyClient.js:1331
#: ../js/ui/components/telepathyClient.js:1356
msgid "Unable to connect to %s"
msgstr "%s க்கு இணைக்க முடியவில்லை"
#: ../js/ui/components/telepathyClient.js:1336
#: ../js/ui/components/telepathyClient.js:1361
msgid "View account"
msgstr "கணக்கை காட்டவும்"
#: ../js/ui/components/telepathyClient.js:1368
#: ../js/ui/components/telepathyClient.js:1400
msgid "Unknown reason"
msgstr "தெரியாத காரணம்"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:95
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:100
msgid "Windows"
msgstr "சாளரங்கள்"
@ -919,72 +910,72 @@ msgstr "தேதி நேரம் அமைப்புகள்"
msgid "%A %B %e, %Y"
msgstr "%A %B %e, %Y"
#: ../js/ui/endSessionDialog.js:64
#: ../js/ui/endSessionDialog.js:62
msgctxt "title"
msgid "Log Out %s"
msgstr "%s யிலிருந்து வெளியேறு"
#: ../js/ui/endSessionDialog.js:65
#: ../js/ui/endSessionDialog.js:63
msgctxt "title"
msgid "Log Out"
msgstr "வெளியேறு"
#: ../js/ui/endSessionDialog.js:67
#: ../js/ui/endSessionDialog.js:65
msgid "%s will be logged out automatically in %d second."
msgid_plural "%s will be logged out automatically in %d seconds."
msgstr[0] "%s தானியங்கியாக %d வினாடியில் வெளியேறும்"
msgstr[1] "%s தானியங்கியாக %d வினாடிகளில் வெளியேறும்"
#: ../js/ui/endSessionDialog.js:72
#: ../js/ui/endSessionDialog.js:70
msgid "You will be logged out automatically in %d second."
msgid_plural "You will be logged out automatically in %d seconds."
msgstr[0] "நீங்கள் தானியங்கியாக %d வினாடியில் வெளியேற்றப்படுவீர்கள் "
msgstr[1] "நீங்கள் தானியங்கியாக %d வினாடிகளில் வெளியேற்றப்படுவீர்கள் "
#: ../js/ui/endSessionDialog.js:77
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "வெளியேறு"
#: ../js/ui/endSessionDialog.js:83
#: ../js/ui/endSessionDialog.js:81
msgctxt "title"
msgid "Power Off"
msgstr "மின்சக்தி நிறுத்தம்"
#: ../js/ui/endSessionDialog.js:85
#: ../js/ui/endSessionDialog.js:83
msgid "The system will power off automatically in %d second."
msgid_plural "The system will power off automatically in %d seconds."
msgstr[0] "கணினி தானியங்கியாக %d வினாடியில் மின் நிறுத்தப்படும்"
msgstr[1] "கணினி தானியங்கியாக %d வினாடிகளில் மின் நிறுத்தப்படும்"
#: ../js/ui/endSessionDialog.js:90 ../js/ui/endSessionDialog.js:106
#: ../js/ui/endSessionDialog.js:88 ../js/ui/endSessionDialog.js:104
msgctxt "button"
msgid "Restart"
msgstr "மறு துவக்கம்"
#: ../js/ui/endSessionDialog.js:92
#: ../js/ui/endSessionDialog.js:90
msgctxt "button"
msgid "Power Off"
msgstr "மின்சக்தி நிறுத்தம்"
#: ../js/ui/endSessionDialog.js:99
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "மறு துவக்கம்"
#: ../js/ui/endSessionDialog.js:101
#: ../js/ui/endSessionDialog.js:99
msgid "The system will restart automatically in %d second."
msgid_plural "The system will restart automatically in %d seconds."
msgstr[0] "கணினி தானியங்கியாக %d வினாடியில் மீள் துவக்கம் செய்யப்படும்."
msgstr[1] "கணினி தானியங்கியாக %d வினாடிகளில் மீள் துவக்கம் செய்யப்படும்."
#: ../js/ui/endSessionDialog.js:114
#: ../js/ui/endSessionDialog.js:112
#| msgid "Install Updates & Restart"
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "மறுதுவக்கி புதுப்பிப்புகளை நிறுவு"
#: ../js/ui/endSessionDialog.js:116
#: ../js/ui/endSessionDialog.js:114
#| msgid "The system will restart automatically in %d second."
#| msgid_plural "The system will restart automatically in %d seconds."
msgid "The system will automatically restart and install updates in %d second."
@ -993,26 +984,26 @@ msgid_plural ""
msgstr[0] "%d வினாடியில் கணினி தானாகவே மறுதுவக்கமாகி புதுப்பிப்புகளை நிறுவும்."
msgstr[1] "%d வினாடிகளில் கணினி தானாகவே மறுதுவக்கமாகி புதுப்பிப்புகளை நிறுவும்."
#: ../js/ui/endSessionDialog.js:121
#: ../js/ui/endSessionDialog.js:119
msgctxt "button"
msgid "Restart & Install"
msgstr "மறுதுவக்கி நிறுவு"
#: ../js/ui/endSessionDialog.js:275
#: ../js/ui/endSessionDialog.js:271
msgid "Some applications are busy or have unsaved work."
msgstr "சில பயன்பாடுகள் பணிமிகுதியாக உள்ளன அல்லது சேமிக்கப்படாத பணியைக் கொண்டுள்ளன."
#: ../js/ui/endSessionDialog.js:282
#: ../js/ui/endSessionDialog.js:277
msgid "Other users are logged in."
msgstr "மற்ற பயனர்கள் புகுபதிவு செய்துள்ளனர்."
#. Translators: Remote here refers to a remote session, like a ssh login */
#: ../js/ui/endSessionDialog.js:485
#: ../js/ui/endSessionDialog.js:479
msgid "%s (remote)"
msgstr "%s (தொலைநிலை)"
#. Translators: Console here refers to a tty like a VT console */
#: ../js/ui/endSessionDialog.js:488
#: ../js/ui/endSessionDialog.js:482
msgid "%s (console)"
msgstr "%s (கன்சோல்)"
@ -1024,28 +1015,28 @@ msgstr "நிறுவு"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "'%s' ஐ எக்ஸ்டென்ஷன்ஸ்.க்னோம்.ஆர்க். இலிருந்து தரவிறக்கி நிறுவவா?"
#: ../js/ui/keyboard.js:621 ../js/ui/status/keyboard.js:335
#: ../js/ui/keyboard.js:619
msgid "Keyboard"
msgstr "விசைப்பலகை"
#: ../js/ui/lookingGlass.js:640
#: ../js/ui/lookingGlass.js:689
msgid "No extensions installed"
msgstr "நீட்சிகள் ஏதும் நிறுவப்படவில்லை"
#. Translators: argument is an extension UUID. */
#: ../js/ui/lookingGlass.js:694
#: ../js/ui/lookingGlass.js:743
msgid "%s has not emitted any errors."
msgstr "%s எந்த பிழையையும் வெளியிடவில்லை"
#: ../js/ui/lookingGlass.js:700
#: ../js/ui/lookingGlass.js:749
msgid "Hide Errors"
msgstr "பிழைகளை மறை"
#: ../js/ui/lookingGlass.js:704 ../js/ui/lookingGlass.js:764
#: ../js/ui/lookingGlass.js:753 ../js/ui/lookingGlass.js:813
msgid "Show Errors"
msgstr "பிழைகளை காட்டுக"
#: ../js/ui/lookingGlass.js:713
#: ../js/ui/lookingGlass.js:762
msgid "Enabled"
msgstr "செயலாக்கப்பட்டது"
@ -1053,73 +1044,73 @@ msgstr "செயலாக்கப்பட்டது"
#. because it's disabled by rfkill (airplane mode) */
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:716 ../js/ui/status/network.js:472
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:472
#: ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "செயல்நீக்கப்பட்டது"
#: ../js/ui/lookingGlass.js:718
#: ../js/ui/lookingGlass.js:767
msgid "Error"
msgstr "பிழை"
#: ../js/ui/lookingGlass.js:720
#: ../js/ui/lookingGlass.js:769
msgid "Out of date"
msgstr "காலாவதியானது"
#: ../js/ui/lookingGlass.js:722
#: ../js/ui/lookingGlass.js:771
msgid "Downloading"
msgstr "பதிவிறக்குகிறது"
#: ../js/ui/lookingGlass.js:746
#: ../js/ui/lookingGlass.js:795
msgid "View Source"
msgstr "மூலத்தை பார்க்க"
#: ../js/ui/lookingGlass.js:755
#: ../js/ui/lookingGlass.js:804
msgid "Web Page"
msgstr "இணைய பக்கம்"
#: ../js/ui/messageTray.js:1310
#: ../js/ui/messageTray.js:1347
msgid "Open"
msgstr "திற"
#: ../js/ui/messageTray.js:1317
#: ../js/ui/messageTray.js:1354
msgid "Remove"
msgstr "நீக்கு"
#: ../js/ui/messageTray.js:1618
#: ../js/ui/messageTray.js:1657
msgid "Notifications"
msgstr "அறிவிப்புகள்"
#: ../js/ui/messageTray.js:1625
#: ../js/ui/messageTray.js:1664
msgid "Clear Messages"
msgstr "செய்திகளை அழி"
#: ../js/ui/messageTray.js:1644
#: ../js/ui/messageTray.js:1683
msgid "Notification Settings"
msgstr "அறிவிப்பு அமைப்புகள்"
#: ../js/ui/messageTray.js:1697
#: ../js/ui/messageTray.js:1736
msgid "Tray Menu"
msgstr "ட்ரே மெனு"
#: ../js/ui/messageTray.js:1913
#: ../js/ui/messageTray.js:1952
msgid "No Messages"
msgstr "செய்திகள் இல்லை"
#: ../js/ui/messageTray.js:1951
#: ../js/ui/messageTray.js:1990
msgid "Message Tray"
msgstr "அறிவிப்பு பலகம்"
#: ../js/ui/messageTray.js:2929
#: ../js/ui/messageTray.js:2965
msgid "System Information"
msgstr "கணினி தகவல்கள்"
#: ../js/ui/notificationDaemon.js:539 ../src/shell-app.c:396
#: ../js/ui/notificationDaemon.js:510 ../src/shell-app.c:396
msgctxt "program"
msgid "Unknown"
msgstr "தெரியாத"
#: ../js/ui/overviewControls.js:486 ../js/ui/screenShield.js:153
#: ../js/ui/overviewControls.js:488 ../js/ui/screenShield.js:153
msgid "%d new message"
msgid_plural "%d new messages"
msgstr[0] "%d புதிய செய்தி"
@ -1129,7 +1120,7 @@ msgstr[1] "%d புதிய செய்திகள்"
msgid "Undo"
msgstr "மறை"
#: ../js/ui/overview.js:125
#: ../js/ui/overview.js:127
msgid "Overview"
msgstr "மேலோட்டம்"
@ -1137,7 +1128,7 @@ msgstr "மேலோட்டம்"
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters. */
#: ../js/ui/overview.js:256
#: ../js/ui/overview.js:258
msgid "Type to search…"
msgstr "தேட தட்டச்சு செய்யவும்..."
@ -1195,11 +1186,11 @@ msgstr "பூட்ட முடியவில்லை"
msgid "Lock was blocked by an application"
msgstr "ஒரு பயன்பாடு பூட்டுதலை முடக்கியுள்ளது"
#: ../js/ui/search.js:592
#: ../js/ui/searchDisplay.js:448
msgid "Searching…"
msgstr "தேடுகிறது..."
#: ../js/ui/search.js:635
#: ../js/ui/searchDisplay.js:492
msgid "No results."
msgstr "விடைகள் இல்லை."
@ -1278,7 +1269,7 @@ msgid "Bluetooth"
msgstr "ப்ளூடூத்"
#: ../js/ui/status/bluetooth.js:29 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:1083 ../js/ui/status/rfkill.js:48
#: ../js/ui/status/network.js:1099 ../js/ui/status/rfkill.js:46
msgid "Turn Off"
msgstr "அணை"
@ -1360,20 +1351,16 @@ msgstr "சாதனத்தின் சொல்லும் பின் ஐ
msgid "OK"
msgstr "சரி"
#: ../js/ui/status/brightness.js:44
#: ../js/ui/status/brightness.js:42
msgid "Brightness"
msgstr "ஒளிர்வு"
#: ../js/ui/status/keyboard.js:403
msgid "Show Keyboard Layout"
msgstr "விசைப்பலகை இடவமைவை காட்டுக"
#: ../js/ui/status/network.js:71
msgid "<unknown>"
msgstr "<தெரியாத>"
#: ../js/ui/status/network.js:222 ../js/ui/status/network.js:379
#: ../js/ui/status/network.js:1104
#: ../js/ui/status/network.js:1120
#| msgid "Offline"
msgid "Off"
msgstr "ஆஃப்"
@ -1388,12 +1375,12 @@ msgstr "மேலாண்மை இல்லாத"
msgid "disconnecting..."
msgstr "துண்டிக்கப்படுகிறது......"
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1158
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1174
msgid "connecting..."
msgstr "இணைக்கிறது..."
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1161
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1177
msgid "authentication required"
msgstr "உறுதிப்படுத்துதல் தேவை"
@ -1409,7 +1396,7 @@ msgstr "தள நிரல் காணவில்லை"
msgid "unavailable"
msgstr "செயலாக்க முடியாதவை"
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1163
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1179
msgid "connection failed"
msgstr "இணைப்பு தோல்வி அடைந்தது"
@ -1418,99 +1405,95 @@ msgstr "இணைப்பு தோல்வி அடைந்தது"
msgid "Mobile Broadband Settings"
msgstr "மொபைல் பிராட்பேன்ட் அமைவுகள்"
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1102
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1118
#| msgid "hardware disabled"
msgid "Hardware Disabled"
msgstr "வன்பொருள் முடக்கப்பட்டது"
#: ../js/ui/status/network.js:694
#: ../js/ui/status/network.js:707
#| msgid "Network"
msgid "Wi-Fi Networks"
msgstr "Wi-Fi பிணையங்கள்"
#: ../js/ui/status/network.js:696
#: ../js/ui/status/network.js:709
#| msgid "Enable networking"
msgid "Select a network"
msgstr "ஒரு பிணையத்தைத் தேர்ந்தெடுக்கவும்"
#: ../js/ui/status/network.js:720
#: ../js/ui/status/network.js:733
#| msgid "Network"
msgid "No Networks"
msgstr "பிணையங்கள் இல்லை"
#: ../js/ui/status/network.js:989
#: ../js/ui/status/network.js:1005
#| msgid "Network"
msgid "Select Network"
msgstr "பிணையத்தைத் தேர்ந்தெடுக்கவும்"
#: ../js/ui/status/network.js:995
#: ../js/ui/status/network.js:1011
#| msgid "Settings"
msgid "Wi-Fi Settings"
msgstr "Wi-Fi அமைவுகள்"
#: ../js/ui/status/network.js:1083
#: ../js/ui/status/network.js:1099
msgid "Turn On"
msgstr "இயக்கு"
#: ../js/ui/status/network.js:1106
#: ../js/ui/status/network.js:1122
#| msgid "Connect"
msgid "Not Connected"
msgstr "இணைக்கப்படவில்லை"
#: ../js/ui/status/network.js:1226
#: ../js/ui/status/network.js:1242
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1366
#: ../js/ui/status/network.js:1382
msgid "Network Manager"
msgstr "வலைப்பின்னல் மேலாளர்"
#: ../js/ui/status/network.js:1405
#: ../js/ui/status/network.js:1421
msgid "Connection failed"
msgstr "இணைப்பு தோல்வியுற்றது"
#: ../js/ui/status/network.js:1406
#: ../js/ui/status/network.js:1422
msgid "Activation of network connection failed"
msgstr "வலைப்பின்னல் இணைப்பு செயலாக்கம் தோல்வி அடைந்தது"
#: ../js/ui/status/power.js:49
msgid "Power Settings"
msgstr "மின்சக்தி அமைப்புகள்"
#: ../js/ui/status/power.js:65
msgid "Fully Charged"
msgstr "முழுதும் சார்ஜ் ஆகியுள்ளது"
#: ../js/ui/status/power.js:72 ../js/ui/status/power.js:78
msgid "Estimating…"
msgstr "கணிக்கிறது…"
#: ../js/ui/status/power.js:86
msgid "%d%02d Remaining (%d%%)"
msgstr "%d%02d மீதமுள்ளது (%d%%)"
#: ../js/ui/status/power.js:91
msgid "%d%02d Until Full (%d%%)"
msgstr "%d%02d நிரம்ப உள்ளது (%d%%)"
#: ../js/ui/status/power.js:119
msgid "UPS"
msgstr "யூபிஎஸ்"
#: ../js/ui/status/power.js:121
#: ../js/ui/status/power.js:46
msgid "Battery"
msgstr "மின்கலம்"
#: ../js/ui/status/rfkill.js:45
#: ../js/ui/status/power.js:47
msgid "Power Settings"
msgstr "மின்சக்தி அமைப்புகள்"
#: ../js/ui/status/power.js:63
msgid "Fully Charged"
msgstr "முழுதும் சார்ஜ் ஆகியுள்ளது"
#: ../js/ui/status/power.js:69 ../js/ui/status/power.js:86
msgid "Estimating…"
msgstr "கணிக்கிறது…"
#: ../js/ui/status/power.js:77
msgid "%d%02d Remaining (%d%%)"
msgstr "%d%02d மீதமுள்ளது (%d%%)"
#: ../js/ui/status/power.js:82
msgid "%d%02d Until Full (%d%%)"
msgstr "%d%02d நிரம்ப உள்ளது (%d%%)"
#: ../js/ui/status/rfkill.js:43
msgid "Airplane Mode"
msgstr "விமானப் பயன்முறை"
#: ../js/ui/status/rfkill.js:47
#: ../js/ui/status/rfkill.js:45
#| msgid "Open"
msgid "On"
msgstr "ஆன்"
#: ../js/ui/status/rfkill.js:51
#: ../js/ui/status/rfkill.js:49
msgid "Network Settings"
msgstr "வலைப்பின்னல் அமைப்புகள்"
@ -1554,14 +1537,26 @@ msgstr "வேறு பயனராக உள்நுழைக"
msgid "Unlock Window"
msgstr "சாளர பூட்டு திறக்கவும்"
#: ../js/ui/viewSelector.js:99
#: ../js/ui/viewSelector.js:104
msgid "Applications"
msgstr "பயன்பாடுகள்"
#: ../js/ui/viewSelector.js:103
#: ../js/ui/viewSelector.js:108
msgid "Search"
msgstr "தேடு"
#: ../js/ui/wanda.js:77
msgid ""
"Sorry, no wisdom for you today:\n"
"%s"
msgstr ""
"மன்னிக்க இன்றூ உங்களுக்கு பொன்மொழி இல்லை:\n"
"%s"
#: ../js/ui/wanda.js:81
msgid "%s the Oracle says"
msgstr "%s அசரீரி சொல்லுகிறது"
#: ../js/ui/windowAttentionHandler.js:19
msgid "'%s' is ready"
msgstr "'%s' தயாராக உள்ளது"
@ -1614,23 +1609,23 @@ msgstr[1] "%u உள்ளீடுகள்"
msgid "System Sounds"
msgstr "கணினி ஒலிகள்"
#: ../src/main.c:351
#: ../src/main.c:353
msgid "Print version"
msgstr "அச்சுப் பதிப்பு"
#: ../src/main.c:357
#: ../src/main.c:359
msgid "Mode used by GDM for login screen"
msgstr "ஜிடிஎம் உள்நுழைவு திரைக்கு பயன்படுத்தும் பாங்கு"
#: ../src/main.c:363
#: ../src/main.c:365
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "உள்நுழைவு திரைக்கு குறிப்பிட்ட பாங்கை, எ.கா. \"gdm\" பயன்படுத்துக"
#: ../src/main.c:369
#: ../src/main.c:371
msgid "List possible modes"
msgstr "இயன்ற பாங்குகளின் பட்டியல்"
#: ../src/shell-app.c:639
#: ../src/shell-app.c:644
#, c-format
msgid "Failed to launch '%s'"
msgstr "'%s' ஐ துவக்க முடியவில்லை"
@ -1734,3 +1729,9 @@ msgstr "பயனர் உறுதிப்படுத்தல் உரை
#~ "ஸ்க்ரீன்காஸ்ட் இல் பதிவாவனக்கான கோப்புப்பெயர் தனித்தன்மை வாய்ந்தது. இது நடப்பு தேதியை "
#~ "அடிப்படையாக கொண்டது; இந்த பின்னொட்டை பயன்படுத்தும். பதிவதை வேறு கொள்கலத்தின் ஒழுங்கில் "
#~ "மாற்றுகையில் இதையும் மாற்ற வேண்டும்."
#~ msgid "There was an error loading the preferences dialog for %s:"
#~ msgstr "%s க்கு விருப்பங்கள் உரையாடலை ஏற்றுகையில் பிழை நேர்ந்தது:"
#~ msgid "Extension"
#~ msgstr "நீட்சி"

File diff suppressed because it is too large Load Diff

View File

@ -156,10 +156,8 @@ libst_1_0_la_SOURCES = \
$(st_source_private_h) \
$(st_source_private_c) \
$(st_source_h) \
$(NULL)
nodist_libst_1_0_la_SOURCES = \
$(st_built_sources) \
st.h \
$(st_built_sources) \
$(NULL)
libst_1_0_la_CPPFLAGS = $(st_cflags)
libst_1_0_la_LDFLAGS = $(LDADD)

View File

@ -4,6 +4,8 @@ tray_cflags = \
$(TRAY_CFLAGS) \
$(NULL)
BUILT_SOURCES += $(tray_built_sources)
# please, keep this sorted alphabetically
tray_source = \
tray/na-tray-child.c \
@ -17,6 +19,7 @@ noinst_LTLIBRARIES += libtray.la
libtray_la_LIBADD = $(TRAY_LIBS)
libtray_la_SOURCES = \
$(tray_source) \
$(tray_built_sources) \
$(NULL)
libtray_la_CPPFLAGS = $(tray_cflags)
libtray_la_LDFLAGS = $(LDADD)

View File

@ -75,7 +75,8 @@ gnome_shell_cflags = \
-DDATADIR=\"$(datadir)\" \
-DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\"
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
-DJSDIR=\"$(pkgdatadir)/js\"
privlibdir = $(pkglibdir)
privlib_LTLIBRARIES = libgnome-shell-js.la libgnome-shell-menu.la libgnome-shell.la
@ -151,6 +152,7 @@ libgnome_shell_base_la_SOURCES = \
$(NULL)
libgnome_shell_sources = \
$(shell_built_sources) \
$(shell_public_headers_h) \
shell-app-private.h \
shell-app-system-private.h \
@ -171,17 +173,10 @@ libgnome_shell_sources = \
shell-wm.c \
$(NULL)
libgnome_shell_built_sources = \
$(shell_built_sources) \
$(top_builddir)/js/js-resources.c \
$(top_builddir)/js/js-resources.h \
$(NULL)
libgnome_shell_la_SOURCES = $(libgnome_shell_sources)
nodist_libgnome_shell_la_SOURCES = $(libgnome_shell_built_sources)
libgnome_shell_la_gir_sources = \
$(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_base_la_SOURCES) $(libgnome_shell_sources) $(libgnome_shell_built_sources))
$(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_base_la_SOURCES) $(libgnome_shell_sources))
gnome_shell_SOURCES = main.c
gnome_shell_CPPFLAGS = \
@ -196,7 +191,6 @@ gnome_shell_DEPENDENCIES = libgnome-shell.la
if HAVE_MUTTER_WAYLAND
libgnome_shell_wayland_la_SOURCES = $(libgnome_shell_sources)
nodist_libgnome_shell_wayland_la_SOURCES = $(libgnome_shell_built_sources)
gnome_shell_wayland_SOURCES = main.c
gnome_shell_wayland_CPPFLAGS = \
@ -213,7 +207,7 @@ endif HAVE_MUTTER_WAYLAND
libgnome_shell_js_la_SOURCES = \
shell-js.h \
shell-js.cpp \
shell-js.c \
$(NULL)
libgnome_shell_js_la_LIBADD = \

View File

@ -29,6 +29,8 @@
#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"

View File

@ -12,9 +12,9 @@ G_BEGIN_DECLS
ShellApp* _shell_app_new_for_window (MetaWindow *window);
ShellApp* _shell_app_new (GDesktopAppInfo *info);
ShellApp* _shell_app_new (GMenuTreeEntry *entry);
void _shell_app_set_app_info (ShellApp *app, GDesktopAppInfo *info);
void _shell_app_set_entry (ShellApp *app, GMenuTreeEntry *entry);
void _shell_app_handle_startup_sequence (ShellApp *app, SnStartupSequence *sequence);

View File

@ -38,12 +38,18 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
struct _ShellAppSystemPrivate {
GMenuTree *apps_tree;
GHashTable *running_apps;
GHashTable *visible_id_to_app;
GHashTable *id_to_app;
GHashTable *startup_wm_class_to_id;
GHashTable *startup_wm_class_to_app;
GSList *known_vendor_prefixes;
};
static void shell_app_system_finalize (GObject *object);
static void on_apps_tree_changed_cb (GMenuTree *tree, gpointer user_data);
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
@ -71,45 +77,10 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
}
static void
scan_startup_wm_class_to_id (ShellAppSystem *self)
{
ShellAppSystemPrivate *priv = self->priv;
GList *apps, *l;
g_hash_table_remove_all (priv->startup_wm_class_to_id);
apps = g_app_info_get_all ();
for (l = apps; l != NULL; l = l->next)
{
GAppInfo *info = l->data;
const char *startup_wm_class, *id;
id = g_app_info_get_id (info);
startup_wm_class = g_desktop_app_info_get_startup_wm_class (G_DESKTOP_APP_INFO (info));
if (startup_wm_class != NULL)
g_hash_table_insert (priv->startup_wm_class_to_id, (char *) startup_wm_class, (char *) id);
}
g_list_free_full (apps, g_object_unref);
}
static void
installed_changed (GAppInfoMonitor *monitor,
gpointer user_data)
{
ShellAppSystem *self = user_data;
scan_startup_wm_class_to_id (self);
g_signal_emit (self, signals[INSTALLED_CHANGED], 0, NULL);
}
static void
shell_app_system_init (ShellAppSystem *self)
{
ShellAppSystemPrivate *priv;
GAppInfoMonitor *monitor;
self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
SHELL_TYPE_APP_SYSTEM,
@ -120,11 +91,19 @@ shell_app_system_init (ShellAppSystem *self)
NULL,
(GDestroyNotify)g_object_unref);
priv->startup_wm_class_to_id = g_hash_table_new (g_str_hash, g_str_equal);
/* All the objects in this hash table are owned by id_to_app */
priv->visible_id_to_app = g_hash_table_new (g_str_hash, g_str_equal);
monitor = g_app_info_monitor_get ();
g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
installed_changed (monitor, self);
priv->startup_wm_class_to_app = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL,
(GDestroyNotify)g_object_unref);
/* We want to track NoDisplay apps, so we add INCLUDE_NODISPLAY. We'll
* filter NoDisplay apps out when showing them to the user. */
priv->apps_tree = gmenu_tree_new ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
g_signal_connect (priv->apps_tree, "changed", G_CALLBACK (on_apps_tree_changed_cb), self);
on_apps_tree_changed_cb (priv->apps_tree, self);
}
static void
@ -133,13 +112,313 @@ shell_app_system_finalize (GObject *object)
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
ShellAppSystemPrivate *priv = self->priv;
g_object_unref (priv->apps_tree);
g_hash_table_destroy (priv->running_apps);
g_hash_table_destroy (priv->id_to_app);
g_hash_table_destroy (priv->startup_wm_class_to_id);
g_hash_table_destroy (priv->visible_id_to_app);
g_hash_table_destroy (priv->startup_wm_class_to_app);
g_slist_free_full (priv->known_vendor_prefixes, g_free);
priv->known_vendor_prefixes = NULL;
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
}
static char *
get_prefix_for_entry (GMenuTreeEntry *entry)
{
char *prefix = NULL, *file_prefix = NULL;
const char *id;
GFile *file;
char *name;
int i = 0;
id = gmenu_tree_entry_get_desktop_file_id (entry);
file = g_file_new_for_path (gmenu_tree_entry_get_desktop_file_path (entry));
name = g_file_get_basename (file);
if (!name)
{
g_object_unref (file);
return NULL;
}
for (i = 0; vendor_prefixes[i]; i++)
{
if (g_str_has_prefix (name, vendor_prefixes[i]))
{
file_prefix = g_strdup (vendor_prefixes[i]);
break;
}
}
while (strcmp (name, id) != 0)
{
char *t;
char *pname;
GFile *parent = g_file_get_parent (file);
if (!parent)
{
g_warn_if_reached ();
break;
}
pname = g_file_get_basename (parent);
if (!pname)
{
g_object_unref (parent);
break;
}
if (!g_strstr_len (id, -1, pname))
{
/* handle <LegacyDir prefix="..."> */
char *t;
size_t name_len = strlen (name);
size_t id_len = strlen (id);
char *t_id = g_strdup (id);
t_id[id_len - name_len] = '\0';
t = g_strdup(t_id);
g_free (prefix);
g_free (t_id);
g_free (name);
name = g_strdup (id);
prefix = t;
g_object_unref (file);
file = parent;
g_free (pname);
g_free (file_prefix);
file_prefix = NULL;
break;
}
t = g_strconcat (pname, "-", name, NULL);
g_free (name);
name = t;
t = g_strconcat (pname, "-", prefix, NULL);
g_free (prefix);
prefix = t;
g_object_unref (file);
file = parent;
g_free (pname);
}
if (file)
g_object_unref (file);
if (strcmp (name, id) == 0)
{
g_free (name);
if (file_prefix && !prefix)
return file_prefix;
if (file_prefix)
{
char *t = g_strconcat (prefix, "-", file_prefix, NULL);
g_free (prefix);
g_free (file_prefix);
prefix = t;
}
return prefix;
}
g_free (name);
g_free (prefix);
g_free (file_prefix);
g_return_val_if_reached (NULL);
}
static void
get_flattened_entries_recurse (GMenuTreeDirectory *dir,
GHashTable *entry_set)
{
GMenuTreeIter *iter = gmenu_tree_directory_iter (dir);
GMenuTreeItemType next_type;
while ((next_type = gmenu_tree_iter_next (iter)) != GMENU_TREE_ITEM_INVALID)
{
gpointer item = NULL;
switch (next_type)
{
case GMENU_TREE_ITEM_ENTRY:
{
GMenuTreeEntry *entry;
item = entry = gmenu_tree_iter_get_entry (iter);
/* Key is owned by entry */
g_hash_table_replace (entry_set,
(char*)gmenu_tree_entry_get_desktop_file_id (entry),
gmenu_tree_item_ref (entry));
}
break;
case GMENU_TREE_ITEM_DIRECTORY:
{
item = gmenu_tree_iter_get_directory (iter);
get_flattened_entries_recurse ((GMenuTreeDirectory*)item, entry_set);
}
break;
default:
break;
}
if (item != NULL)
gmenu_tree_item_unref (item);
}
gmenu_tree_iter_unref (iter);
}
static GHashTable *
get_flattened_entries_from_tree (GMenuTree *tree)
{
GHashTable *table;
GMenuTreeDirectory *root;
table = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
(GDestroyNotify) gmenu_tree_item_unref);
root = gmenu_tree_get_root_directory (tree);
if (root != NULL)
get_flattened_entries_recurse (root, table);
gmenu_tree_item_unref (root);
return table;
}
static void
on_apps_tree_changed_cb (GMenuTree *tree,
gpointer user_data)
{
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
GError *error = NULL;
GHashTable *new_apps;
GHashTableIter iter;
gpointer key, value;
g_assert (tree == self->priv->apps_tree);
g_hash_table_remove_all (self->priv->visible_id_to_app);
g_slist_free_full (self->priv->known_vendor_prefixes, g_free);
self->priv->known_vendor_prefixes = NULL;
if (!gmenu_tree_load_sync (self->priv->apps_tree, &error))
{
if (error)
{
g_warning ("Failed to load apps: %s", error->message);
g_error_free (error);
}
else
{
g_warning ("Failed to load apps");
}
return;
}
new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
g_hash_table_iter_init (&iter, new_apps);
while (g_hash_table_iter_next (&iter, &key, &value))
{
const char *id = key;
GMenuTreeEntry *entry = value;
GMenuTreeEntry *old_entry;
char *prefix;
ShellApp *app;
GDesktopAppInfo *info;
const char *startup_wm_class;
prefix = get_prefix_for_entry (entry);
if (prefix != NULL
&& !g_slist_find_custom (self->priv->known_vendor_prefixes, prefix,
(GCompareFunc)g_strcmp0))
self->priv->known_vendor_prefixes = g_slist_append (self->priv->known_vendor_prefixes,
prefix);
else
g_free (prefix);
app = g_hash_table_lookup (self->priv->id_to_app, id);
if (app != NULL)
{
/* We hold a reference to the original entry temporarily,
* because otherwise the hash table would be referencing
* potentially free'd memory until we replace it below with
* the new data.
*/
old_entry = shell_app_get_tree_entry (app);
gmenu_tree_item_ref (old_entry);
_shell_app_set_entry (app, entry);
g_object_ref (app); /* Extra ref, removed in _replace below */
}
else
{
old_entry = NULL;
app = _shell_app_new (entry);
}
/* Note that "id" is owned by app->entry. Since we're always
* setting a new entry, even if the app already exists in the
* hash table we need to replace the key so that the new id
* string is pointed to.
*/
g_hash_table_replace (self->priv->id_to_app, (char*)id, app);
if (!gmenu_tree_entry_get_is_nodisplay_recurse (entry))
g_hash_table_replace (self->priv->visible_id_to_app, (char*)id, app);
if (old_entry)
{
GDesktopAppInfo *old_info;
const gchar *old_startup_wm_class;
old_info = gmenu_tree_entry_get_app_info (old_entry);
old_startup_wm_class = g_desktop_app_info_get_startup_wm_class (old_info);
if (old_startup_wm_class)
g_hash_table_remove (self->priv->startup_wm_class_to_app, old_startup_wm_class);
}
info = gmenu_tree_entry_get_app_info (entry);
startup_wm_class = g_desktop_app_info_get_startup_wm_class (info);
if (startup_wm_class)
g_hash_table_replace (self->priv->startup_wm_class_to_app,
(char*)startup_wm_class, g_object_ref (app));
if (old_entry)
gmenu_tree_item_unref (old_entry);
}
/* Now iterate over the apps again; we need to unreference any apps
* which have been removed. The JS code may still be holding a
* reference; that's fine.
*/
g_hash_table_iter_init (&iter, self->priv->id_to_app);
while (g_hash_table_iter_next (&iter, &key, &value))
{
const char *id = key;
if (!g_hash_table_lookup (new_apps, id))
g_hash_table_iter_remove (&iter);
}
g_hash_table_destroy (new_apps);
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
}
/**
* shell_app_system_get_tree:
*
* Return Value: (transfer none): The #GMenuTree for apps
*/
GMenuTree *
shell_app_system_get_tree (ShellAppSystem *self)
{
return self->priv->apps_tree;
}
/**
* shell_app_system_get_default:
*
@ -167,21 +446,61 @@ ShellApp *
shell_app_system_lookup_app (ShellAppSystem *self,
const char *id)
{
ShellAppSystemPrivate *priv = self->priv;
return g_hash_table_lookup (self->priv->id_to_app, id);
}
/**
* shell_app_system_lookup_app_by_tree_entry:
* @system: a #ShellAppSystem
* @entry: a #GMenuTreeEntry
*
* Find a #ShellApp corresponding to a #GMenuTreeEntry.
*
* Return value: (transfer none): The #ShellApp for @entry, or %NULL if none
*/
ShellApp *
shell_app_system_lookup_app_by_tree_entry (ShellAppSystem *self,
GMenuTreeEntry *entry)
{
/* If we looked up directly in ->entry_to_app, we'd lose the
* override of running apps. Thus, indirect through the id.
*/
return shell_app_system_lookup_app (self, gmenu_tree_entry_get_desktop_file_id (entry));
}
/**
* shell_app_system_lookup_app_for_path:
* @system: a #ShellAppSystem
* @desktop_path: (type utf8): UTF-8 encoded absolute file name
*
* Find or create a #ShellApp corresponding to a given absolute file
* name which must be in the standard paths (XDG_DATA_DIRS). For
* files outside the datadirs, this function returns %NULL.
*
* Return value: (transfer none): The #ShellApp for id, or %NULL if none
*/
ShellApp *
shell_app_system_lookup_app_for_path (ShellAppSystem *system,
const char *desktop_path)
{
const char *basename;
const char *app_path;
ShellApp *app;
GDesktopAppInfo *info;
app = g_hash_table_lookup (priv->id_to_app, id);
if (app)
return app;
basename = g_strrstr (desktop_path, "/");
if (basename)
basename += 1;
else
basename = desktop_path;
info = g_desktop_app_info_new (id);
if (!info)
app = shell_app_system_lookup_app (system, basename);
if (!app)
return NULL;
app_path = g_desktop_app_info_get_filename (shell_app_get_app_info (app));
if (strcmp (desktop_path, app_path) != 0)
return NULL;
app = _shell_app_new (info);
g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app);
g_object_unref (info);
return app;
}
@ -201,15 +520,15 @@ shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
const char *name)
{
ShellApp *result;
const char *const *prefix;
GSList *prefix;
result = shell_app_system_lookup_app (system, name);
if (result != NULL)
return result;
for (prefix = vendor_prefixes; *prefix != NULL; prefix++)
for (prefix = system->priv->known_vendor_prefixes; prefix; prefix = g_slist_next (prefix))
{
char *tmpid = g_strconcat (*prefix, name, NULL);
char *tmpid = g_strconcat ((char*)prefix->data, name, NULL);
result = shell_app_system_lookup_app (system, tmpid);
g_free (tmpid);
if (result != NULL)
@ -284,16 +603,10 @@ ShellApp *
shell_app_system_lookup_startup_wmclass (ShellAppSystem *system,
const char *wmclass)
{
const char *id;
if (wmclass == NULL)
return NULL;
id = g_hash_table_lookup (system->priv->startup_wm_class_to_id, wmclass);
if (id == NULL)
return NULL;
return shell_app_system_lookup_app (system, id);
return g_hash_table_lookup (system->priv->startup_wm_class_to_app, wmclass);
}
void
@ -368,22 +681,13 @@ sort_and_concat_results (ShellAppSystem *system,
GSList *prefix_matches,
GSList *substring_matches)
{
GSList *matches = NULL;
GSList *l;
prefix_matches = g_slist_sort_with_data (prefix_matches,
compare_apps_by_usage,
system);
substring_matches = g_slist_sort_with_data (substring_matches,
compare_apps_by_usage,
system);
for (l = substring_matches; l != NULL; l = l->next)
matches = g_slist_prepend (matches, (char *) shell_app_get_id (SHELL_APP (l->data)));
for (l = prefix_matches; l != NULL; l = l->next)
matches = g_slist_prepend (matches, (char *) shell_app_get_id (SHELL_APP (l->data)));
return g_slist_reverse (matches);
return g_slist_concat (prefix_matches, substring_matches);
}
/**
@ -430,6 +734,7 @@ search_tree (ShellAppSystem *self,
g_slist_free_full (normalized_terms, g_free);
return sort_and_concat_results (self, prefix_results, substring_results);
}
/**
@ -439,26 +744,26 @@ search_tree (ShellAppSystem *self,
*
* Search through applications for the given search terms.
*
* Returns: (transfer container) (element-type utf8): List of applications
* Returns: (transfer container) (element-type ShellApp): List of applications
*/
GSList *
shell_app_system_initial_search (ShellAppSystem *self,
GSList *terms)
{
return search_tree (self, terms, self->priv->id_to_app);
return search_tree (self, terms, self->priv->visible_id_to_app);
}
/**
* shell_app_system_subsearch:
* @system: A #ShellAppSystem
* @previous_results: (element-type utf8): List of previous results
* @previous_results: (element-type ShellApp): List of previous results
* @terms: (element-type utf8): List of terms, logical AND
*
* Search through a previous result set; for more information, see
* js/ui/search.js. Note that returned strings are only valid until
* a return to the main loop.
*
* Returns: (transfer container) (element-type utf8): List of application identifiers
* Returns: (transfer container) (element-type ShellApp): List of application identifiers
*/
GSList *
shell_app_system_subsearch (ShellAppSystem *system,
@ -474,8 +779,8 @@ shell_app_system_subsearch (ShellAppSystem *system,
for (iter = previous_results; iter; iter = iter->next)
{
ShellApp *app = shell_app_system_lookup_app (system, iter->data);
ShellApp *app = iter->data;
_shell_app_do_match (app, normalized_terms,
&prefix_results,
&substring_results);

View File

@ -5,6 +5,8 @@
#include <gio/gio.h>
#include <clutter/clutter.h>
#include <meta/window.h>
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
#include <gmenu-tree.h>
#include "shell-app.h"
@ -37,8 +39,14 @@ struct _ShellAppSystemClass
GType shell_app_system_get_type (void) G_GNUC_CONST;
ShellAppSystem *shell_app_system_get_default (void);
GMenuTree *shell_app_system_get_tree (ShellAppSystem *system);
ShellApp *shell_app_system_lookup_app (ShellAppSystem *system,
const char *id);
ShellApp *shell_app_system_lookup_app_by_tree_entry (ShellAppSystem *system,
GMenuTreeEntry *entry);
ShellApp *shell_app_system_lookup_app_for_path (ShellAppSystem *system,
const char *desktop_path);
ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
const char *id);

View File

@ -17,12 +17,6 @@
#include "st.h"
#include "gtkactionmuxer.h"
#ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h>
#include <errno.h>
#include <unistd.h>
#endif
typedef enum {
MATCH_NONE,
MATCH_SUBSTRING, /* Not prefix, substring */
@ -43,7 +37,7 @@ typedef struct {
GSList *windows;
/* Whether or not we need to resort the windows; this is done on demand */
guint window_sort_stale : 1;
gboolean window_sort_stale : 1;
/* DBus property notification subscription */
guint properties_changed_id : 1;
@ -59,7 +53,7 @@ typedef struct {
* SECTION:shell-app
* @short_description: Object representing an application
*
* This object wraps a #GDesktopAppInfo, providing methods and signals
* This object wraps a #GMenuTreeEntry, providing methods and signals
* primarily useful for running applications.
*/
struct _ShellApp
@ -70,7 +64,7 @@ struct _ShellApp
ShellAppState state;
GDesktopAppInfo *info; /* If NULL, this app is backed by one or more
GMenuTreeEntry *entry; /* If NULL, this app is backed by one or more
* MetaWindow. For purposes of app title
* etc., we use the first window added,
* because it's most likely to be what we
@ -143,15 +137,15 @@ shell_app_get_property (GObject *gobject,
const char *
shell_app_get_id (ShellApp *app)
{
if (app->info)
return g_app_info_get_id (G_APP_INFO (app->info));
if (app->entry)
return gmenu_tree_entry_get_desktop_file_id (app->entry);
return app->window_id_string;
}
static MetaWindow *
window_backed_app_get_window (ShellApp *app)
{
g_assert (app->info == NULL);
g_assert (app->entry == NULL);
g_assert (app->running_state);
g_assert (app->running_state->windows);
return app->running_state->windows->data;
@ -200,10 +194,10 @@ shell_app_create_icon_texture (ShellApp *app,
ret = NULL;
if (app->info == NULL)
if (app->entry == NULL)
return window_backed_app_get_icon (app, size);
icon = g_app_info_get_icon (G_APP_INFO (app->info));
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
if (icon != NULL)
ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, size);
@ -251,7 +245,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
info = NULL;
icon = g_app_info_get_icon (G_APP_INFO (app->info));
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
if (icon != NULL)
{
info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
@ -353,7 +347,7 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
* property tracking bits, and this helps us visually distinguish
* app-tracked from not.
*/
if (!app->info)
if (!app->entry)
return window_backed_app_get_icon (app, size);
/* Use icon: prefix so that we get evicted from the cache on
@ -390,8 +384,8 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
const char *
shell_app_get_name (ShellApp *app)
{
if (app->info)
return g_app_info_get_name (G_APP_INFO (app->info));
if (app->entry)
return g_app_info_get_name (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
else
{
MetaWindow *window = window_backed_app_get_window (app);
@ -407,8 +401,8 @@ shell_app_get_name (ShellApp *app)
const char *
shell_app_get_description (ShellApp *app)
{
if (app->info)
return g_app_info_get_description (G_APP_INFO (app->info));
if (app->entry)
return g_app_info_get_description (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
else
return NULL;
}
@ -423,7 +417,7 @@ shell_app_get_description (ShellApp *app)
gboolean
shell_app_is_window_backed (ShellApp *app)
{
return app->info == NULL;
return app->entry == NULL;
}
typedef struct {
@ -639,7 +633,12 @@ shell_app_activate_full (ShellApp *app,
case SHELL_APP_STATE_STOPPED:
{
GError *error = NULL;
if (!shell_app_launch (app, timestamp, workspace, &error))
if (!shell_app_launch (app,
timestamp,
NULL,
workspace,
NULL,
&error))
{
char *msg;
msg = g_strdup_printf (_("Failed to launch '%s'"), shell_app_get_name (app));
@ -671,7 +670,7 @@ void
shell_app_open_new_window (ShellApp *app,
int workspace)
{
g_return_if_fail (app->info != NULL);
g_return_if_fail (app->entry != NULL);
/* Here we just always launch the application again, even if we know
* it was already running. For most applications this
@ -681,7 +680,12 @@ shell_app_open_new_window (ShellApp *app,
* as say Pidgin. Ideally, we have the application express to us
* that it supports an explicit new-window action.
*/
shell_app_launch (app, 0, workspace, NULL);
shell_app_launch (app,
0,
NULL,
workspace,
NULL,
NULL);
}
/**
@ -861,24 +865,25 @@ _shell_app_new_for_window (MetaWindow *window)
}
ShellApp *
_shell_app_new (GDesktopAppInfo *info)
_shell_app_new (GMenuTreeEntry *info)
{
ShellApp *app;
app = g_object_new (SHELL_TYPE_APP, NULL);
_shell_app_set_app_info (app, info);
_shell_app_set_entry (app, info);
return app;
}
void
_shell_app_set_app_info (ShellApp *app,
GDesktopAppInfo *info)
_shell_app_set_entry (ShellApp *app,
GMenuTreeEntry *entry)
{
g_clear_object (&app->info);
app->info = g_object_ref (info);
if (app->entry != NULL)
gmenu_tree_item_unref (app->entry);
app->entry = gmenu_tree_item_ref (entry);
if (app->name_collation_key != NULL)
g_free (app->name_collation_key);
app->name_collation_key = g_utf8_collate_key (shell_app_get_name (app), -1);
@ -1167,50 +1172,40 @@ _gather_pid_callback (GDesktopAppInfo *gapp,
app);
}
#ifdef HAVE_SYSTEMD
/* This sets up the launched application to log to the journal
* using its own identifier, instead of just "gnome-session".
*/
static void
app_child_setup (gpointer user_data)
{
const char *appid = user_data;
int res;
int journalfd = sd_journal_stream_fd (appid, LOG_INFO, FALSE);
if (journalfd >= 0)
{
do
res = dup2 (journalfd, 1);
while (G_UNLIKELY (res == -1 && errno == EINTR));
do
res = dup2 (journalfd, 2);
while (G_UNLIKELY (res == -1 && errno == EINTR));
(void) close (journalfd);
}
}
#endif
/**
* shell_app_launch:
* @timestamp: Event timestamp, or 0 for current event timestamp
* @uris: (element-type utf8): List of uris to pass to application
* @workspace: Start on this workspace, or -1 for default
* @startup_id: (out): Returned startup notification ID, or %NULL if none
* @error: A #GError
*/
gboolean
shell_app_launch (ShellApp *app,
guint timestamp,
GList *uris,
int workspace,
char **startup_id,
GError **error)
{
GDesktopAppInfo *gapp;
GdkAppLaunchContext *context;
gboolean ret;
ShellGlobal *global;
MetaScreen *screen;
GdkDisplay *gdisplay;
if (app->info == NULL)
if (startup_id)
*startup_id = NULL;
if (app->entry == NULL)
{
MetaWindow *window = window_backed_app_get_window (app);
/* We can't pass URIs into a window; shouldn't hit this
* code path. If we do, fix the caller to disallow it.
*/
g_return_val_if_fail (uris == NULL, TRUE);
meta_window_activate (window, timestamp);
return TRUE;
}
@ -1229,14 +1224,11 @@ shell_app_launch (ShellApp *app,
gdk_app_launch_context_set_timestamp (context, timestamp);
gdk_app_launch_context_set_desktop (context, workspace);
ret = g_desktop_app_info_launch_uris_as_manager (app->info, NULL,
gapp = gmenu_tree_entry_get_app_info (app->entry);
ret = g_desktop_app_info_launch_uris_as_manager (gapp, uris,
G_APP_LAUNCH_CONTEXT (context),
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
#ifdef HAVE_SYSTEMD
app_child_setup, (gpointer)shell_app_get_id (app),
#else
NULL, NULL,
#endif
_gather_pid_callback, app,
error);
g_object_unref (context);
@ -1253,7 +1245,21 @@ shell_app_launch (ShellApp *app,
GDesktopAppInfo *
shell_app_get_app_info (ShellApp *app)
{
return app->info;
if (app->entry)
return gmenu_tree_entry_get_app_info (app->entry);
return NULL;
}
/**
* shell_app_get_tree_entry:
* @app: a #ShellApp
*
* Returns: (transfer none): The #GMenuTreeEntry for this app, or %NULL if backed by a window
*/
GMenuTreeEntry *
shell_app_get_tree_entry (ShellApp *app)
{
return app->entry;
}
static void
@ -1368,22 +1374,24 @@ shell_app_init_search_data (ShellApp *app)
const char *exec;
const char * const *keywords;
char *normalized_exec;
GDesktopAppInfo *appinfo;
name = g_app_info_get_name (G_APP_INFO (app->info));
appinfo = gmenu_tree_entry_get_app_info (app->entry);
name = g_app_info_get_name (G_APP_INFO (appinfo));
app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name);
generic_name = g_desktop_app_info_get_generic_name (app->info);
generic_name = g_desktop_app_info_get_generic_name (appinfo);
if (generic_name)
app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name);
else
app->casefolded_generic_name = NULL;
exec = g_app_info_get_executable (G_APP_INFO (app->info));
exec = g_app_info_get_executable (G_APP_INFO (appinfo));
normalized_exec = shell_util_normalize_casefold_and_unaccent (exec);
app->casefolded_exec = trim_exec_line (normalized_exec);
g_free (normalized_exec);
keywords = g_desktop_app_info_get_keywords (app->info);
keywords = g_desktop_app_info_get_keywords (appinfo);
if (keywords)
{
@ -1504,14 +1512,16 @@ _shell_app_do_match (ShellApp *app,
GSList **substring_results)
{
ShellAppSearchMatch match;
GAppInfo *appinfo;
g_assert (app != NULL);
/* Skip window-backed apps */
if (app->info == NULL)
appinfo = (GAppInfo*)shell_app_get_app_info (app);
if (appinfo == NULL)
return;
/* Skip not-visible apps */
if (!g_app_info_should_show (G_APP_INFO (app->info)))
if (!g_app_info_should_show (appinfo))
return;
match = _shell_app_match_search_terms (app, terms);
@ -1540,7 +1550,11 @@ shell_app_dispose (GObject *object)
{
ShellApp *app = SHELL_APP (object);
g_clear_object (&app->info);
if (app->entry)
{
gmenu_tree_item_unref (app->entry);
app->entry = NULL;
}
if (app->running_state)
{

View File

@ -4,8 +4,9 @@
#include <clutter/clutter.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <meta/window.h>
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
#include <gmenu-tree.h>
G_BEGIN_DECLS
@ -38,6 +39,7 @@ GType shell_app_get_type (void) G_GNUC_CONST;
const char *shell_app_get_id (ShellApp *app);
GMenuTreeEntry *shell_app_get_tree_entry (ShellApp *app);
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
@ -71,7 +73,9 @@ gboolean shell_app_is_on_workspace (ShellApp *app, MetaWorkspace *workspace);
gboolean shell_app_launch (ShellApp *app,
guint timestamp,
GList *uris,
int workspace,
char **startup_id,
GError **error);
int shell_app_compare_by_name (ShellApp *app, ShellApp *other);

View File

@ -22,6 +22,7 @@
#include <clutter/x11/clutter-x11.h>
#include <gdk/gdkx.h>
#include <gio/gio.h>
#include <gjs/gjs-module.h>
#include <girepository.h>
#include <meta/display.h>
#include <meta/util.h>
@ -33,11 +34,6 @@
#include <malloc.h>
#endif
#ifdef __OpenBSD__
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#include "shell-enum-types.h"
#include "shell-global-private.h"
#include "shell-perf-log.h"
@ -84,11 +80,10 @@ struct _ShellGlobal {
const char *datadir;
const char *imagedir;
const char *userdatadir;
GFile *userdatadir_path;
GFile *runtime_state_path;
StFocusManager *focus_manager;
GFile *runtime_state_path;
guint work_count;
GSList *leisure_closures;
guint leisure_function_id;
@ -257,7 +252,6 @@ shell_global_init (ShellGlobal *global)
/* Ensure config dir exists for later use */
global->userdatadir = g_build_filename (g_get_user_data_dir (), "gnome-shell", NULL);
g_mkdir_with_parents (global->userdatadir, 0700);
global->userdatadir_path = g_file_new_for_path (global->userdatadir);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
byteorder_string = "LE";
@ -288,16 +282,9 @@ shell_global_init (ShellGlobal *global)
NULL);
ca_context_open (global->sound_context);
if (shell_js)
{
search_path = g_strsplit (shell_js, ":", -1);
}
else
{
search_path = g_malloc0 (2 * sizeof (char *));
search_path[0] = g_strdup ("resource:///org/gnome/shell");
}
if (!shell_js)
shell_js = JSDIR;
search_path = g_strsplit (shell_js, ":", -1);
global->js_context = g_object_new (GJS_TYPE_CONTEXT,
"search-path", search_path,
"js-version", "1.8",
@ -319,7 +306,6 @@ shell_global_finalize (GObject *object)
the_object = NULL;
g_clear_object (&global->userdatadir_path);
g_clear_object (&global->runtime_state_path);
G_OBJECT_CLASS(shell_global_parent_class)->finalize (object);
@ -1114,30 +1100,20 @@ shell_global_reexec_self (ShellGlobal *global)
char *buf_p;
char *buf_end;
GError *error = NULL;
#if defined __linux__
/* Linux specific (I think, anyways). */
if (!g_file_get_contents ("/proc/self/cmdline", &buf, &len, &error))
{
g_warning ("failed to get /proc/self/cmdline: %s", error->message);
return;
}
#elif defined __OpenBSD__
int pid = getpid();
int mib[] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV };
if (sysctl(mib, G_N_ELEMENTS (mib), &buf, &len, NULL, 0) == -1) {
g_warning ("failed to get command line args: %d", errno);
return;
}
#else
return;
#endif
buf_end = buf+len;
arr = g_ptr_array_new ();
/* The cmdline file is NUL-separated */
for (buf_p = buf; buf_p < buf_end; buf_p = buf_p + strlen (buf_p) + 1)
g_ptr_array_add (arr, buf_p);
g_ptr_array_add (arr, NULL);
/* Close all file descriptors other than stdin/stdout/stderr, otherwise
@ -1163,6 +1139,44 @@ shell_global_on_gc (GjsContext *context,
global->last_gc_end_time = g_get_monotonic_time ();
}
/**
* shell_global_get_memory_info:
* @global:
* @meminfo: (out caller-allocates): Output location for memory information
*
* Load process-global data about memory usage.
*/
void
shell_global_get_memory_info (ShellGlobal *global,
ShellMemoryInfo *meminfo)
{
JSContext *context;
gint64 now;
#ifdef HAVE_MALLINFO
{
struct mallinfo info = mallinfo ();
meminfo->glibc_uordblks = info.uordblks;
}
#else
meminfo->glibc_uordblks = 0;
#endif
context = gjs_context_get_native_context (global->js_context);
meminfo->js_bytes = JS_GetGCParameter (JS_GetRuntime (context), JSGC_BYTES);
meminfo->gjs_boxed = (unsigned int) gjs_counter_boxed.value;
meminfo->gjs_gobject = (unsigned int) gjs_counter_object.value;
meminfo->gjs_function = (unsigned int) gjs_counter_function.value;
meminfo->gjs_closure = (unsigned int) gjs_counter_closure.value;
now = g_get_monotonic_time ();
meminfo->last_gc_seconds_ago = (now - global->last_gc_end_time) / G_TIME_SPAN_SECOND;
}
/**
* shell_global_notify_error:
* @global: a #ShellGlobal
@ -1732,14 +1746,31 @@ shell_global_get_session_mode (ShellGlobal *global)
return global->session_mode;
}
static void
save_variant (GFile *dir,
const char *property_name,
GVariant *variant)
static GFile *
get_runtime_state_path (ShellGlobal *global,
const char *property_name)
{
GFile *path = g_file_get_child (dir, property_name);
return g_file_get_child (global->runtime_state_path, property_name);
}
if (variant == NULL || g_variant_get_data (variant) == NULL)
/**
* shell_global_set_runtime_state:
* @global: a #ShellGlobal
* @property_name: Name of the property
* @variant: (allow-none): A #GVariant, or %NULL to unset
*
* Change the value of serialized runtime state.
*/
void
shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name,
GVariant *variant)
{
GFile *path;
path = get_runtime_state_path (global, property_name);
if (variant == NULL)
(void) g_file_delete (path, NULL, NULL);
else
{
@ -1752,17 +1783,29 @@ save_variant (GFile *dir,
g_object_unref (path);
}
static GVariant *
load_variant (GFile *dir,
const char *property_type,
const char *property_name)
/**
* shell_global_get_runtime_state:
* @global: a #ShellGlobal
* @property_type: Expected data type
* @property_name: Name of the property
*
* The shell maintains "runtime" state which does not persist across
* logout or reboot.
*
* Returns: (transfer floating): The value of a serialized property, or %NULL if none stored
*/
GVariant *
shell_global_get_runtime_state (ShellGlobal *global,
const char *property_type,
const char *property_name)
{
GVariant *res = NULL;
GMappedFile *mfile;
GFile *path = g_file_get_child (dir, property_name);
GFile *path;
char *pathstr;
GError *local_error = NULL;
path = get_runtime_state_path (global, property_name);
pathstr = g_file_get_path (path);
mfile = g_mapped_file_new (pathstr, FALSE, &local_error);
if (!mfile)
@ -1786,73 +1829,3 @@ load_variant (GFile *dir,
return res;
}
/**
* shell_global_set_runtime_state:
* @global: a #ShellGlobal
* @property_name: Name of the property
* @variant: (allow-none): A #GVariant, or %NULL to unset
*
* Change the value of serialized runtime state.
*/
void
shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name,
GVariant *variant)
{
save_variant (global->runtime_state_path, property_name, variant);
}
/**
* shell_global_get_runtime_state:
* @global: a #ShellGlobal
* @property_type: Expected data type
* @property_name: Name of the property
*
* The shell maintains "runtime" state which does not persist across
* logout or reboot.
*
* Returns: (transfer floating): The value of a serialized property, or %NULL if none stored
*/
GVariant *
shell_global_get_runtime_state (ShellGlobal *global,
const char *property_type,
const char *property_name)
{
return load_variant (global->runtime_state_path, property_type, property_name);
}
/**
* shell_global_set_persistent_state:
* @global: a #ShellGlobal
* @property_name: Name of the property
* @variant: (allow-none): A #GVariant, or %NULL to unset
*
* Change the value of serialized persistent state.
*/
void
shell_global_set_persistent_state (ShellGlobal *global,
const char *property_name,
GVariant *variant)
{
save_variant (global->userdatadir_path, property_name, variant);
}
/**
* shell_global_get_persistent_state:
* @global: a #ShellGlobal
* @property_type: Expected data type
* @property_name: Name of the property
*
* The shell maintains "persistent" state which will persist after
* logout or reboot.
*
* Returns: (transfer none): The value of a serialized property, or %NULL if none stored
*/
GVariant *
shell_global_get_persistent_state (ShellGlobal *global,
const char *property_type,
const char *property_name)
{
return load_variant (global->userdatadir_path, property_type, property_name);
}

View File

@ -69,6 +69,10 @@ typedef struct {
guint last_gc_seconds_ago;
} ShellMemoryInfo;
void shell_global_get_memory_info (ShellGlobal *global,
ShellMemoryInfo *meminfo);
/* Run-at-leisure API */
void shell_global_begin_work (ShellGlobal *global);
void shell_global_end_work (ShellGlobal *global);
@ -125,19 +129,13 @@ void shell_global_reexec_self (ShellGlobal *global);
const char * shell_global_get_session_mode (ShellGlobal *global);
void shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name,
GVariant *variant);
void shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name,
GVariant *variant);
GVariant * shell_global_get_runtime_state (ShellGlobal *global,
const char *property_type,
const char *property_name);
void shell_global_set_persistent_state (ShellGlobal *global,
const char *property_name,
GVariant *variant);
GVariant * shell_global_get_persistent_state (ShellGlobal *global,
const char *property_type,
const char *property_name);
G_END_DECLS

View File

@ -38,7 +38,7 @@ shell_js_add_extension_importer (const char *target_object_script,
* we should only ever have one context, so this
* should be alright. */
contexts = gjs_context_get_all ();
context = (JSContext*) gjs_context_get_native_context ((GjsContext*)contexts->data);
context = gjs_context_get_native_context (contexts->data);
g_list_free_full (contexts, g_object_unref);
JS_BeginRequest (context);

View File

@ -844,7 +844,6 @@ ShellApp *
shell_startup_sequence_get_app (ShellStartupSequence *sequence)
{
const char *appid;
char *basename;
ShellAppSystem *appsys;
ShellApp *app;
@ -852,10 +851,8 @@ shell_startup_sequence_get_app (ShellStartupSequence *sequence)
if (!appid)
return NULL;
basename = g_path_get_basename (appid);
appsys = shell_app_system_get_default ();
app = shell_app_system_lookup_app (appsys, basename);
g_free (basename);
app = shell_app_system_lookup_app_for_path (appsys, appid);
return app;
}

View File

@ -45,7 +45,7 @@ struct _StAdjustmentPrivate
{
/* Do not sanity-check values while constructing,
* not all properties may be set yet. */
guint is_constructing : 1;
gboolean is_constructing : 1;
gdouble lower;
gdouble upper;

View File

@ -98,8 +98,8 @@ struct _StScrollViewPrivate
StScrollViewFade *fade_effect;
guint row_size_set : 1;
guint column_size_set : 1;
gboolean row_size_set : 1;
gboolean column_size_set : 1;
guint mouse_scroll : 1;
guint overlay_scrollbars : 1;
guint hscrollbar_visible : 1;

View File

@ -45,7 +45,10 @@
#include "st-theme-node.h"
#include "st-theme-private.h"
static void st_theme_constructed (GObject *object);
static GObject *st_theme_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties);
static void st_theme_finalize (GObject *object);
static void st_theme_set_property (GObject *object,
guint prop_id,
@ -111,7 +114,7 @@ st_theme_class_init (StThemeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = st_theme_constructed;
object_class->constructor = st_theme_constructor;
object_class->finalize = st_theme_finalize;
object_class->set_property = st_theme_set_property;
object_class->get_property = st_theme_get_property;
@ -299,15 +302,21 @@ st_theme_get_custom_stylesheets (StTheme *theme)
return result;
}
static void
st_theme_constructed (GObject *object)
static GObject *
st_theme_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
StTheme *theme = ST_THEME (object);
GObject *object;
StTheme *theme;
CRStyleSheet *application_stylesheet;
CRStyleSheet *theme_stylesheet;
CRStyleSheet *default_stylesheet;
G_OBJECT_CLASS (st_theme_parent_class)->constructed (object);
object = (*G_OBJECT_CLASS (st_theme_parent_class)->constructor) (type,
n_construct_properties,
construct_properties);
theme = ST_THEME (object);
application_stylesheet = parse_stylesheet_nofail (theme->application_stylesheet);
theme_stylesheet = parse_stylesheet_nofail (theme->theme_stylesheet);
@ -323,6 +332,8 @@ st_theme_constructed (GObject *object)
insert_stylesheet (theme, theme->application_stylesheet, application_stylesheet);
insert_stylesheet (theme, theme->theme_stylesheet, theme_stylesheet);
insert_stylesheet (theme, theme->default_stylesheet, default_stylesheet);
return object;
}
static void

View File

@ -59,12 +59,13 @@ struct _StWidgetPrivate
StThemeNodeTransition *transition_animation;
guint is_style_dirty : 1;
guint draw_bg_color : 1;
guint draw_border_internal : 1;
guint track_hover : 1;
guint hover : 1;
guint can_focus : 1;
gboolean is_stylable : 1;
gboolean is_style_dirty : 1;
gboolean draw_bg_color : 1;
gboolean draw_border_internal : 1;
gboolean track_hover : 1;
gboolean hover : 1;
gboolean can_focus : 1;
gulong texture_file_changed_id;
@ -104,6 +105,7 @@ enum
PROP_PSEUDO_CLASS,
PROP_STYLE_CLASS,
PROP_STYLE,
PROP_STYLABLE,
PROP_TRACK_HOVER,
PROP_HOVER,
PROP_CAN_FOCUS,
@ -162,6 +164,14 @@ st_widget_set_property (GObject *gobject,
st_widget_set_style (actor, g_value_get_string (value));
break;
case PROP_STYLABLE:
if (actor->priv->is_stylable != g_value_get_boolean (value))
{
actor->priv->is_stylable = g_value_get_boolean (value);
clutter_actor_queue_relayout ((ClutterActor *) gobject);
}
break;
case PROP_TRACK_HOVER:
st_widget_set_track_hover (actor, g_value_get_boolean (value));
break;
@ -219,6 +229,10 @@ st_widget_get_property (GObject *gobject,
g_value_set_string (value, priv->inline_style);
break;
case PROP_STYLABLE:
g_value_set_boolean (value, priv->is_stylable);
break;
case PROP_TRACK_HOVER:
g_value_set_boolean (value, priv->track_hover);
break;
@ -324,8 +338,17 @@ st_widget_dispose (GObject *gobject)
StWidget *actor = ST_WIDGET (gobject);
StWidgetPrivate *priv = ST_WIDGET (actor)->priv;
g_clear_pointer (&priv->theme, g_object_unref);
g_clear_pointer (&priv->theme_node, g_object_unref);
if (priv->theme)
{
g_object_unref (priv->theme);
priv->theme = NULL;
}
if (priv->theme_node)
{
g_object_unref (priv->theme_node);
priv->theme_node = NULL;
}
st_widget_remove_transition (actor);
@ -335,7 +358,11 @@ st_widget_dispose (GObject *gobject)
if (priv->accessible)
priv->accessible = NULL;
g_clear_pointer (&priv->label_actor, g_object_unref);
if (priv->label_actor)
{
g_object_unref (priv->label_actor);
priv->label_actor = NULL;
}
if (priv->texture_file_changed_id != 0)
{
@ -524,6 +551,12 @@ notify_children_of_style_change (ClutterActor *self)
static void
st_widget_real_style_changed (StWidget *self)
{
StWidgetPrivate *priv = ST_WIDGET (self)->priv;
/* application has request this widget is not stylable */
if (!priv->is_stylable)
return;
clutter_actor_queue_redraw ((ClutterActor *) self);
notify_children_of_style_change ((ClutterActor *) self);
}
@ -909,6 +942,20 @@ st_widget_class_init (StWidgetClass *klass)
ST_TYPE_THEME,
ST_PARAM_READWRITE));
/**
* StWidget:stylable:
*
* Enable or disable styling of the widget
*/
pspec = g_param_spec_boolean ("stylable",
"Stylable",
"Whether the table should be styled",
TRUE,
ST_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_STYLABLE,
pspec);
/**
* StWidget:track-hover:
*
@ -1499,6 +1546,7 @@ st_widget_init (StWidget *actor)
int i;
actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
priv->is_stylable = TRUE;
priv->transition_animation = NULL;
priv->local_state_set = atk_state_set_new ();