Compare commits
140 Commits
Author | SHA1 | Date | |
---|---|---|---|
2639e30d9c | |||
78a0218a91 | |||
e12bf8daed | |||
04e2072e2c | |||
7bafe20a34 | |||
554d5aeb7c | |||
3991d2729d | |||
5bc8a0860a | |||
ad03fb0815 | |||
e10d2a68f3 | |||
213ee8d381 | |||
52b1a1b835 | |||
fce2930b85 | |||
735f589b1c | |||
69f17da5ca | |||
5c0ee02251 | |||
0cb4c7e437 | |||
842c792868 | |||
4ba8518462 | |||
143dfb6246 | |||
da4238ec68 | |||
5f9e3edbe1 | |||
1c68aee577 | |||
e8d9a4bd49 | |||
9520e87a38 | |||
f9f5004909 | |||
4f7014b2d5 | |||
01dbfddb64 | |||
6266a22d86 | |||
09fe31179a | |||
78343f4837 | |||
a5619bc0a3 | |||
dcb28aad2a | |||
754cf172f5 | |||
7890af1659 | |||
d27d9fe694 | |||
634a599db6 | |||
5d0d859a1f | |||
40c966fcd6 | |||
d9245598a4 | |||
03b0f4b16b | |||
2daa0d057b | |||
76eca409a3 | |||
d84b018ba7 | |||
027c3d1661 | |||
4965b1ca7b | |||
9cd7ea9371 | |||
dc2468b27b | |||
ea2451d882 | |||
252617bd70 | |||
8bd7003ea7 | |||
280203158c | |||
d456c3f62e | |||
f64d17963b | |||
f12378cf7b | |||
15ff426be8 | |||
c4a6837d56 | |||
e6c28cf509 | |||
a347a75617 | |||
7fc2183826 | |||
b6c3c9891c | |||
d401b493a4 | |||
da1a8308b6 | |||
106d827a21 | |||
1ebb162a00 | |||
9d2791d9f8 | |||
04a00f6564 | |||
a5dd44c77f | |||
8f86fd6bae | |||
d5cd534320 | |||
a5a6fd3bc2 | |||
287ddda5df | |||
7747f1c31d | |||
8097cbbbe3 | |||
e4c07875a3 | |||
026fd4cf35 | |||
87016f9620 | |||
88393f0f65 | |||
f5a9dbb348 | |||
dbf3bb112c | |||
f3186bd501 | |||
3f1a252b91 | |||
1240d6be76 | |||
faf7b62f5c | |||
445011b1e5 | |||
e630fec63a | |||
17421e8a63 | |||
af06b78605 | |||
3749b09366 | |||
27cac10d0c | |||
0590962d36 | |||
c0c20d49a5 | |||
cf7cf45003 | |||
633dd0d9de | |||
b929320d4c | |||
7296bedd8e | |||
e9fbbf4000 | |||
dd44219aa5 | |||
8cc1fe007d | |||
c0b45c9fc4 | |||
41315f45a9 | |||
04d28a0eea | |||
1e9cd3f785 | |||
f462dd6a4c | |||
34e75fc595 | |||
dac513e046 | |||
2c538d247b | |||
f3b7f61e54 | |||
d47ecf19f5 | |||
da19b344b5 | |||
eb66407926 | |||
61c5b8e7d2 | |||
4b09d57ec2 | |||
a16f699dfc | |||
b908a3d70a | |||
d519c7263e | |||
5dedc5d8ba | |||
3ca1784ff4 | |||
b54d512f3f | |||
9d8fb19f55 | |||
1ac4ab7edc | |||
c9b73ac731 | |||
e0b87f1e14 | |||
394743efc8 | |||
27a86a4756 | |||
8ee0ef2cde | |||
43f4682ec4 | |||
5f081b8f8d | |||
5023542882 | |||
88d0731d80 | |||
06cb8c52d7 | |||
4d1358b7ed | |||
0cfa7c1c56 | |||
76928390a3 | |||
af1f9cd76d | |||
2f39f3d146 | |||
f72f39bc26 | |||
2659ba6bb4 | |||
0b8c0c202e | |||
37c8132632 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -43,6 +43,8 @@ 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
|
||||
|
@ -1,7 +1,11 @@
|
||||
# Point to our macro directory and pick up user flags from the environment
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
SUBDIRS = data js src browser-plugin tests po docs
|
||||
SUBDIRS = data js src tests po docs
|
||||
|
||||
if BUILD_BROWSER_PLUGIN
|
||||
SUBDIRS += browser-plugin
|
||||
endif
|
||||
|
||||
if ENABLE_MAN
|
||||
SUBDIRS += man
|
||||
|
39
NEWS
39
NEWS
@ -1,3 +1,42 @@
|
||||
3.11.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]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Sebastien Lafargue, Tim Lunn,
|
||||
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Stas Solovey [ru], Yosef Or Boczko [he], Rafael Ferreira [pt_BR]
|
||||
|
||||
3.10.1
|
||||
======
|
||||
* Make sure lock screen is drawn once before switching user [Giovanni; #708051]
|
||||
|
38
configure.ac
38
configure.ac
@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[3.10.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.11.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,6 +16,7 @@ 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])
|
||||
@ -57,10 +58,25 @@ 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.10.1
|
||||
MUTTER_MIN_VERSION=3.11.1
|
||||
GTK_MIN_VERSION=3.7.9
|
||||
GIO_MIN_VERSION=2.37.0
|
||||
LIBECAL_MIN_VERSION=3.5.3
|
||||
@ -70,7 +86,6 @@ 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
|
||||
|
||||
@ -80,7 +95,6 @@ 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
|
||||
@ -94,6 +108,9 @@ 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)
|
||||
@ -109,12 +126,20 @@ 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`
|
||||
@ -147,6 +172,9 @@ 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])
|
||||
|
@ -1,6 +1,3 @@
|
||||
wandadir = $(pkgdatadir)
|
||||
dist_wanda_DATA = wanda.png
|
||||
|
||||
desktopdir=$(datadir)/applications
|
||||
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
|
||||
if HAVE_MUTTER_WAYLAND
|
||||
|
@ -306,16 +306,13 @@ StScrollBar StButton#vhandle:active {
|
||||
font-size: 12pt;
|
||||
border-bottom: 1px solid #666;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.nm-dialog-item:checked {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.nm-dialog-item-box {
|
||||
spacing: 20px;
|
||||
}
|
||||
|
||||
.nm-dialog-item:selected {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.nm-dialog-icons {
|
||||
spacing: .5em;
|
||||
}
|
||||
@ -1970,6 +1967,11 @@ 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;
|
||||
}
|
||||
@ -2387,6 +2389,10 @@ StScrollBar StButton#vhandle:active {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.login-dialog-user-selection-box {
|
||||
padding: 100px 0;
|
||||
}
|
||||
|
||||
.login-dialog-user-selection-box .login-dialog-not-listed-label {
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
BIN
data/wanda.png
BIN
data/wanda.png
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
132
js/Makefile.am
132
js/Makefile.am
@ -1,7 +1,5 @@
|
||||
NULL =
|
||||
|
||||
EXTRA_DIST = misc/config.js.in
|
||||
CLEANFILES = misc/config.js
|
||||
BUILT_SOURCES =
|
||||
|
||||
misc/config.js: misc/config.js.in Makefile
|
||||
[ -d $(@D) ] || $(mkdir_p) $(@D) ; \
|
||||
@ -14,112 +12,26 @@ misc/config.js: misc/config.js.in Makefile
|
||||
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \
|
||||
$< > $@
|
||||
|
||||
jsdir = $(pkgdatadir)/js
|
||||
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 $<
|
||||
|
||||
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 \
|
||||
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) \
|
||||
$(NULL)
|
||||
|
@ -13,13 +13,15 @@ const _ = Gettext.gettext;
|
||||
const Config = imports.misc.config;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
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 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 GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
|
||||
|
||||
@ -204,11 +206,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(signals, extension) {
|
||||
_extensionFound: function(finder, extension) {
|
||||
let iter = this._model.append();
|
||||
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
|
||||
this._extensionIters[extension.uuid] = iter;
|
||||
|
@ -5,11 +5,13 @@ const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
|
||||
<method name='GetDefaultDevice'>
|
||||
<arg type='o' direction='out' />
|
||||
</method>
|
||||
</interface>;
|
||||
const FprintManagerIface = '<node> \
|
||||
<interface name="net.reactivated.Fprint.Manager"> \
|
||||
<method name="GetDefaultDevice"> \
|
||||
<arg type="o" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);
|
||||
|
||||
|
@ -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: false });
|
||||
let layout = new St.BoxLayout({ vertical: true });
|
||||
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
||||
can_focus: true,
|
||||
@ -68,39 +68,18 @@ const UserListItem = new Lang.Class({
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
|
||||
this._userAvatar = new UserWidget.Avatar(this.user,
|
||||
{ styleClass: 'login-dialog-user-list-item-icon' });
|
||||
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._userWidget = new UserWidget.UserWidget(this.user);
|
||||
layout.add(this._userWidget.actor);
|
||||
|
||||
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
|
||||
scale_x: 0 });
|
||||
textLayout.add(this._timedLoginIndicator,
|
||||
{ x_fill: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_fill: false,
|
||||
y_align: St.Align.END });
|
||||
layout.add(this._timedLoginIndicator);
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
@ -189,7 +168,6 @@ const UserList = new Lang.Class({
|
||||
for (let userName in this._items) {
|
||||
let item = this._items[userName];
|
||||
item.actor.sync_hover();
|
||||
item.syncStyleClasses();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -4,11 +4,13 @@ const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const OVirtCredentialsIface = <interface name='org.ovirt.vdsm.Credentials'>
|
||||
<signal name="UserAuthenticated">
|
||||
<arg type="s" name="token"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const OVirtCredentialsIface = '<node> \
|
||||
<interface name="org.ovirt.vdsm.Credentials"> \
|
||||
<signal name="UserAuthenticated"> \
|
||||
<arg type="s" name="token"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);
|
||||
|
||||
|
@ -5,52 +5,58 @@ const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
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 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 Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
|
||||
|
||||
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 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 Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
|
||||
|
||||
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 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 Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
|
||||
|
||||
const Manager = new Lang.Class({
|
||||
|
108
js/js-resources.gresource.xml
Normal file
108
js/js-resources.gresource.xml
Normal file
@ -0,0 +1,108 @@
|
||||
<?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>
|
@ -174,17 +174,9 @@ 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.collectFromDatadirsAsync('extensions',
|
||||
{ processFile: Lang.bind(this, this._loadExtension),
|
||||
loadedCallback: Lang.bind(this, this._extensionsLoaded),
|
||||
includeUserDir: true,
|
||||
data: perUserDir });
|
||||
FileUtils.collectFromDatadirs('extensions', true, Lang.bind(this, this._loadExtension, perUserDir));
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ExtensionFinder.prototype);
|
||||
|
@ -25,60 +25,27 @@ function listDirAsync(file, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function collectFromDatadirs(subdir, includeUserDir, processFile) {
|
||||
let dataDirs = GLib.get_system_data_dirs();
|
||||
if (params.includeUserDir)
|
||||
if (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);
|
||||
|
||||
_collectFromDirectoryAsync(dir, loadState);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,15 +4,17 @@ const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
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 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 PresenceStatus = {
|
||||
AVAILABLE: 0,
|
||||
@ -30,14 +32,16 @@ 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 = <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>;
|
||||
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>';
|
||||
|
||||
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
|
||||
function Inhibitor(objectPath, initCallback, cancellable) {
|
||||
@ -45,27 +49,29 @@ function Inhibitor(objectPath, initCallback, cancellable) {
|
||||
}
|
||||
|
||||
// Not the full interface, only the methods we use
|
||||
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>;
|
||||
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>';
|
||||
|
||||
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
|
||||
function SessionManager(initCallback, cancellable) {
|
||||
|
@ -7,58 +7,66 @@ const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
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 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 SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
||||
<signal name='Lock' />
|
||||
<signal name='Unlock' />
|
||||
</interface>;
|
||||
const SystemdLoginSessionIface = '<node> \
|
||||
<interface name="org.freedesktop.login1.Session"> \
|
||||
<signal name="Lock" /> \
|
||||
<signal name="Unlock" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
|
||||
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
|
||||
|
||||
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 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 ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
|
||||
<signal name='Lock' />
|
||||
<signal name='Unlock' />
|
||||
</interface>;
|
||||
const ConsoleKitSessionIface = '<node> \
|
||||
<interface name="org.freedesktop.ConsoleKit.Session"> \
|
||||
<signal name="Lock" /> \
|
||||
<signal name="Unlock" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
|
||||
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
|
||||
|
@ -92,37 +92,41 @@ function _findProviderForSid(sid) {
|
||||
// The following are not the complete interfaces, just the methods we need
|
||||
// (or may need in the future)
|
||||
|
||||
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 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 ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
|
||||
|
||||
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 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 ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
|
||||
|
||||
@ -218,20 +222,26 @@ Signals.addSignalMethods(ModemCdma.prototype);
|
||||
// Support for the new ModemManager1 interface (MM >= 0.7)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const BroadbandModemInterface = <interface name="org.freedesktop.ModemManager1.Modem">
|
||||
<property name="SignalQuality" type="(ub)" access="read" />
|
||||
</interface>;
|
||||
const BroadbandModemInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager1.Modem"> \
|
||||
<property name="SignalQuality" type="(ub)" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
|
||||
|
||||
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 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 BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface);
|
||||
|
||||
const BroadbandModemCdmaInterface = <interface name="org.freedesktop.ModemManager1.Modem.ModemCdma">
|
||||
<property name="Sid" type="u" access="read" />
|
||||
</interface>;
|
||||
const BroadbandModemCdmaInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> \
|
||||
<property name="Sid" type="u" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
|
||||
|
||||
const BroadbandModem = new Lang.Class({
|
||||
|
@ -8,19 +8,21 @@ const Signals = imports.signals;
|
||||
|
||||
// Specified in the D-Bus specification here:
|
||||
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
|
||||
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 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 ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
|
||||
|
||||
|
@ -7,12 +7,14 @@ const Signals = imports.signals;
|
||||
|
||||
const ObjectManager = imports.misc.objectManager;
|
||||
|
||||
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>;
|
||||
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>';
|
||||
|
||||
let _smartcardManager = null;
|
||||
|
||||
|
@ -106,6 +106,8 @@ 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;
|
||||
},
|
||||
@ -375,6 +377,9 @@ 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;
|
||||
},
|
||||
|
||||
|
@ -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 app = appSystem.lookup_app_by_tree_entry(entry);
|
||||
if (!entry.get_app_info().get_nodisplay())
|
||||
let appInfo = entry.get_app_info();
|
||||
let app = appSystem.lookup_app(entry.get_desktop_file_id());
|
||||
if (appInfo.should_show())
|
||||
view.addApp(app);
|
||||
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||
let itemDir = iter.get_directory();
|
||||
if (!itemDir.get_is_nodisplay())
|
||||
_loadCategory(itemDir, view);
|
||||
_loadCategory(itemDir, view);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -92,7 +92,7 @@ const BaseAppView = new Lang.Class({
|
||||
},
|
||||
|
||||
removeAll: function() {
|
||||
this._grid.removeAll();
|
||||
this._grid.destroyAll();
|
||||
this._items = {};
|
||||
this._allItems = [];
|
||||
},
|
||||
@ -613,6 +613,10 @@ 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();
|
||||
@ -691,8 +695,7 @@ const AppDisplay = new Lang.Class({
|
||||
Name: 'AppDisplay',
|
||||
|
||||
_init: function() {
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
|
||||
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
|
||||
Main.queueDeferredWork(this._allAppsWorkId);
|
||||
}));
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
@ -813,7 +816,8 @@ const AppDisplay = new Lang.Class({
|
||||
|
||||
view.removeAll();
|
||||
|
||||
let tree = this._appSystem.get_tree();
|
||||
let tree = new GMenu.Tree({ menu_basename: "applications.menu" });
|
||||
tree.load_sync();
|
||||
let root = tree.get_root_directory();
|
||||
|
||||
let iter = root.iter();
|
||||
@ -822,8 +826,6 @@ 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);
|
||||
@ -871,8 +873,8 @@ const AppSearchProvider = new Lang.Class({
|
||||
getResultMetas: function(apps, callback) {
|
||||
let metas = [];
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i];
|
||||
metas.push({ 'id': app,
|
||||
let app = this._appSys.lookup_app(apps[i]);
|
||||
metas.push({ 'id': app.get_id(),
|
||||
'name': app.get_name(),
|
||||
'createIcon': function(size) {
|
||||
return app.create_icon_texture(size);
|
||||
@ -886,15 +888,16 @@ const AppSearchProvider = new Lang.Class({
|
||||
return results.slice(0, maxNumber);
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
this.searchSystem.setResults(this, this._appSys.initial_search(terms));
|
||||
getInitialResultSet: function(terms, callback, cancellable) {
|
||||
callback(this._appSys.initial_search(terms));
|
||||
},
|
||||
|
||||
getSubsearchResultSet: function(previousResults, terms) {
|
||||
this.searchSystem.setResults(this, this._appSys.subsearch(previousResults, terms));
|
||||
getSubsearchResultSet: function(previousResults, terms, callback, cancellable) {
|
||||
callback(this._appSys.subsearch(previousResults, terms));
|
||||
},
|
||||
|
||||
activateResult: function(app) {
|
||||
activateResult: function(result) {
|
||||
let app = this._appSys.lookup_app(result);
|
||||
let event = Clutter.get_current_event();
|
||||
let modifiers = event ? event.get_state() : 0;
|
||||
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
||||
@ -913,8 +916,8 @@ const AppSearchProvider = new Lang.Class({
|
||||
app.open_new_window(workspace);
|
||||
},
|
||||
|
||||
createResultObject: function (resultMeta, terms) {
|
||||
let app = resultMeta['id'];
|
||||
createResultObject: function (resultMeta) {
|
||||
let app = this._appSys.lookup_app(resultMeta['id']);
|
||||
return new AppIcon(app);
|
||||
}
|
||||
});
|
||||
@ -1352,7 +1355,9 @@ 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();
|
||||
|
@ -315,7 +315,6 @@ 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;
|
||||
|
||||
@ -416,7 +415,6 @@ const Background = new Lang.Class({
|
||||
},
|
||||
|
||||
_addImage: function(content, index, filename) {
|
||||
content.saturation = this._saturation;
|
||||
content.brightness = this._brightness;
|
||||
content.vignette_sharpness = this._vignetteSharpness;
|
||||
|
||||
@ -432,7 +430,6 @@ const Background = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateImage: function(content, index, filename) {
|
||||
content.saturation = this._saturation;
|
||||
content.brightness = this._brightness;
|
||||
content.vignette_sharpness = this._vignetteSharpness;
|
||||
|
||||
@ -590,24 +587,6 @@ 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;
|
||||
},
|
||||
@ -751,7 +730,6 @@ 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',
|
||||
|
@ -190,16 +190,18 @@ const EmptyEventSource = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(EmptyEventSource.prototype);
|
||||
|
||||
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 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 CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
|
||||
|
||||
|
@ -75,12 +75,14 @@ function startAppForMount(app, mount) {
|
||||
|
||||
/******************************************/
|
||||
|
||||
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
|
||||
<method name="SniffURI">
|
||||
<arg type="s" direction="in" />
|
||||
<arg type="as" direction="out" />
|
||||
</method>
|
||||
</interface>;
|
||||
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 HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
|
||||
function HotplugSniffer() {
|
||||
|
@ -138,6 +138,8 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
key: Clutter.KEY_Escape,
|
||||
},
|
||||
this._okButton]);
|
||||
|
||||
this._updateOkButton();
|
||||
},
|
||||
|
||||
_updateOkButton: function() {
|
||||
@ -432,6 +434,7 @@ 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
|
||||
|
@ -446,6 +446,7 @@ 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;
|
||||
|
||||
@ -544,20 +545,19 @@ const ChatSource = new Lang.Class({
|
||||
this._notification.update(this._notification.title, null, { customContent: true });
|
||||
},
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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,6 +960,8 @@ const ChatNotification = new Lang.Class({
|
||||
},
|
||||
|
||||
appendTimestamp: function() {
|
||||
this._timestampTimeoutId = 0;
|
||||
|
||||
let lastMessageTime = this._history[0].time;
|
||||
let lastMessageDate = new Date(lastMessageTime * 1000);
|
||||
|
||||
@ -1095,22 +1097,16 @@ const RoomInviteNotification = new Lang.Class({
|
||||
* for example. */
|
||||
this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier()));
|
||||
|
||||
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.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.destroy();
|
||||
}));
|
||||
}
|
||||
@ -1136,23 +1132,17 @@ const AudioVideoNotification = new Lang.Class({
|
||||
|
||||
this.setUrgency(MessageTray.Urgency.CRITICAL);
|
||||
|
||||
this.addButton('reject', _("Decline"));
|
||||
this.addAction(_("Decline"), Lang.bind(this, function() {
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
|
||||
src.leave_channels_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
/* translators: this is a button label (verb), not a noun */
|
||||
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.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.destroy();
|
||||
}));
|
||||
}
|
||||
@ -1176,22 +1166,16 @@ const FileTransferNotification = new Lang.Class({
|
||||
{ customContent: true });
|
||||
this.setResident(true);
|
||||
|
||||
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.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.destroy();
|
||||
}));
|
||||
}
|
||||
@ -1239,27 +1223,20 @@ const SubscriptionRequestNotification = new Lang.Class({
|
||||
|
||||
this.addActor(layout);
|
||||
|
||||
this.addButton('decline', _("Decline"));
|
||||
this.addButton('accept', _("Accept"));
|
||||
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.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
|
||||
contact.request_subscription_async('', function(src, result) {
|
||||
src.request_subscription_finish(result);
|
||||
});
|
||||
}));
|
||||
|
||||
this._changedId = contact.connect('subscription-states-changed',
|
||||
@ -1358,18 +1335,11 @@ const AccountNotification = new Lang.Class({
|
||||
|
||||
this._account = account;
|
||||
|
||||
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.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._enabledId = account.connect('notify::enabled',
|
||||
|
@ -576,6 +576,7 @@ const Dash = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._labelShowing = true;
|
||||
item.showLabel();
|
||||
this._showLabelTimeoutId = 0;
|
||||
return false;
|
||||
}));
|
||||
if (this._resetHoverTimeoutId > 0) {
|
||||
@ -592,6 +593,7 @@ 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;
|
||||
}));
|
||||
}
|
||||
|
11
js/ui/dnd.js
11
js/ui/dnd.js
@ -236,7 +236,7 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor();
|
||||
this._dragActor.reparent(Main.uiGroup);
|
||||
Main.uiGroup.add_child(this._dragActor);
|
||||
this._dragActor.raise_top();
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
||||
|
||||
@ -285,7 +285,8 @@ const _Draggable = new Lang.Class({
|
||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||
|
||||
this._dragActor.reparent(Main.uiGroup);
|
||||
this._dragOrigParent.remove_actor(this._dragActor);
|
||||
Main.uiGroup.add_child(this._dragActor);
|
||||
this._dragActor.raise_top();
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
||||
}
|
||||
@ -345,6 +346,7 @@ 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 = {
|
||||
@ -389,7 +391,7 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
_queueUpdateDragHover: function() {
|
||||
if (this._updateHoverId)
|
||||
GLib.source_remove(this._updateHoverId);
|
||||
return;
|
||||
|
||||
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
|
||||
Lang.bind(this, this._updateDragHover));
|
||||
@ -555,7 +557,8 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
_onAnimationComplete : function (dragActor, eventTime) {
|
||||
if (this._dragOrigParent) {
|
||||
dragActor.reparent(this._dragOrigParent);
|
||||
Main.uiGroup.remove_child(this._dragActor);
|
||||
this._dragOrigParent.add_actor(this._dragActor);
|
||||
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
|
||||
dragActor.set_position(this._dragOrigX, this._dragOrigY);
|
||||
} else {
|
||||
|
@ -43,20 +43,22 @@ const _DIALOG_ICON_SIZE = 32;
|
||||
|
||||
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
|
||||
|
||||
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 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 logoutDialogContent = {
|
||||
subjectWithUser: C_("title", "Log Out %s"),
|
||||
@ -131,13 +133,15 @@ const DialogContent = {
|
||||
|
||||
const MAX_USERS_IN_SESSION_DIALOG = 5;
|
||||
|
||||
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 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 LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
|
||||
|
||||
@ -269,13 +273,15 @@ 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({ vertical: true });
|
||||
this._applicationList = new St.BoxLayout({ style_class: 'end-session-dialog-app-list',
|
||||
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({ vertical: true });
|
||||
this._sessionList = new St.BoxLayout({ style_class: 'end-session-dialog-session-list',
|
||||
vertical: true });
|
||||
this._inhibitorSection.add_actor(this._sessionHeader);
|
||||
this._inhibitorSection.add_actor(this._sessionList);
|
||||
|
||||
@ -409,6 +415,7 @@ 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;
|
||||
}));
|
||||
|
@ -76,7 +76,11 @@ function disableExtension(uuid) {
|
||||
theme.unload_stylesheet(extension.stylesheet.get_path());
|
||||
}
|
||||
|
||||
extension.stateObj.disable();
|
||||
try {
|
||||
extension.stateObj.disable();
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
}
|
||||
|
||||
for (let i = 0; i < order.length; i++) {
|
||||
let uuid = order[i];
|
||||
@ -89,8 +93,10 @@ function disableExtension(uuid) {
|
||||
|
||||
extensionOrder.splice(orderIdx, 1);
|
||||
|
||||
extension.state = ExtensionState.DISABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
if ( extension.state != ExtensionState.ERROR ) {
|
||||
extension.state = ExtensionState.DISABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
}
|
||||
}
|
||||
|
||||
function enableExtension(uuid) {
|
||||
@ -117,10 +123,15 @@ function enableExtension(uuid) {
|
||||
}
|
||||
}
|
||||
|
||||
extension.stateObj.enable();
|
||||
|
||||
extension.state = ExtensionState.ENABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
try {
|
||||
extension.stateObj.enable();
|
||||
extension.state = ExtensionState.ENABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
return;
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function logExtensionError(uuid, error) {
|
||||
@ -150,7 +161,8 @@ function loadExtension(extension) {
|
||||
} else {
|
||||
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
|
||||
if (enabled) {
|
||||
initExtension(extension.uuid);
|
||||
if (!initExtension(extension.uuid))
|
||||
return;
|
||||
if (extension.state == ExtensionState.DISABLED)
|
||||
enableExtension(extension.uuid);
|
||||
} else {
|
||||
@ -205,7 +217,12 @@ function initExtension(uuid) {
|
||||
extensionModule = extension.imports.extension;
|
||||
|
||||
if (extensionModule.init) {
|
||||
extensionState = extensionModule.init(extension);
|
||||
try {
|
||||
extensionState = extensionModule.init(extension);
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!extensionState)
|
||||
@ -214,6 +231,7 @@ function initExtension(uuid) {
|
||||
|
||||
extension.state = ExtensionState.DISABLED;
|
||||
_signals.emit('extension-loaded', uuid);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getEnabledExtensions() {
|
||||
@ -235,11 +253,7 @@ function onEnabledExtensionsChanged() {
|
||||
newEnabledExtensions.filter(function(uuid) {
|
||||
return enabledExtensions.indexOf(uuid) == -1;
|
||||
}).forEach(function(uuid) {
|
||||
try {
|
||||
enableExtension(uuid);
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
}
|
||||
enableExtension(uuid);
|
||||
});
|
||||
|
||||
// Find and disable all the newly disabled extensions: UUIDs found in the
|
||||
@ -247,11 +261,7 @@ function onEnabledExtensionsChanged() {
|
||||
enabledExtensions.filter(function(item) {
|
||||
return newEnabledExtensions.indexOf(item) == -1;
|
||||
}).forEach(function(uuid) {
|
||||
try {
|
||||
disableExtension(uuid);
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
}
|
||||
disableExtension(uuid);
|
||||
});
|
||||
|
||||
enabledExtensions = newEnabledExtensions;
|
||||
@ -262,12 +272,8 @@ function _loadExtensions() {
|
||||
enabledExtensions = getEnabledExtensions();
|
||||
|
||||
let finder = new ExtensionUtils.ExtensionFinder();
|
||||
finder.connect('extension-found', function(signals, extension) {
|
||||
try {
|
||||
loadExtension(extension);
|
||||
} catch(e) {
|
||||
logExtensionError(extension.uuid, e);
|
||||
}
|
||||
finder.connect('extension-found', function(finder, extension) {
|
||||
loadExtension(extension);
|
||||
});
|
||||
finder.scanExtensions();
|
||||
}
|
||||
|
@ -413,15 +413,18 @@ 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 || !item.icon instanceof BaseIcon) {
|
||||
log('Only items with a BaseIcon icon property can be added to IconGrid');
|
||||
return;
|
||||
}
|
||||
if (!item.icon instanceof BaseIcon)
|
||||
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
|
||||
|
||||
this._items.push(item);
|
||||
if (index !== undefined)
|
||||
|
@ -23,27 +23,29 @@ const KEYBOARD_TYPE = 'keyboard-type';
|
||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
|
||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
|
||||
|
||||
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 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 Key = new Lang.Class({
|
||||
Name: 'Key',
|
||||
|
@ -629,55 +629,6 @@ 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',
|
||||
|
||||
@ -880,6 +831,19 @@ 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 });
|
||||
@ -907,9 +871,6 @@ 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);
|
||||
|
||||
|
@ -9,85 +9,89 @@ 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 = <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>;
|
||||
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>';
|
||||
|
||||
// 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 = <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>;
|
||||
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>';
|
||||
|
||||
// For making unique ZoomRegion DBus proxy object paths of the form:
|
||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',
|
||||
|
@ -112,11 +112,6 @@ 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();
|
||||
|
@ -280,10 +280,6 @@ 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.
|
||||
@ -503,7 +499,6 @@ 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;
|
||||
@ -836,17 +831,7 @@ const Notification = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
// 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) {
|
||||
addButton: function(button, callback) {
|
||||
if (!this._buttonBox) {
|
||||
let box = new St.BoxLayout({ style_class: 'notification-actions' });
|
||||
this.setActionArea(box, { x_expand: false,
|
||||
@ -858,43 +843,37 @@ const Notification = new Lang.Class({
|
||||
global.focus_manager.add_group(this._buttonBox);
|
||||
}
|
||||
|
||||
let button = new St.Button({ can_focus: true });
|
||||
button._actionId = id;
|
||||
|
||||
let iconName = strHasSuffix(id, '-symbolic') ? id : id + '-symbolic';
|
||||
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
|
||||
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));
|
||||
button.connect('clicked', Lang.bind(this, function() {
|
||||
callback();
|
||||
|
||||
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();
|
||||
}
|
||||
}));
|
||||
|
||||
this.updated();
|
||||
return button;
|
||||
},
|
||||
|
||||
// setButtonSensitive:
|
||||
// @id: the action ID
|
||||
// @sensitive: whether the button should be sensitive
|
||||
// addAction:
|
||||
// @label: the label for the action's button
|
||||
// @callback: the callback for the action
|
||||
//
|
||||
// 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;
|
||||
// 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 });
|
||||
|
||||
let button = this._buttonBox.get_children().filter(function(b) {
|
||||
return b._actionId == id;
|
||||
})[0];
|
||||
|
||||
if (!button || button.reactive == sensitive)
|
||||
return;
|
||||
|
||||
button.reactive = sensitive;
|
||||
return this.addButton(button, callback);
|
||||
},
|
||||
|
||||
setUrgency: function(urgency) {
|
||||
@ -913,10 +892,6 @@ 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');
|
||||
},
|
||||
@ -1141,18 +1116,6 @@ 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
|
||||
@ -1418,9 +1381,7 @@ 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);
|
||||
|
||||
@ -2212,7 +2173,10 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
toggleAndNavigate: function() {
|
||||
if (this.toggle())
|
||||
if (!this.toggle())
|
||||
return;
|
||||
|
||||
if (this._traySummoned)
|
||||
this._summary.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
},
|
||||
|
||||
@ -2409,7 +2373,6 @@ 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) &&
|
||||
@ -2420,9 +2383,9 @@ const MessageTray = new Lang.Class({
|
||||
if (mustClose) {
|
||||
let animate = hasNotifications && !this._notificationRemoved;
|
||||
this._hideNotification(animate);
|
||||
} else if (pinned && !this._notification.expanded) {
|
||||
} else if (this._pointerInNotification && !this._notification.expanded) {
|
||||
this._expandNotification(false);
|
||||
} else if (pinned) {
|
||||
} else if (this._pointerInNotification) {
|
||||
this._ensureNotificationFocused();
|
||||
}
|
||||
}
|
||||
@ -2792,12 +2755,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.
|
||||
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
|
||||
{ y: expandedY,
|
||||
opacity: 255,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
Tweener.addTween(this._notificationWidget,
|
||||
{ y: expandedY,
|
||||
opacity: 255,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -4,6 +4,7 @@ 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;
|
||||
@ -15,54 +16,56 @@ 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 = <interface name="org.freedesktop.DBus">
|
||||
<method name="GetConnectionUnixProcessID">
|
||||
<arg type="s" direction="in" />
|
||||
<arg type="u" direction="out" />
|
||||
</method>
|
||||
</interface>;
|
||||
const BusIface = '<node> \
|
||||
<interface name="org.freedesktop.DBus"> \
|
||||
<method name="GetConnectionUnixProcessID"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
|
||||
function Bus() {
|
||||
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
|
||||
}
|
||||
|
||||
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 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 NotificationClosedReason = {
|
||||
EXPIRED: 1,
|
||||
@ -103,11 +106,11 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'ibus-ui-gtk': 'keyboard'
|
||||
};
|
||||
|
||||
const NotificationDaemon = new Lang.Class({
|
||||
Name: 'NotificationDaemon',
|
||||
const FdoNotificationDaemon = new Lang.Class({
|
||||
Name: 'FdoNotificationDaemon',
|
||||
|
||||
_init: function() {
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(FdoNotificationsIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||
|
||||
this._sources = [];
|
||||
@ -115,6 +118,8 @@ const NotificationDaemon = 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));
|
||||
@ -213,7 +218,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
let source = new Source(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
let source = new FdoNotificationDaemonSource(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
source.setTransient(isForTransientNotification);
|
||||
|
||||
if (!isForTransientNotification) {
|
||||
@ -252,7 +257,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
hints['category'] == 'presence.offline')) {
|
||||
// Ignore replacesId since we already sent back a
|
||||
// NotificationClosed for that id.
|
||||
id = nextNotificationId++;
|
||||
id = this._nextNotificationId++;
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function () {
|
||||
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
|
||||
@ -296,7 +301,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
ndata.notification = this._notifications[replacesId].notification;
|
||||
} else {
|
||||
replacesId = 0;
|
||||
ndata.id = id = nextNotificationId++;
|
||||
ndata.id = id = this._nextNotificationId++;
|
||||
}
|
||||
this._notifications[id] = ndata;
|
||||
|
||||
@ -351,6 +356,19 @@ const NotificationDaemon = 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,
|
||||
@ -376,10 +394,6 @@ const NotificationDaemon = 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
|
||||
@ -413,18 +427,33 @@ const NotificationDaemon = new Lang.Class({
|
||||
soundName: hints['sound-name'] });
|
||||
notification.setImage(image);
|
||||
|
||||
let hasDefaultAction = false;
|
||||
|
||||
if (actions.length) {
|
||||
notification.setUseActionIcons(hints['action-icons'] == true);
|
||||
let useActionIcons = (hints['action-icons'] == true);
|
||||
|
||||
for (let i = 0; i < actions.length - 1; i += 2) {
|
||||
if (actions[i] == 'default')
|
||||
notification.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._emitActionInvoked(ndata.id, "default");
|
||||
}));
|
||||
else
|
||||
notification.addButton(actions[i], actions[i + 1]);
|
||||
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 (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);
|
||||
@ -517,8 +546,8 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const Source = new Lang.Class({
|
||||
Name: 'NotificationDaemonSource',
|
||||
const FdoNotificationDaemonSource = new Lang.Class({
|
||||
Name: 'FdoNotificationDaemonSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(title, pid, sender, trayIcon, appId) {
|
||||
@ -553,7 +582,7 @@ const Source = new Lang.Class({
|
||||
},
|
||||
|
||||
_createPolicy: function() {
|
||||
if (this.app) {
|
||||
if (this.app && this.app.get_app_info()) {
|
||||
let id = this.app.get_id().replace(/\.desktop$/,'');
|
||||
return new MessageTray.NotificationApplicationPolicy(id);
|
||||
} else {
|
||||
@ -643,7 +672,7 @@ const Source = new Lang.Class({
|
||||
this.parent(title);
|
||||
},
|
||||
|
||||
open: function(notification) {
|
||||
open: function() {
|
||||
this.openApp();
|
||||
this.destroyNonResidentNotifications();
|
||||
},
|
||||
@ -685,3 +714,276 @@ const Source = 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();
|
||||
},
|
||||
});
|
||||
|
@ -78,10 +78,8 @@ const ShellInfo = new Lang.Class({
|
||||
}
|
||||
|
||||
this._undoCallback = undoCallback;
|
||||
if (undoCallback) {
|
||||
notification.addButton('system-undo', _("Undo"));
|
||||
notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked));
|
||||
}
|
||||
if (undoCallback)
|
||||
notification.addAction(_("Undo"), Lang.bind(this, this._onUndoClicked));
|
||||
|
||||
this._source.notify(notification);
|
||||
}
|
||||
@ -365,11 +363,13 @@ 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(source) {
|
||||
this.emit('window-drag-begin');
|
||||
beginWindowDrag: function(clone) {
|
||||
this.emit('window-drag-begin', clone);
|
||||
this._inDrag = true;
|
||||
},
|
||||
|
||||
cancelledWindowDrag: function(source) {
|
||||
this.emit('window-drag-cancelled');
|
||||
cancelledWindowDrag: function(clone) {
|
||||
this.emit('window-drag-cancelled', clone);
|
||||
},
|
||||
|
||||
endWindowDrag: function(source) {
|
||||
this.emit('window-drag-end');
|
||||
endWindowDrag: function(clone) {
|
||||
this.emit('window-drag-end', clone);
|
||||
this._inDrag = false;
|
||||
},
|
||||
|
||||
|
@ -36,6 +36,7 @@ const SlideLayout = new Lang.Class({
|
||||
|
||||
_init: function(params) {
|
||||
this._slideX = 1;
|
||||
this._translationX = 0;
|
||||
this._direction = SlideDirection.LEFT;
|
||||
|
||||
this.parent(params);
|
||||
@ -66,9 +67,9 @@ const SlideLayout = new Lang.Class({
|
||||
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0;
|
||||
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
actorBox.x1 = alignX;
|
||||
actorBox.x2 = actorBox.x1 + child.x_expand ? availWidth : natWidth;
|
||||
actorBox.y1 = 0;
|
||||
actorBox.x1 = box.x1 + alignX + this._translationX;
|
||||
actorBox.x2 = actorBox.x1 + (child.x_expand ? availWidth : natWidth);
|
||||
actorBox.y1 = box.y1;
|
||||
actorBox.y2 = actorBox.y1 + availHeight;
|
||||
|
||||
child.allocate(actorBox, flags);
|
||||
@ -90,7 +91,16 @@ 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({
|
||||
@ -99,8 +109,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;
|
||||
@ -109,6 +119,7 @@ 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));
|
||||
@ -119,12 +130,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' });
|
||||
},
|
||||
@ -151,28 +162,30 @@ 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.actor.translation_x == translationEnd)
|
||||
if (this.layout.translationX == translationEnd)
|
||||
return;
|
||||
|
||||
this.actor.translation_x = translationStart;
|
||||
Tweener.addTween(this.actor, { translation_x: translationEnd,
|
||||
time: SIDE_CONTROLS_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
this.layout.translationX = translationStart;
|
||||
Tweener.addTween(this.layout, { translationX: translationEnd,
|
||||
time: SIDE_CONTROLS_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
},
|
||||
|
||||
_onOverviewShowing: function() {
|
||||
// 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;
|
||||
this._visible = true;
|
||||
this.layout.slideX = this._getSlide();
|
||||
this.layout.translationX = this._getTranslation();
|
||||
this.slideIn();
|
||||
},
|
||||
|
||||
_onOverviewHiding: function() {
|
||||
this.slideOut();
|
||||
},
|
||||
|
||||
_onWindowDragBegin: function() {
|
||||
@ -184,14 +197,14 @@ const SlidingControl = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDragBegin: function() {
|
||||
this.inDrag = true;
|
||||
this.actor.translation_x = 0;
|
||||
this.updateSlide();
|
||||
this._inDrag = true;
|
||||
this.layout.translationX = 0;
|
||||
this._updateSlide();
|
||||
},
|
||||
|
||||
_onDragEnd: function() {
|
||||
this.inDrag = false;
|
||||
this.updateSlide();
|
||||
this._inDrag = false;
|
||||
this._updateSlide();
|
||||
},
|
||||
|
||||
fadeIn: function() {
|
||||
@ -209,13 +222,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
|
||||
},
|
||||
@ -225,7 +238,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();
|
||||
}
|
||||
});
|
||||
@ -244,16 +257,15 @@ 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));
|
||||
Main.overview.connect('hiding', Lang.bind(this, this.slideOut));
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this.updateSlide));
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateSlide));
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this._updateSlide));
|
||||
this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
||||
},
|
||||
|
||||
_getAlwaysZoomOut: function() {
|
||||
// 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;
|
||||
@ -273,20 +285,13 @@ 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();
|
||||
@ -323,29 +328,22 @@ 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));
|
||||
Main.overview.connect('hiding', Lang.bind(this, this.slideOut));
|
||||
this._dash.connect('icon-size-changed', Lang.bind(this, this._updateSlide));
|
||||
},
|
||||
|
||||
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();
|
||||
},
|
||||
|
@ -1114,7 +1114,7 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
removeMenu: function(menu) {
|
||||
if (menu == this.activeMenu)
|
||||
this._closeMenu(menu);
|
||||
this._closeMenu(false, menu);
|
||||
|
||||
let position = this._findMenu(menu);
|
||||
if (position == -1) // not a menu we manage
|
||||
|
@ -7,58 +7,63 @@ 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 = <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 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 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>;
|
||||
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>';
|
||||
|
||||
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
|
||||
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
|
||||
var SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
|
||||
var SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
|
||||
|
||||
function loadRemoteSearchProviders(addProviderCallback) {
|
||||
function loadRemoteSearchProviders(callback) {
|
||||
let objectPaths = {};
|
||||
let loadedProviders = [];
|
||||
|
||||
@ -112,30 +117,25 @@ function loadRemoteSearchProviders(addProviderCallback) {
|
||||
}
|
||||
}
|
||||
|
||||
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(addProviderCallback) {
|
||||
return (idxA - idxB);
|
||||
});
|
||||
|
||||
loadedProviders.forEach(addProviderCallback);
|
||||
callback(loadedProviders);
|
||||
}
|
||||
|
||||
const RemoteSearchProvider = new Lang.Class({
|
||||
Name: 'RemoteSearchProvider',
|
||||
|
||||
_init: function(appInfo, dbusName, dbusPath, proxyType) {
|
||||
if (!proxyType)
|
||||
proxyType = SearchProviderProxy;
|
||||
_init: function(appInfo, dbusName, dbusPath, proxyInfo) {
|
||||
if (!proxyInfo)
|
||||
proxyInfo = SearchProviderProxyInfo;
|
||||
|
||||
this.proxy = new proxyType(Gio.DBus.session,
|
||||
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
|
||||
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.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,40 +217,33 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
|
||||
},
|
||||
|
||||
_getResultsFinished: function(results, error) {
|
||||
if (error)
|
||||
_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([]);
|
||||
return;
|
||||
this.searchSystem.setResults(this, results[0]);
|
||||
}
|
||||
|
||||
callback(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, []);
|
||||
}
|
||||
getInitialResultSet: function(terms, callback, cancellable) {
|
||||
this.proxy.GetInitialResultSetRemote(terms,
|
||||
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, []);
|
||||
}
|
||||
getSubsearchResultSet: function(previousResults, newTerms, callback, cancellable) {
|
||||
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
Lang.bind(this, this._getResultsFinished, callback),
|
||||
cancellable);
|
||||
},
|
||||
|
||||
_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;
|
||||
}
|
||||
@ -272,17 +265,10 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
callback(resultMetas);
|
||||
},
|
||||
|
||||
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([]);
|
||||
}
|
||||
getResultMetas: function(ids, callback, cancellable) {
|
||||
this.proxy.GetResultMetasRemote(ids,
|
||||
Lang.bind(this, this._getResultMetasFinished, callback),
|
||||
cancellable);
|
||||
},
|
||||
|
||||
activateResult: function(id) {
|
||||
@ -302,7 +288,7 @@ const RemoteSearchProvider2 = new Lang.Class({
|
||||
Extends: RemoteSearchProvider,
|
||||
|
||||
_init: function(appInfo, dbusName, dbusPath) {
|
||||
this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy);
|
||||
this.parent(appInfo, dbusName, dbusPath, SearchProvider2ProxyInfo);
|
||||
|
||||
this.canLaunchSearch = true;
|
||||
},
|
||||
|
@ -198,8 +198,8 @@ const NotificationsBox = new Lang.Class({
|
||||
|
||||
let body = '';
|
||||
if (n.bannerBodyText) {
|
||||
body = n.bannerBodyMarkup ? n.bannerBodyText :
|
||||
GLib.markup_escape_text(n.bannerBodyMarkup, -1);
|
||||
body = n.bannerBodyMarkup ? n.bannerBodyText
|
||||
: GLib.markup_escape_text(n.bannerBodyText, -1);
|
||||
}
|
||||
|
||||
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
|
||||
|
@ -9,27 +9,29 @@ const Signals = imports.signals;
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ScreencastIface = <interface name="org.gnome.Shell.Screencast">
|
||||
<method name="Screencast">
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="ScreencastArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="StopScreencast">
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const 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 ScreencastService = new Lang.Class({
|
||||
Name: 'ScreencastService',
|
||||
@ -103,8 +105,10 @@ const ScreencastService = new Lang.Class({
|
||||
|
||||
ScreencastAsync: function(params, invocation) {
|
||||
let returnValue = [false, ''];
|
||||
if (!Main.sessionMode.allowScreencast)
|
||||
if (!Main.sessionMode.allowScreencast) {
|
||||
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||
return;
|
||||
}
|
||||
|
||||
let sender = invocation.get_sender();
|
||||
let recorder = this._ensureRecorderForSender(sender);
|
||||
@ -122,8 +126,10 @@ const ScreencastService = new Lang.Class({
|
||||
|
||||
ScreencastAreaAsync: function(params, invocation) {
|
||||
let returnValue = [false, ''];
|
||||
if (!Main.sessionMode.allowScreencast)
|
||||
if (!Main.sessionMode.allowScreencast) {
|
||||
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||
return;
|
||||
}
|
||||
|
||||
let sender = invocation.get_sender();
|
||||
let recorder = this._ensureRecorderForSender(sender);
|
||||
@ -131,6 +137,16 @@ const ScreencastService = new Lang.Class({
|
||||
if (!recorder.is_recording()) {
|
||||
let [x, y, width, height, fileTemplate, options] = params;
|
||||
|
||||
if (x < 0 || y < 0 ||
|
||||
width <= 0 || height <= 0 ||
|
||||
x + width > global.screen_width ||
|
||||
y + height > global.screen_height) {
|
||||
invocation.return_error_literal(Gio.IOErrorEnum,
|
||||
Gio.IOErrorEnum.CANCELLED,
|
||||
"Invalid params");
|
||||
return;
|
||||
}
|
||||
|
||||
recorder.set_file_template(fileTemplate);
|
||||
recorder.set_area(x, y, width, height);
|
||||
this._applyOptionalParameters(recorder, options);
|
||||
|
@ -15,45 +15,47 @@ const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const ScreenshotIface = <interface name="org.gnome.Shell.Screenshot">
|
||||
<method name="ScreenshotArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="s" direction="in" name="filename"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="ScreenshotWindow">
|
||||
<arg type="b" direction="in" name="include_frame"/>
|
||||
<arg type="b" direction="in" name="include_cursor"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="s" direction="in" name="filename"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="Screenshot">
|
||||
<arg type="b" direction="in" name="include_cursor"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="s" direction="in" name="filename"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="SelectArea">
|
||||
<arg type="i" direction="out" name="x"/>
|
||||
<arg type="i" direction="out" name="y"/>
|
||||
<arg type="i" direction="out" name="width"/>
|
||||
<arg type="i" direction="out" name="height"/>
|
||||
</method>
|
||||
<method name="FlashArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const 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 ScreenshotService = new Lang.Class({
|
||||
Name: 'ScreenshotService',
|
||||
@ -77,7 +79,9 @@ const ScreenshotService = new Lang.Class({
|
||||
|
||||
ScreenshotAreaAsync : function (params, invocation) {
|
||||
let [x, y, width, height, flash, filename, callback] = params;
|
||||
if (height <= 0 || width <= 0) {
|
||||
if (x < 0 || y < 0 ||
|
||||
width <= 0 || height <= 0 ||
|
||||
x + width > global.screen_width || y + height > global.screen_height) {
|
||||
invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
|
||||
"Invalid params");
|
||||
return;
|
||||
|
@ -69,16 +69,18 @@ function waitLeisure() {
|
||||
};
|
||||
}
|
||||
|
||||
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>;
|
||||
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>';
|
||||
|
||||
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
|
||||
function PerfHelper() {
|
||||
|
719
js/ui/search.js
719
js/ui/search.js
@ -1,105 +1,706 @@
|
||||
// -*- 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._remoteProviders = [];
|
||||
this.reset();
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
registerProvider: function (provider) {
|
||||
provider.searchSystem = this;
|
||||
addProvider: function(provider) {
|
||||
this._providers.push(provider);
|
||||
|
||||
if (provider.isRemoteProvider)
|
||||
this._remoteProviders.push(provider);
|
||||
this.emit('providers-changed');
|
||||
},
|
||||
|
||||
unregisterProvider: function (provider) {
|
||||
let index = this._providers.indexOf(provider);
|
||||
if (index == -1)
|
||||
return;
|
||||
provider.searchSystem = null;
|
||||
this._providers.splice(index, 1);
|
||||
_reloadRemoteProviders: function() {
|
||||
let remoteProviders = this._providers.filter(function(provider) {
|
||||
return provider.isRemoteProvider;
|
||||
});
|
||||
remoteProviders.forEach(Lang.bind(this, function(provider) {
|
||||
this._unregisterProvider(provider);
|
||||
}));
|
||||
|
||||
let remoteIndex = this._remoteProviders.indexOf(provider);
|
||||
if (remoteIndex != -1)
|
||||
this._remoteProviders.splice(remoteIndex, 1);
|
||||
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) {
|
||||
let index = this._providers.indexOf(provider);
|
||||
this._providers.splice(index, 1);
|
||||
},
|
||||
|
||||
getProviders: function() {
|
||||
return this._providers;
|
||||
},
|
||||
|
||||
getRemoteProviders: function() {
|
||||
return this._remoteProviders;
|
||||
},
|
||||
|
||||
getTerms: function() {
|
||||
return this._previousTerms;
|
||||
return this._terms;
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this._previousTerms = [];
|
||||
this._previousResults = [];
|
||||
this._terms = [];
|
||||
this._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]);
|
||||
_gotResults: function(results, provider) {
|
||||
this._results[provider.id] = results;
|
||||
this.emit('search-updated', provider, results);
|
||||
},
|
||||
|
||||
updateSearchResults: function(terms) {
|
||||
setTerms: function(terms) {
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
|
||||
let previousResults = this._results;
|
||||
let previousTerms = this._terms;
|
||||
this.reset();
|
||||
|
||||
if (!terms)
|
||||
return;
|
||||
|
||||
let searchString = terms.join(' ');
|
||||
let previousSearchString = this._previousTerms.join(' ');
|
||||
let previousSearchString = previousTerms.join(' ');
|
||||
if (searchString == previousSearchString)
|
||||
return;
|
||||
|
||||
let isSubSearch = false;
|
||||
if (this._previousTerms.length > 0)
|
||||
if (previousTerms.length > 0)
|
||||
isSubSearch = searchString.indexOf(previousSearchString) == 0;
|
||||
|
||||
let previousResultsArr = this._previousResults;
|
||||
this._terms = terms;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}));
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
@ -1,567 +0,0 @@
|
||||
// -*- 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);
|
||||
}
|
||||
});
|
@ -102,19 +102,12 @@ const _modes = {
|
||||
}
|
||||
};
|
||||
|
||||
function _getModes(modesLoadedCallback) {
|
||||
FileUtils.collectFromDatadirsAsync('modes',
|
||||
{ processFile: _loadMode,
|
||||
loadedCallback: modesLoadedCallback,
|
||||
data: _modes });
|
||||
}
|
||||
|
||||
function _loadMode(file, info, loadedData) {
|
||||
function _loadMode(file, info) {
|
||||
let name = info.get_name();
|
||||
let suffix = name.indexOf('.json');
|
||||
let modeName = suffix == -1 ? name : name.slice(name, suffix);
|
||||
|
||||
if (loadedData.hasOwnProperty(modeName))
|
||||
if (_modes.hasOwnProperty(modeName))
|
||||
return;
|
||||
|
||||
let fileContent, success, tag, newMode;
|
||||
@ -125,18 +118,23 @@ function _loadMode(file, info, loadedData) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadedData[modeName] = {};
|
||||
_modes[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];
|
||||
}
|
||||
loadedData[modeName]['isPrimary'] = true;
|
||||
_modes[modeName]['isPrimary'] = true;
|
||||
}
|
||||
|
||||
function _getModes() {
|
||||
FileUtils.collectFromDatadirs('modes', false, _loadMode);
|
||||
}
|
||||
|
||||
function listModes() {
|
||||
_getModes(function(modes) {
|
||||
let modes = _getModes();
|
||||
modes.forEach(function() {
|
||||
let names = Object.getOwnPropertyNames(modes);
|
||||
for (let i = 0; i < names.length; i++)
|
||||
if (_modes[names[i]].isPrimary)
|
||||
@ -149,17 +147,12 @@ function listModes() {
|
||||
const SessionMode = new Lang.Class({
|
||||
Name: 'SessionMode',
|
||||
|
||||
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');
|
||||
}));
|
||||
_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();
|
||||
},
|
||||
|
||||
pushMode: function(mode) {
|
||||
@ -186,13 +179,13 @@ const SessionMode = new Lang.Class({
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let params = this._modes[this.currentMode];
|
||||
let params = _modes[this.currentMode];
|
||||
let defaults;
|
||||
if (params.parentMode)
|
||||
defaults = Params.parse(this._modes[params.parentMode],
|
||||
this._modes[DEFAULT_MODE]);
|
||||
defaults = Params.parse(_modes[params.parentMode],
|
||||
_modes[DEFAULT_MODE]);
|
||||
else
|
||||
defaults = this._modes[DEFAULT_MODE];
|
||||
defaults = _modes[DEFAULT_MODE];
|
||||
params = Params.parse(params, defaults);
|
||||
|
||||
// A simplified version of Lang.copyProperties, handles
|
||||
|
@ -15,59 +15,63 @@ const Main = imports.ui.main;
|
||||
const Screenshot = imports.ui.screenshot;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
|
||||
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 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 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 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 GnomeShell = new Lang.Class({
|
||||
Name: 'GnomeShellDBus',
|
||||
@ -115,7 +119,7 @@ const GnomeShell = new Lang.Class({
|
||||
returnValue = '';
|
||||
success = true;
|
||||
} catch (e) {
|
||||
returnValue = JSON.stringify(e);
|
||||
returnValue = '' + e;
|
||||
success = false;
|
||||
}
|
||||
return [success, returnValue];
|
||||
@ -246,41 +250,43 @@ const GnomeShell = new Lang.Class({
|
||||
ShellVersion: Config.PACKAGE_VERSION
|
||||
});
|
||||
|
||||
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 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 GnomeShellExtensions = new Lang.Class({
|
||||
Name: 'GnomeShellExtensionsDBus',
|
||||
|
@ -521,36 +521,38 @@ const ShellProcessesDialog = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(ShellProcessesDialog.prototype);
|
||||
|
||||
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 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 ShellMountOperationType = {
|
||||
NONE: 0,
|
||||
|
@ -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.addButton('allow', _("Allow"));
|
||||
this.addButton('deny', _("Deny"));
|
||||
this.addAction('allow', _("Allow"));
|
||||
this.addAction('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.addButton('always-grant', _("Always grant access"));
|
||||
this.addButton('grant', _("Grant this time only"));
|
||||
this.addButton('reject', _("Reject"));
|
||||
this.addAction('always-grant', _("Always grant access"));
|
||||
this.addAction('grant', _("Grant this time only"));
|
||||
this.addAction('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.addButton('matches', _("Matches"));
|
||||
this.addButton('does-not-match', _("Does not match"));
|
||||
this.addAction('matches', _("Matches"));
|
||||
this.addAction('does-not-match', _("Does not match"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'matches')
|
||||
@ -207,47 +207,48 @@ const PinNotification = new Lang.Class({
|
||||
let key = event.get_key_symbol();
|
||||
if (key == Clutter.KEY_Return) {
|
||||
if (this._canActivateOkButton())
|
||||
this.emit('action-invoked', 'ok');
|
||||
this._ok();
|
||||
return true;
|
||||
} else if (key == Clutter.KEY_Escape) {
|
||||
this.emit('action-invoked', 'cancel');
|
||||
this._cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
this.addActor(this._entry);
|
||||
|
||||
this.addButton('ok', _("OK"));
|
||||
this.addButton('cancel', _("Cancel"));
|
||||
let okButton = this.addAction(_("OK"), Lang.bind(this, this._ok));
|
||||
this.addAction(_("Cancel"), Lang.bind(this, this._cancel));
|
||||
|
||||
this.setButtonSensitive('ok', this._canActivateOkButton());
|
||||
this._entry.clutter_text.connect('text-changed', Lang.bind(this,
|
||||
function() {
|
||||
this.setButtonSensitive('ok', this._canActivateOkButton());
|
||||
}));
|
||||
|
||||
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.destroy();
|
||||
okButton.reactive = this._canActivateOkButton();
|
||||
this._entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
|
||||
okButton.reactive = 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._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();
|
||||
},
|
||||
|
||||
_canActivateOkButton: function() {
|
||||
// PINs have a fixed length of 6
|
||||
if (this._numeric)
|
||||
|
@ -11,9 +11,11 @@ const Slider = imports.ui.slider;
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
|
||||
|
||||
const BrightnessInterface = <interface name="org.gnome.SettingsDaemon.Power.Screen">
|
||||
<property name='Brightness' type='i' access='readwrite'/>
|
||||
</interface>;
|
||||
const BrightnessInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Power.Screen"> \
|
||||
<property name="Brightness" type="i" access="readwrite"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
|
||||
|
||||
|
@ -41,11 +41,13 @@ const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard';
|
||||
|
||||
const KeyboardManagerInterface = <interface name="org.gnome.SettingsDaemon.Keyboard">
|
||||
<method name="SetInputSource">
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
const KeyboardManagerInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Keyboard"> \
|
||||
<method name="SetInputSource"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface);
|
||||
|
||||
|
@ -549,33 +549,30 @@ const NMWirelessDialogItem = new Lang.Class({
|
||||
this._network = network;
|
||||
this._ap = network.accessPoints[0];
|
||||
|
||||
this.actor = new St.Button({ style_class: 'nm-dialog-item',
|
||||
can_focus: true,
|
||||
x_fill: true });
|
||||
this.actor = new St.BoxLayout({ style_class: 'nm-dialog-item',
|
||||
can_focus: true,
|
||||
reactive: true });
|
||||
this.actor.connect('key-focus-in', Lang.bind(this, function() {
|
||||
this.emit('selected');
|
||||
}));
|
||||
this.actor.connect('clicked', Lang.bind(this, function() {
|
||||
let action = new Clutter.ClickAction();
|
||||
action.connect('clicked', Lang.bind(this, function() {
|
||||
this.actor.grab_key_focus();
|
||||
}));
|
||||
|
||||
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);
|
||||
this.actor.add_action(action);
|
||||
|
||||
let title = ssidToLabel(this._ap.get_ssid());
|
||||
this._label = new St.Label({ text: title });
|
||||
|
||||
this.actor.label_actor = this._label;
|
||||
this._content.add(this._label, { x_align: St.Align.START });
|
||||
this.actor.add(this._label, { x_align: St.Align.START });
|
||||
|
||||
this._selectedIcon = new St.Icon({ style_class: 'nm-dialog-icon',
|
||||
icon_name: 'object-select-symbolic' });
|
||||
this._content.add(this._selectedIcon);
|
||||
this.actor.add(this._selectedIcon);
|
||||
|
||||
this._icons = new St.BoxLayout({ style_class: 'nm-dialog-icons' });
|
||||
this._content.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END });
|
||||
this.actor.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)
|
||||
@ -606,16 +603,6 @@ 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);
|
||||
@ -968,13 +955,13 @@ const NMWirelessDialog = new Lang.Class({
|
||||
|
||||
_selectNetwork: function(network) {
|
||||
if (this._selectedNetwork)
|
||||
this._selectedNetwork.item.actor.checked = false;
|
||||
this._selectedNetwork.item.actor.remove_style_pseudo_class('selected');
|
||||
|
||||
this._selectedNetwork = network;
|
||||
this._updateSensitivity();
|
||||
|
||||
if (this._selectedNetwork)
|
||||
this._selectedNetwork.item.actor.checked = true;
|
||||
this._selectedNetwork.item.actor.add_style_pseudo_class('selected');
|
||||
},
|
||||
|
||||
_createNetworkItem: function(network) {
|
||||
@ -984,9 +971,6 @@ 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();
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -8,20 +8,22 @@ const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
|
||||
const BUS_NAME = 'org.freedesktop.UPower';
|
||||
const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
|
||||
|
||||
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 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 PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
|
||||
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface);
|
||||
|
||||
const Indicator = new Lang.Class({
|
||||
Name: 'PowerIndicator',
|
||||
@ -32,7 +34,7 @@ const Indicator = new Lang.Class({
|
||||
|
||||
this._indicator = this._addIndicator();
|
||||
|
||||
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
|
||||
this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
|
||||
Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
@ -43,7 +45,7 @@ const Indicator = new Lang.Class({
|
||||
this._sync();
|
||||
}));
|
||||
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Battery"), true);
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
|
||||
this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
|
||||
this.menu.addMenuItem(this._item);
|
||||
|
||||
@ -56,11 +58,18 @@ const Indicator = new Lang.Class({
|
||||
this.menu.setSensitive(sensitive);
|
||||
},
|
||||
|
||||
_statusForDevice: function(device) {
|
||||
let [device_id, device_type, icon, percentage, state, seconds] = device;
|
||||
_getStatus: function() {
|
||||
let seconds = 0;
|
||||
|
||||
if (state == UPower.DeviceState.FULLY_CHARGED)
|
||||
if (this._proxy.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) {
|
||||
@ -72,44 +81,43 @@ const Indicator = new Lang.Class({
|
||||
let minutes = time % 60;
|
||||
let hours = Math.floor(time / 60);
|
||||
|
||||
if (state == UPower.DeviceState.DISCHARGING) {
|
||||
if (this._proxy.State == UPower.DeviceState.DISCHARGING) {
|
||||
// Translators: this is <hours>:<minutes> Remaining (<percentage>)
|
||||
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, percentage);
|
||||
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, this._proxy.Percentage);
|
||||
}
|
||||
|
||||
if (state == UPower.DeviceState.CHARGING) {
|
||||
if (this._proxy.State == UPower.DeviceState.CHARGING) {
|
||||
// Translators: this is <hours>:<minutes> Until Full (<percentage>)
|
||||
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, percentage);
|
||||
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, this._proxy.Percentage);
|
||||
}
|
||||
|
||||
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
|
||||
return _("Estimating…");
|
||||
return null;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
function isBattery(result) {
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
let [device] = result;
|
||||
let [, deviceType] = device;
|
||||
return (deviceType == UPower.DeviceKind.BATTERY);
|
||||
// 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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}));
|
||||
// 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");
|
||||
},
|
||||
});
|
||||
|
@ -9,9 +9,11 @@ const PopupMenu = imports.ui.popupMenu;
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
|
||||
|
||||
const RfkillManagerInterface = <interface name="org.gnome.SettingsDaemon.Rfkill">
|
||||
<property name="AirplaneMode" type="b" access="readwrite" />
|
||||
</interface>;
|
||||
const RfkillManagerInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Rfkill"> \
|
||||
<property name="AirplaneMode" type="b" access="readwrite" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface);
|
||||
|
||||
|
@ -18,10 +18,12 @@ const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
|
||||
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
|
||||
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
|
||||
const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy'
|
||||
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
|
||||
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
|
||||
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
|
||||
const DISABLE_RESTART_KEY = 'disable-restart-buttons';
|
||||
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
|
||||
|
||||
const AltSwitcher = new Lang.Class({
|
||||
@ -91,6 +93,7 @@ const Indicator = new Lang.Class({
|
||||
this.parent();
|
||||
|
||||
this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
|
||||
this._loginScreenSettings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
|
||||
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
|
||||
this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA });
|
||||
this._orientationSettings = new Gio.Settings({ schema: 'org.gnome.settings-daemon.peripherals.touchscreen' });
|
||||
@ -261,7 +264,10 @@ const Indicator = new Lang.Class({
|
||||
},
|
||||
|
||||
_updatePowerOff: function() {
|
||||
this._powerOffAction.visible = this._haveShutdown && !Main.sessionMode.isLocked;
|
||||
let disabled = Main.sessionMode.isLocked ||
|
||||
(Main.sessionMode.isGreeter &&
|
||||
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
|
||||
this._powerOffAction.visible = this._haveShutdown && !disabled;
|
||||
this._updateActionsVisibility();
|
||||
},
|
||||
|
||||
@ -273,7 +279,10 @@ const Indicator = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateSuspend: function() {
|
||||
this._suspendAction.visible = this._haveSuspend && !Main.sessionMode.isLocked;
|
||||
let disabled = Main.sessionMode.isLocked ||
|
||||
(Main.sessionMode.isGreeter &&
|
||||
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
|
||||
this._suspendAction.visible = this._haveShutdown && !disabled;
|
||||
this._updateActionsVisibility();
|
||||
},
|
||||
|
||||
|
@ -11,29 +11,8 @@ const Signals = imports.signals;
|
||||
const Tweener = imports.tweener.tweener;
|
||||
|
||||
// This is a wrapper around imports.tweener.tweener that adds a bit of
|
||||
// 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).
|
||||
|
||||
// Clutter integration. If the tweening target is a Clutter.Actor, then
|
||||
// the tweenings will automatically be removed if the actor is destroyed.
|
||||
|
||||
// ActionScript Tweener methods that imports.tweener.tweener doesn't
|
||||
// currently implement: getTweens, getVersion, registerTransition,
|
||||
@ -77,7 +56,6 @@ 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);
|
||||
}
|
||||
|
||||
@ -85,7 +63,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)
|
||||
_resetTweenState(target);
|
||||
target.__ShellTweenerState = {};
|
||||
return target.__ShellTweenerState;
|
||||
}
|
||||
|
||||
@ -95,8 +73,6 @@ function _resetTweenState(target) {
|
||||
if (state) {
|
||||
if (state.destroyedId)
|
||||
state.actor.disconnect(state.destroyedId);
|
||||
if (state.idleCompletedId)
|
||||
Mainloop.source_remove(state.idleCompletedId);
|
||||
}
|
||||
|
||||
target.__ShellTweenerState = {};
|
||||
@ -122,32 +98,9 @@ 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) {
|
||||
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)) {
|
||||
if (!isTweening(target))
|
||||
_resetTweenState(target);
|
||||
if (delegate && delegate.onAnimationComplete)
|
||||
delegate.onAnimationComplete();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getTweenCount(scope) {
|
||||
|
@ -1,7 +1,8 @@
|
||||
|
||||
// -*- 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;
|
||||
@ -56,6 +57,83 @@ 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',
|
||||
|
||||
@ -67,22 +145,14 @@ const UserWidget = new Lang.Class({
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._avatar = new Avatar(user);
|
||||
this.actor.add(this._avatar.actor,
|
||||
{ x_fill: true, y_fill: true });
|
||||
this.actor.add_child(this._avatar.actor);
|
||||
|
||||
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._label = new UserWidgetLabel(user);
|
||||
this.actor.add_child(this._label);
|
||||
|
||||
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();
|
||||
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();
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
@ -98,11 +168,6 @@ 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();
|
||||
}
|
||||
});
|
||||
|
@ -14,12 +14,9 @@ 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';
|
||||
@ -66,8 +63,6 @@ const ViewSelector = new Lang.Class({
|
||||
this._searchActive = false;
|
||||
this._searchTimeoutId = 0;
|
||||
|
||||
this._searchSystem = new Search.SearchSystem();
|
||||
|
||||
this._entry = searchEntry;
|
||||
ShellEntry.addContextMenu(this._entry);
|
||||
|
||||
@ -103,24 +98,11 @@ const ViewSelector = new Lang.Class({
|
||||
this._appsPage = this._addPage(this.appDisplay.actor,
|
||||
_("Applications"), 'view-grid-symbolic');
|
||||
|
||||
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||
this._searchResults = new Search.SearchResults();
|
||||
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
|
||||
@ -486,45 +468,10 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
let terms = getTermsForSearchString(this._entry.get_text());
|
||||
|
||||
this._searchSystem.updateSearchResults(terms);
|
||||
this._searchResults.setTerms(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
160
js/ui/wanda.js
@ -1,160 +0,0 @@
|
||||
// -*- 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);
|
||||
}
|
||||
});
|
@ -39,6 +39,9 @@ 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);
|
||||
@ -79,7 +82,7 @@ const Source = new Lang.Class({
|
||||
return this._app.create_icon_texture(size);
|
||||
},
|
||||
|
||||
open : function(notification) {
|
||||
open: function() {
|
||||
Main.activateWindow(this._window);
|
||||
this.destroy();
|
||||
}
|
||||
|
@ -10,19 +10,14 @@ 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;
|
||||
@ -892,6 +887,19 @@ 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
|
||||
*/
|
||||
@ -967,11 +975,17 @@ 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)
|
||||
@ -1194,6 +1208,7 @@ const Workspace = new Lang.Class({
|
||||
}
|
||||
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
|
||||
this._repositionWindowsId = 0;
|
||||
return false;
|
||||
},
|
||||
|
||||
@ -1449,17 +1464,17 @@ const Workspace = new Lang.Class({
|
||||
clone.connect('selected',
|
||||
Lang.bind(this, this._onCloneSelected));
|
||||
clone.connect('drag-begin',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.beginWindowDrag();
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginWindowDrag(clone);
|
||||
overlay.hide();
|
||||
}));
|
||||
clone.connect('drag-cancelled',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.cancelledWindowDrag();
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.cancelledWindowDrag(clone);
|
||||
}));
|
||||
clone.connect('drag-end',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.endWindowDrag();
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endWindowDrag(clone);
|
||||
overlay.show();
|
||||
}));
|
||||
clone.connect('size-changed',
|
||||
@ -1621,9 +1636,7 @@ 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, // don't create workspace
|
||||
time);
|
||||
metaWindow.change_workspace_by_index(index, false);
|
||||
return true;
|
||||
} else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
|
||||
|
@ -438,16 +438,16 @@ const WorkspaceThumbnail = new Lang.Class({
|
||||
this.activate(time);
|
||||
}));
|
||||
clone.connect('drag-begin',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.beginWindowDrag();
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginWindowDrag(clone);
|
||||
}));
|
||||
clone.connect('drag-cancelled',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.cancelledWindowDrag();
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.cancelledWindowDrag(clone);
|
||||
}));
|
||||
clone.connect('drag-end',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.endWindowDrag();
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endWindowDrag(clone);
|
||||
}));
|
||||
this._contents.add_actor(clone.actor);
|
||||
|
||||
@ -507,9 +507,7 @@ 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, // don't create workspace
|
||||
time);
|
||||
metaWindow.change_workspace_by_index(this.metaWorkspace.index(), false);
|
||||
return true;
|
||||
} else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
|
||||
@ -739,14 +737,12 @@ 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, time);
|
||||
win.meta_window.change_workspace_by_index(win.get_workspace() + 1, true);
|
||||
});
|
||||
|
||||
if (isWindow)
|
||||
// ... and bam, a workspace, good as new.
|
||||
source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
|
||||
true, time);
|
||||
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true);
|
||||
else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
|
||||
timestamp: time });
|
||||
|
@ -23,75 +23,92 @@ const MAX_WORKSPACES = 16;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
function rectEqual(one, two) {
|
||||
if (one == two)
|
||||
return true;
|
||||
const WorkspacesViewBase = new Lang.Class({
|
||||
Name: 'WorkspacesViewBase',
|
||||
|
||||
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) {
|
||||
_init: function(monitorIndex) {
|
||||
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.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._monitorIndex = monitorIndex;
|
||||
|
||||
this._fullGeometry = null;
|
||||
this._actualGeometry = null;
|
||||
|
||||
this._spacing = 0;
|
||||
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._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._workspaces = workspaces;
|
||||
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));
|
||||
|
||||
// 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._workspaces = [];
|
||||
this._updateWorkspaces();
|
||||
this._updateWorkspacesId = global.screen.connect('notify::n-workspaces', Lang.bind(this, this._updateWorkspaces));
|
||||
|
||||
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() {
|
||||
@ -99,72 +116,21 @@ 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));
|
||||
},
|
||||
|
||||
_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);
|
||||
}
|
||||
},
|
||||
|
||||
_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;
|
||||
|
||||
_setReservedSlot: function(clone) {
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setFullGeometry(geom);
|
||||
this._workspaces[i].setReservedSlot(clone);
|
||||
},
|
||||
|
||||
setActualGeometry: function(geom) {
|
||||
if (rectEqual(this._actualGeometry, geom))
|
||||
return;
|
||||
|
||||
this._actualGeometry = geom;
|
||||
|
||||
_syncGeometry: function() {
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setActualGeometry(geom);
|
||||
this._workspaces[i].setFullGeometry(this._fullGeometry);
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setActualGeometry(this._actualGeometry);
|
||||
},
|
||||
|
||||
getActiveWorkspace: function() {
|
||||
@ -172,29 +138,22 @@ const WorkspacesView = new Lang.Class({
|
||||
return this._workspaces[active];
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||
|
||||
activeWorkspace.actor.raise_top();
|
||||
zoomToOverview: function() {
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].zoomToOverview();
|
||||
this._updateWorkspaceActors(false);
|
||||
},
|
||||
|
||||
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() {
|
||||
@ -216,7 +175,7 @@ const WorkspacesView = new Lang.Class({
|
||||
|
||||
Tweener.removeTweens(workspace.actor);
|
||||
|
||||
let y = (w - active) * (this._fullGeometry.height + this._spacing);
|
||||
let y = (w - active) * this._fullGeometry.height;
|
||||
|
||||
if (showAnimation) {
|
||||
let params = { y: y,
|
||||
@ -276,25 +235,31 @@ const WorkspacesView = new Lang.Class({
|
||||
});
|
||||
},
|
||||
|
||||
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
_updateWorkspaces: function() {
|
||||
let oldNumWorkspaces = this._workspaces.length;
|
||||
let newNumWorkspaces = global.screen.n_workspaces;
|
||||
|
||||
Tweener.addTween(this.scrollAdjustment,
|
||||
{ upper: newNumWorkspaces,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
this.scrollAdjustment.upper = newNumWorkspaces;
|
||||
|
||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
this._workspaces[w].setFullGeometry(this._fullGeometry);
|
||||
if (this._actualGeometry)
|
||||
this._workspaces[w].setActualGeometry(this._actualGeometry);
|
||||
this.actor.add_actor(this._workspaces[w].actor);
|
||||
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._updateWorkspaceActors(false);
|
||||
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._syncGeometry();
|
||||
},
|
||||
|
||||
_activeWorkspaceChanged: function(wm, from, to, direction) {
|
||||
@ -305,70 +270,12 @@ const WorkspacesView = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this._destroyExtraWorkspaces();
|
||||
this.parent();
|
||||
|
||||
this.scrollAdjustment.run_dispose();
|
||||
Main.overview.disconnect(this._overviewShowingId);
|
||||
Main.overview.disconnect(this._overviewShownId);
|
||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||
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);
|
||||
global.screen.disconnect(this._updateWorkspacesId);
|
||||
},
|
||||
|
||||
startSwipeScroll: function() {
|
||||
@ -427,6 +334,42 @@ 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',
|
||||
@ -471,7 +414,6 @@ 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 });
|
||||
@ -480,9 +422,6 @@ 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;
|
||||
@ -500,6 +439,8 @@ 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',
|
||||
@ -509,9 +450,8 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++) {
|
||||
this._workspacesViews[i].hide();
|
||||
}
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].zoomFromOverview();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
@ -543,46 +483,38 @@ 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)
|
||||
continue; // we are only interested in the primary monitor
|
||||
view = new ExtraWorkspaceView(i);
|
||||
else
|
||||
view = new WorkspacesView(i);
|
||||
|
||||
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 (this._workspacesOnlyOnPrimary || i == this._primaryIndex) {
|
||||
if (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;
|
||||
@ -592,10 +524,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
_getPrimaryView: function() {
|
||||
if (!this._workspacesViews.length)
|
||||
return null;
|
||||
if (this._workspacesOnlyOnPrimary)
|
||||
return this._workspacesViews[0];
|
||||
else
|
||||
return this._workspacesViews[this._primaryIndex];
|
||||
return this._workspacesViews[this._primaryIndex];
|
||||
},
|
||||
|
||||
activeWorkspaceHasMaximizedWindows: function() {
|
||||
@ -641,15 +570,9 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
return;
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == this._primaryIndex) {
|
||||
this._workspacesViews[m].setFullGeometry(this._fullGeometry);
|
||||
m++;
|
||||
} else if (!this._workspacesOnlyOnPrimary) {
|
||||
this._workspacesViews[m].setFullGeometry(monitors[i]);
|
||||
m++;
|
||||
}
|
||||
let geometry = (i == this._primaryIndex) ? this._fullGeometry : monitors[i];
|
||||
this._workspacesViews[i].setFullGeometry(geometry);
|
||||
}
|
||||
},
|
||||
|
||||
@ -660,18 +583,12 @@ 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 geometry = { x: x, y: y, width: width, height: height };
|
||||
let primaryGeometry = { x: x, y: y, width: width, height: height };
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == this._primaryIndex) {
|
||||
this._workspacesViews[m].setActualGeometry(geometry);
|
||||
m++;
|
||||
} else if (!this._workspacesOnlyOnPrimary) {
|
||||
this._workspacesViews[m].setActualGeometry(monitors[i]);
|
||||
m++;
|
||||
}
|
||||
let geometry = (i == this._primaryIndex) ? primaryGeometry : monitors[i];
|
||||
this._workspacesViews[i].setActualGeometry(geometry);
|
||||
}
|
||||
},
|
||||
|
||||
@ -680,60 +597,6 @@ 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;
|
||||
|
@ -38,7 +38,7 @@ js/ui/panel.js
|
||||
js/ui/popupMenu.js
|
||||
js/ui/runDialog.js
|
||||
js/ui/screenShield.js
|
||||
js/ui/searchDisplay.js
|
||||
js/ui/search.js
|
||||
js/ui/shellEntry.js
|
||||
js/ui/shellMountOperation.js
|
||||
js/ui/status/accessibility.js
|
||||
@ -52,7 +52,6 @@ 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
|
||||
|
294
po/pt_BR.po
294
po/pt_BR.po
@ -19,8 +19,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-10-10 21:27+0000\n"
|
||||
"PO-Revision-Date: 2013-10-11 07:22-0300\n"
|
||||
"POT-Creation-Date: 2013-10-26 13:17+0000\n"
|
||||
"PO-Revision-Date: 2013-10-27 15:38-0300\n"
|
||||
"Last-Translator: Rafael Ferreira <rafael.f.f1@gmail.com>\n"
|
||||
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
|
||||
"Language: pt_BR\n"
|
||||
@ -291,23 +291,23 @@ msgid "Select an extension to configure using the combobox above."
|
||||
msgstr ""
|
||||
"Selecione uma extensão para configurar usando a caixa de seleção abaixo."
|
||||
|
||||
#: ../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:728
|
||||
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:739
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: ../js/gdm/authPrompt.js:167 ../js/gdm/authPrompt.js:215
|
||||
#: ../js/gdm/authPrompt.js:168 ../js/gdm/authPrompt.js:216
|
||||
msgid "Next"
|
||||
msgstr "Próximo"
|
||||
|
||||
#: ../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 "Desbloquear"
|
||||
|
||||
#: ../js/gdm/authPrompt.js:213
|
||||
#: ../js/gdm/authPrompt.js:214
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "Entrar"
|
||||
@ -334,11 +334,11 @@ msgstr "Nome de usuário: "
|
||||
msgid "Login Window"
|
||||
msgstr "Janela de sessão"
|
||||
|
||||
#: ../js/gdm/util.js:306
|
||||
#: ../js/gdm/util.js:321
|
||||
msgid "Authentication error"
|
||||
msgstr "Erro de autenticação"
|
||||
|
||||
#: ../js/gdm/util.js:436
|
||||
#: ../js/gdm/util.js:451
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(ou deslize o dedo)"
|
||||
|
||||
@ -367,15 +367,15 @@ msgstr "Frequente"
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1514
|
||||
#: ../js/ui/appDisplay.js:1523
|
||||
msgid "New Window"
|
||||
msgstr "Nova janela"
|
||||
|
||||
#: ../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 "Remover dos favoritos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1518
|
||||
#: ../js/ui/appDisplay.js:1527
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Adicionar aos favoritos"
|
||||
|
||||
@ -389,7 +389,7 @@ msgstr "%s foi adicionado aos seus favoritos."
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s foi removido dos seus favoritos."
|
||||
|
||||
#: ../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 "Configurações"
|
||||
@ -589,8 +589,8 @@ msgstr "Senha:"
|
||||
msgid "Type again:"
|
||||
msgstr "Digite novamente:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:133
|
||||
#: ../js/ui/status/network.js:296 ../js/ui/status/network.js:731
|
||||
#: ../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 "Conectar"
|
||||
|
||||
@ -684,60 +684,60 @@ msgstr "Autenticação"
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "Desculpe, isto não funcionou. Por favor, tente novamente."
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:238
|
||||
#: ../js/ui/components/telepathyClient.js:237
|
||||
msgid "Invitation"
|
||||
msgstr "Convite"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:298
|
||||
#: ../js/ui/components/telepathyClient.js:297
|
||||
msgid "Call"
|
||||
msgstr "Chamada"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:314
|
||||
#: ../js/ui/components/telepathyClient.js:313
|
||||
msgid "File Transfer"
|
||||
msgstr "Transferência de arquivo"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:418
|
||||
#: ../js/ui/components/telepathyClient.js:417
|
||||
msgid "Chat"
|
||||
msgstr "Conversar"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:480
|
||||
#: ../js/ui/components/telepathyClient.js:479
|
||||
msgid "Unmute"
|
||||
msgstr "Ativar áudio"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:480
|
||||
#: ../js/ui/components/telepathyClient.js:479
|
||||
msgid "Mute"
|
||||
msgstr "Sem áudio"
|
||||
|
||||
#. 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>Ontem</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> de <b>%B</b>, às <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> de <b>%B</b> de <b>%Y</b>, às <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 agora é conhecido como %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 "Convite para %s"
|
||||
@ -745,38 +745,38 @@ msgstr "Convite para %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 está convidando você para participar de %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 "Recusar"
|
||||
|
||||
#: ../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 "Aceitar"
|
||||
|
||||
#. 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 "Chamada de vídeo para %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 "Chamada de %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 "Atender"
|
||||
|
||||
@ -785,110 +785,110 @@ msgstr "Atender"
|
||||
#. * 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 está enviando %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 quer permissão para vê-lo quando conectado"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1301
|
||||
#: ../js/ui/components/telepathyClient.js:1300
|
||||
msgid "Network error"
|
||||
msgstr "Erro de rede"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1303
|
||||
#: ../js/ui/components/telepathyClient.js:1302
|
||||
msgid "Authentication failed"
|
||||
msgstr "Falha de autenticação"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1305
|
||||
#: ../js/ui/components/telepathyClient.js:1304
|
||||
msgid "Encryption error"
|
||||
msgstr "Erro de criptografia"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1307
|
||||
#: ../js/ui/components/telepathyClient.js:1306
|
||||
msgid "Certificate not provided"
|
||||
msgstr "Certificado não fornecido"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1309
|
||||
#: ../js/ui/components/telepathyClient.js:1308
|
||||
msgid "Certificate untrusted"
|
||||
msgstr "Certificado não confiável"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1311
|
||||
#: ../js/ui/components/telepathyClient.js:1310
|
||||
msgid "Certificate expired"
|
||||
msgstr "Certificado expirado"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1313
|
||||
#: ../js/ui/components/telepathyClient.js:1312
|
||||
msgid "Certificate not activated"
|
||||
msgstr "Certificado não ativado"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1315
|
||||
#: ../js/ui/components/telepathyClient.js:1314
|
||||
msgid "Certificate hostname mismatch"
|
||||
msgstr "Máquina do certificado não confere"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1317
|
||||
#: ../js/ui/components/telepathyClient.js:1316
|
||||
msgid "Certificate fingerprint mismatch"
|
||||
msgstr "Impressão digital do certificado não confere"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1319
|
||||
#: ../js/ui/components/telepathyClient.js:1318
|
||||
msgid "Certificate self-signed"
|
||||
msgstr "Certificado auto-assinado"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1321
|
||||
#: ../js/ui/components/telepathyClient.js:1320
|
||||
msgid "Status is set to offline"
|
||||
msgstr "O status está definido como desconectado."
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1323
|
||||
#: ../js/ui/components/telepathyClient.js:1322
|
||||
msgid "Encryption is not available"
|
||||
msgstr "Criptografia não disponível"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1325
|
||||
#: ../js/ui/components/telepathyClient.js:1324
|
||||
msgid "Certificate is invalid"
|
||||
msgstr "O certificado é inválido"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1327
|
||||
#: ../js/ui/components/telepathyClient.js:1326
|
||||
msgid "Connection has been refused"
|
||||
msgstr "A conexão foi recusada"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1329
|
||||
#: ../js/ui/components/telepathyClient.js:1328
|
||||
msgid "Connection can't be established"
|
||||
msgstr "A conexão não pode ser estabelecida"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1331
|
||||
#: ../js/ui/components/telepathyClient.js:1330
|
||||
msgid "Connection has been lost"
|
||||
msgstr "Conexão perdida"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1333
|
||||
#: ../js/ui/components/telepathyClient.js:1332
|
||||
msgid "This account is already connected to the server"
|
||||
msgstr "Esta conta já está conectada ao servidor"
|
||||
|
||||
#: ../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 "A conexão foi substituída por uma nova conexão usando o mesmo recurso"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1337
|
||||
#: ../js/ui/components/telepathyClient.js:1336
|
||||
msgid "The account already exists on the server"
|
||||
msgstr "A conta já existe no servidor"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1339
|
||||
#: ../js/ui/components/telepathyClient.js:1338
|
||||
msgid "Server is currently too busy to handle the connection"
|
||||
msgstr "O servidor está atualmente muito ocupado para controlar a conexão"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1341
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
msgid "Certificate has been revoked"
|
||||
msgstr "O certificado foi revogado"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1343
|
||||
#: ../js/ui/components/telepathyClient.js:1342
|
||||
msgid ""
|
||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr ""
|
||||
"O certificado usa um algoritmo de cifragem inseguro ou é criptograficamente "
|
||||
"fraco"
|
||||
|
||||
#: ../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"
|
||||
@ -896,22 +896,22 @@ msgstr ""
|
||||
"O comprimento do certificado do servidor, ou a profundidade da cadeia do "
|
||||
"certificado excedeu os limites impostos pela biblioteca de criptografia"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1347
|
||||
#: ../js/ui/components/telepathyClient.js:1346
|
||||
msgid "Internal error"
|
||||
msgstr "Erro interno"
|
||||
|
||||
#. 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 "Não foi possível conectar-se a %s"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1362
|
||||
#: ../js/ui/components/telepathyClient.js:1361
|
||||
msgid "View account"
|
||||
msgstr "Visualizar conta"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1401
|
||||
#: ../js/ui/components/telepathyClient.js:1400
|
||||
msgid "Unknown reason"
|
||||
msgstr "Razão desconhecida"
|
||||
|
||||
@ -1092,7 +1092,7 @@ msgstr "Habilitado"
|
||||
#. because it's disabled by rfkill (airplane mode) */
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:473
|
||||
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:472
|
||||
#: ../src/gvc/gvc-mixer-control.c:1830
|
||||
msgid "Disabled"
|
||||
msgstr "Desabilitado"
|
||||
@ -1117,49 +1117,48 @@ msgstr "Ver fonte"
|
||||
msgid "Web Page"
|
||||
msgstr "Página web"
|
||||
|
||||
#: ../js/ui/messageTray.js:1222
|
||||
#: ../js/ui/messageTray.js:1347
|
||||
msgid "Open"
|
||||
msgstr "Abrir"
|
||||
|
||||
#: ../js/ui/messageTray.js:1229
|
||||
#: ../js/ui/messageTray.js:1354
|
||||
msgid "Remove"
|
||||
msgstr "Remover"
|
||||
|
||||
#: ../js/ui/messageTray.js:1530
|
||||
#| msgid "Notification Settings"
|
||||
#: ../js/ui/messageTray.js:1657
|
||||
msgid "Notifications"
|
||||
msgstr "Notificações"
|
||||
|
||||
#: ../js/ui/messageTray.js:1537
|
||||
#: ../js/ui/messageTray.js:1664
|
||||
msgid "Clear Messages"
|
||||
msgstr "Sem mensagens"
|
||||
|
||||
#: ../js/ui/messageTray.js:1564
|
||||
#: ../js/ui/messageTray.js:1683
|
||||
msgid "Notification Settings"
|
||||
msgstr "Configurações de notificação"
|
||||
|
||||
#: ../js/ui/messageTray.js:1617
|
||||
#: ../js/ui/messageTray.js:1736
|
||||
msgid "Tray Menu"
|
||||
msgstr "Menu de notificação"
|
||||
|
||||
#: ../js/ui/messageTray.js:1833
|
||||
#: ../js/ui/messageTray.js:1952
|
||||
msgid "No Messages"
|
||||
msgstr "Sem mensagens"
|
||||
|
||||
#: ../js/ui/messageTray.js:1871
|
||||
#: ../js/ui/messageTray.js:1990
|
||||
msgid "Message Tray"
|
||||
msgstr "Área de notificação"
|
||||
|
||||
#: ../js/ui/messageTray.js:2846
|
||||
#: ../js/ui/messageTray.js:2965
|
||||
msgid "System Information"
|
||||
msgstr "Informações do sistema"
|
||||
|
||||
#: ../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 "Desconhecido"
|
||||
|
||||
#: ../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"
|
||||
@ -1182,21 +1181,21 @@ msgstr "Panorama"
|
||||
msgid "Type to search…"
|
||||
msgstr "Digite para pesquisar…"
|
||||
|
||||
#: ../js/ui/panel.js:518
|
||||
#: ../js/ui/panel.js:516
|
||||
msgid "Quit"
|
||||
msgstr "Sair"
|
||||
|
||||
#. 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 "Atividades"
|
||||
|
||||
#: ../js/ui/panel.js:904
|
||||
#: ../js/ui/panel.js:900
|
||||
msgid "Top Bar"
|
||||
msgstr "Barra superior"
|
||||
|
||||
#: ../js/ui/popupMenu.js:233
|
||||
#: ../js/ui/popupMenu.js:260
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
@ -1210,30 +1209,30 @@ msgstr "Fechar"
|
||||
|
||||
#. 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 de %B"
|
||||
|
||||
#: ../js/ui/screenShield.js:154
|
||||
#: ../js/ui/screenShield.js:155
|
||||
#, javascript-format
|
||||
msgid "%d new notification"
|
||||
msgid_plural "%d new notifications"
|
||||
msgstr[0] "%d nova notificação"
|
||||
msgstr[1] "%d novas notificações"
|
||||
|
||||
#: ../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 "Bloquear"
|
||||
|
||||
#: ../js/ui/screenShield.js:704
|
||||
#: ../js/ui/screenShield.js:712
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME precisa bloquear a tela"
|
||||
|
||||
#: ../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 "Não foi possível bloquear"
|
||||
|
||||
#: ../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 "O bloqueio foi impedido por um aplicativo"
|
||||
|
||||
@ -1273,111 +1272,111 @@ msgstr "Lembrar senha"
|
||||
msgid "Accessibility"
|
||||
msgstr "Acessibilidade"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:58
|
||||
#: ../js/ui/status/accessibility.js:56
|
||||
msgid "Zoom"
|
||||
msgstr "Ampliador"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:65
|
||||
#: ../js/ui/status/accessibility.js:63
|
||||
msgid "Screen Reader"
|
||||
msgstr "Leitor de tela"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:69
|
||||
#: ../js/ui/status/accessibility.js:67
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Teclado de tela"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:73
|
||||
#: ../js/ui/status/accessibility.js:71
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Alertas visuais"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:76
|
||||
#: ../js/ui/status/accessibility.js:74
|
||||
msgid "Sticky Keys"
|
||||
msgstr "Teclas de aderência"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:79
|
||||
#: ../js/ui/status/accessibility.js:77
|
||||
msgid "Slow Keys"
|
||||
msgstr "Teclas lentas"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:82
|
||||
#: ../js/ui/status/accessibility.js:80
|
||||
msgid "Bounce Keys"
|
||||
msgstr "Teclas de repercussão"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:85
|
||||
#: ../js/ui/status/accessibility.js:83
|
||||
msgid "Mouse Keys"
|
||||
msgstr "Teclas do mouse"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:144
|
||||
#: ../js/ui/status/accessibility.js:142
|
||||
msgid "High Contrast"
|
||||
msgstr "Alto contraste"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:193
|
||||
#: ../js/ui/status/accessibility.js:191
|
||||
msgid "Large Text"
|
||||
msgstr "Texto grande"
|
||||
|
||||
#: ../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:133
|
||||
#: ../js/ui/status/network.js:1085 ../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 "Desligar"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:33
|
||||
#: ../js/ui/status/bluetooth.js:32
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Configurações de Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:58
|
||||
#: ../js/ui/status/bluetooth.js:57
|
||||
#, javascript-format
|
||||
msgid "%d Connected Device"
|
||||
msgid_plural "%d Connected Devices"
|
||||
msgstr[0] "%d dispositivo conectado"
|
||||
msgstr[1] "%d dispositivos conectados"
|
||||
|
||||
#: ../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 "Autorização requisitada de %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 "O dispositivo %s deseja parear com este computador"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
#: ../js/ui/status/bluetooth.js:108
|
||||
msgid "Allow"
|
||||
msgstr "Permitir"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:110
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
msgid "Deny"
|
||||
msgstr "Negar"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:135
|
||||
#: ../js/ui/status/bluetooth.js:134
|
||||
#, javascript-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "O dispositivo %s deseja acessar o serviço \"%s\""
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
#: ../js/ui/status/bluetooth.js:136
|
||||
msgid "Always grant access"
|
||||
msgstr "Sempre permitir acesso"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
msgid "Grant this time only"
|
||||
msgstr "Permitir apenas desta vez"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:139
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
msgid "Reject"
|
||||
msgstr "Rejeitar"
|
||||
|
||||
#. 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 "Confirmação de pareamento para %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."
|
||||
@ -1386,24 +1385,24 @@ msgstr ""
|
||||
"dispositivo."
|
||||
|
||||
#. Translators: this is the verb, not the noun */
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
#: ../js/ui/status/bluetooth.js:175
|
||||
msgid "Matches"
|
||||
msgstr "Corresponde"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:177
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
msgid "Does not match"
|
||||
msgstr "Não corresponde"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:196
|
||||
#: ../js/ui/status/bluetooth.js:195
|
||||
#, javascript-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Requisição de pareamento para %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:204
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Por favor, informe o PIN mencionado no dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:221
|
||||
#: ../js/ui/status/bluetooth.js:220
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
@ -1411,99 +1410,100 @@ msgstr "OK"
|
||||
msgid "Brightness"
|
||||
msgstr "Brilho"
|
||||
|
||||
#: ../js/ui/status/network.js:72
|
||||
#: ../js/ui/status/network.js:71
|
||||
msgid "<unknown>"
|
||||
msgstr "<desconhecido>"
|
||||
|
||||
#: ../js/ui/status/network.js:223 ../js/ui/status/network.js:380
|
||||
#: ../js/ui/status/network.js:1106
|
||||
# Referente ao estado "desligado" da rede.
|
||||
#: ../js/ui/status/network.js:222 ../js/ui/status/network.js:379
|
||||
#: ../js/ui/status/network.js:1120
|
||||
msgid "Off"
|
||||
msgstr "Desligar"
|
||||
msgstr "Desligado"
|
||||
|
||||
#. 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:386
|
||||
#: ../js/ui/status/network.js:385
|
||||
msgid "unmanaged"
|
||||
msgstr "não gerenciado"
|
||||
|
||||
#: ../js/ui/status/network.js:388
|
||||
#: ../js/ui/status/network.js:387
|
||||
msgid "disconnecting..."
|
||||
msgstr "desconectando..."
|
||||
|
||||
#: ../js/ui/status/network.js:394 ../js/ui/status/network.js:1160
|
||||
#: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1174
|
||||
msgid "connecting..."
|
||||
msgstr "conectando..."
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password */
|
||||
#: ../js/ui/status/network.js:397 ../js/ui/status/network.js:1163
|
||||
#: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1177
|
||||
msgid "authentication required"
|
||||
msgstr "autenticação necessária"
|
||||
|
||||
#. Translators: this is for devices that require some kind of firmware or kernel
|
||||
#. module, which is missing */
|
||||
#: ../js/ui/status/network.js:405
|
||||
#: ../js/ui/status/network.js:404
|
||||
msgid "firmware missing"
|
||||
msgstr "firmware faltando"
|
||||
|
||||
#. 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:409
|
||||
#: ../js/ui/status/network.js:408
|
||||
msgid "unavailable"
|
||||
msgstr "indisponível"
|
||||
|
||||
#: ../js/ui/status/network.js:411 ../js/ui/status/network.js:1165
|
||||
#: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1179
|
||||
msgid "connection failed"
|
||||
msgstr "conexão falhou"
|
||||
|
||||
#: ../js/ui/status/network.js:427 ../js/ui/status/network.js:513
|
||||
#: ../js/ui/status/network.js:426 ../js/ui/status/network.js:512
|
||||
msgid "Mobile Broadband Settings"
|
||||
msgstr "Configurações de banda larga móvel"
|
||||
|
||||
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1104
|
||||
#: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1118
|
||||
msgid "Hardware Disabled"
|
||||
msgstr "Hardware desabilitado"
|
||||
|
||||
#: ../js/ui/status/network.js:696
|
||||
#: ../js/ui/status/network.js:707
|
||||
msgid "Wi-Fi Networks"
|
||||
msgstr "Redes Wi-Fi"
|
||||
|
||||
#: ../js/ui/status/network.js:698
|
||||
#: ../js/ui/status/network.js:709
|
||||
msgid "Select a network"
|
||||
msgstr "Selecione uma rede"
|
||||
|
||||
#: ../js/ui/status/network.js:722
|
||||
#: ../js/ui/status/network.js:733
|
||||
msgid "No Networks"
|
||||
msgstr "Nenhuma rede"
|
||||
|
||||
#: ../js/ui/status/network.js:991
|
||||
#: ../js/ui/status/network.js:1005
|
||||
msgid "Select Network"
|
||||
msgstr "Selecione a rede"
|
||||
|
||||
#: ../js/ui/status/network.js:997
|
||||
#: ../js/ui/status/network.js:1011
|
||||
msgid "Wi-Fi Settings"
|
||||
msgstr "Configurações de Wi-Fi"
|
||||
|
||||
#: ../js/ui/status/network.js:1085
|
||||
#: ../js/ui/status/network.js:1099
|
||||
msgid "Turn On"
|
||||
msgstr "Ligar"
|
||||
|
||||
#: ../js/ui/status/network.js:1108
|
||||
#: ../js/ui/status/network.js:1122
|
||||
msgid "Not Connected"
|
||||
msgstr "Não conectado"
|
||||
|
||||
#: ../js/ui/status/network.js:1228
|
||||
#: ../js/ui/status/network.js:1242
|
||||
msgid "VPN"
|
||||
msgstr "VPN"
|
||||
|
||||
#: ../js/ui/status/network.js:1368
|
||||
#: ../js/ui/status/network.js:1382
|
||||
msgid "Network Manager"
|
||||
msgstr "Gerenciador de rede"
|
||||
|
||||
#: ../js/ui/status/network.js:1407
|
||||
#: ../js/ui/status/network.js:1421
|
||||
msgid "Connection failed"
|
||||
msgstr "Falha de conexão"
|
||||
|
||||
#: ../js/ui/status/network.js:1408
|
||||
#: ../js/ui/status/network.js:1422
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Falha ao ativar a conexão da rede"
|
||||
|
||||
|
1560
po/zh_CN.po
1560
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@ -156,8 +156,10 @@ libst_1_0_la_SOURCES = \
|
||||
$(st_source_private_h) \
|
||||
$(st_source_private_c) \
|
||||
$(st_source_h) \
|
||||
st.h \
|
||||
$(NULL)
|
||||
nodist_libst_1_0_la_SOURCES = \
|
||||
$(st_built_sources) \
|
||||
st.h \
|
||||
$(NULL)
|
||||
libst_1_0_la_CPPFLAGS = $(st_cflags)
|
||||
libst_1_0_la_LDFLAGS = $(LDADD)
|
||||
|
@ -4,8 +4,6 @@ tray_cflags = \
|
||||
$(TRAY_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES += $(tray_built_sources)
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
tray_source = \
|
||||
tray/na-tray-child.c \
|
||||
@ -19,7 +17,6 @@ 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)
|
||||
|
@ -75,8 +75,7 @@ gnome_shell_cflags = \
|
||||
-DDATADIR=\"$(datadir)\" \
|
||||
-DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
|
||||
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DJSDIR=\"$(pkgdatadir)/js\"
|
||||
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\"
|
||||
|
||||
privlibdir = $(pkglibdir)
|
||||
privlib_LTLIBRARIES = libgnome-shell-js.la libgnome-shell-menu.la libgnome-shell.la
|
||||
@ -152,7 +151,6 @@ 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 \
|
||||
@ -173,10 +171,17 @@ 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))
|
||||
$(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_base_la_SOURCES) $(libgnome_shell_sources) $(libgnome_shell_built_sources))
|
||||
|
||||
gnome_shell_SOURCES = main.c
|
||||
gnome_shell_CPPFLAGS = \
|
||||
@ -191,6 +196,7 @@ 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 = \
|
||||
@ -207,7 +213,7 @@ endif HAVE_MUTTER_WAYLAND
|
||||
|
||||
libgnome_shell_js_la_SOURCES = \
|
||||
shell-js.h \
|
||||
shell-js.c \
|
||||
shell-js.cpp \
|
||||
$(NULL)
|
||||
|
||||
libgnome_shell_js_la_LIBADD = \
|
||||
|
@ -29,8 +29,6 @@
|
||||
#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"
|
||||
|
@ -12,9 +12,9 @@ G_BEGIN_DECLS
|
||||
|
||||
ShellApp* _shell_app_new_for_window (MetaWindow *window);
|
||||
|
||||
ShellApp* _shell_app_new (GMenuTreeEntry *entry);
|
||||
ShellApp* _shell_app_new (GDesktopAppInfo *info);
|
||||
|
||||
void _shell_app_set_entry (ShellApp *app, GMenuTreeEntry *entry);
|
||||
void _shell_app_set_app_info (ShellApp *app, GDesktopAppInfo *info);
|
||||
|
||||
void _shell_app_handle_startup_sequence (ShellApp *app, SnStartupSequence *sequence);
|
||||
|
||||
|
@ -38,18 +38,12 @@ 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_app;
|
||||
|
||||
GSList *known_vendor_prefixes;
|
||||
GHashTable *startup_wm_class_to_id;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
@ -77,10 +71,45 @@ 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,
|
||||
@ -91,19 +120,11 @@ shell_app_system_init (ShellAppSystem *self)
|
||||
NULL,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
|
||||
/* 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);
|
||||
priv->startup_wm_class_to_id = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
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);
|
||||
monitor = g_app_info_monitor_get ();
|
||||
g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
|
||||
installed_changed (monitor, self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -112,313 +133,13 @@ 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->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_hash_table_destroy (priv->startup_wm_class_to_id);
|
||||
|
||||
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:
|
||||
*
|
||||
@ -446,61 +167,21 @@ ShellApp *
|
||||
shell_app_system_lookup_app (ShellAppSystem *self,
|
||||
const char *id)
|
||||
{
|
||||
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;
|
||||
ShellAppSystemPrivate *priv = self->priv;
|
||||
ShellApp *app;
|
||||
GDesktopAppInfo *info;
|
||||
|
||||
basename = g_strrstr (desktop_path, "/");
|
||||
if (basename)
|
||||
basename += 1;
|
||||
else
|
||||
basename = desktop_path;
|
||||
app = g_hash_table_lookup (priv->id_to_app, id);
|
||||
if (app)
|
||||
return app;
|
||||
|
||||
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)
|
||||
info = g_desktop_app_info_new (id);
|
||||
if (!info)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -520,15 +201,15 @@ shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
|
||||
const char *name)
|
||||
{
|
||||
ShellApp *result;
|
||||
GSList *prefix;
|
||||
const char *const *prefix;
|
||||
|
||||
result = shell_app_system_lookup_app (system, name);
|
||||
if (result != NULL)
|
||||
return result;
|
||||
|
||||
for (prefix = system->priv->known_vendor_prefixes; prefix; prefix = g_slist_next (prefix))
|
||||
for (prefix = vendor_prefixes; *prefix != NULL; prefix++)
|
||||
{
|
||||
char *tmpid = g_strconcat ((char*)prefix->data, name, NULL);
|
||||
char *tmpid = g_strconcat (*prefix, name, NULL);
|
||||
result = shell_app_system_lookup_app (system, tmpid);
|
||||
g_free (tmpid);
|
||||
if (result != NULL)
|
||||
@ -603,10 +284,16 @@ ShellApp *
|
||||
shell_app_system_lookup_startup_wmclass (ShellAppSystem *system,
|
||||
const char *wmclass)
|
||||
{
|
||||
const char *id;
|
||||
|
||||
if (wmclass == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_hash_table_lookup (system->priv->startup_wm_class_to_app, wmclass);
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
@ -681,13 +368,22 @@ 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);
|
||||
return g_slist_concat (prefix_matches, substring_matches);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -734,7 +430,6 @@ search_tree (ShellAppSystem *self,
|
||||
g_slist_free_full (normalized_terms, g_free);
|
||||
|
||||
return sort_and_concat_results (self, prefix_results, substring_results);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -744,26 +439,26 @@ search_tree (ShellAppSystem *self,
|
||||
*
|
||||
* Search through applications for the given search terms.
|
||||
*
|
||||
* Returns: (transfer container) (element-type ShellApp): List of applications
|
||||
* Returns: (transfer container) (element-type utf8): List of applications
|
||||
*/
|
||||
GSList *
|
||||
shell_app_system_initial_search (ShellAppSystem *self,
|
||||
GSList *terms)
|
||||
{
|
||||
return search_tree (self, terms, self->priv->visible_id_to_app);
|
||||
return search_tree (self, terms, self->priv->id_to_app);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_app_system_subsearch:
|
||||
* @system: A #ShellAppSystem
|
||||
* @previous_results: (element-type ShellApp): List of previous results
|
||||
* @previous_results: (element-type utf8): 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 ShellApp): List of application identifiers
|
||||
* Returns: (transfer container) (element-type utf8): List of application identifiers
|
||||
*/
|
||||
GSList *
|
||||
shell_app_system_subsearch (ShellAppSystem *system,
|
||||
@ -779,8 +474,8 @@ shell_app_system_subsearch (ShellAppSystem *system,
|
||||
|
||||
for (iter = previous_results; iter; iter = iter->next)
|
||||
{
|
||||
ShellApp *app = iter->data;
|
||||
|
||||
ShellApp *app = shell_app_system_lookup_app (system, iter->data);
|
||||
|
||||
_shell_app_do_match (app, normalized_terms,
|
||||
&prefix_results,
|
||||
&substring_results);
|
||||
|
@ -5,8 +5,6 @@
|
||||
#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"
|
||||
|
||||
@ -39,14 +37,8 @@ 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);
|
||||
|
||||
|
150
src/shell-app.c
150
src/shell-app.c
@ -17,6 +17,12 @@
|
||||
#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 */
|
||||
@ -37,7 +43,7 @@ typedef struct {
|
||||
GSList *windows;
|
||||
|
||||
/* Whether or not we need to resort the windows; this is done on demand */
|
||||
gboolean window_sort_stale : 1;
|
||||
guint window_sort_stale : 1;
|
||||
|
||||
/* DBus property notification subscription */
|
||||
guint properties_changed_id : 1;
|
||||
@ -53,7 +59,7 @@ typedef struct {
|
||||
* SECTION:shell-app
|
||||
* @short_description: Object representing an application
|
||||
*
|
||||
* This object wraps a #GMenuTreeEntry, providing methods and signals
|
||||
* This object wraps a #GDesktopAppInfo, providing methods and signals
|
||||
* primarily useful for running applications.
|
||||
*/
|
||||
struct _ShellApp
|
||||
@ -64,7 +70,7 @@ struct _ShellApp
|
||||
|
||||
ShellAppState state;
|
||||
|
||||
GMenuTreeEntry *entry; /* If NULL, this app is backed by one or more
|
||||
GDesktopAppInfo *info; /* 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
|
||||
@ -137,15 +143,15 @@ shell_app_get_property (GObject *gobject,
|
||||
const char *
|
||||
shell_app_get_id (ShellApp *app)
|
||||
{
|
||||
if (app->entry)
|
||||
return gmenu_tree_entry_get_desktop_file_id (app->entry);
|
||||
if (app->info)
|
||||
return g_app_info_get_id (G_APP_INFO (app->info));
|
||||
return app->window_id_string;
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
window_backed_app_get_window (ShellApp *app)
|
||||
{
|
||||
g_assert (app->entry == NULL);
|
||||
g_assert (app->info == NULL);
|
||||
g_assert (app->running_state);
|
||||
g_assert (app->running_state->windows);
|
||||
return app->running_state->windows->data;
|
||||
@ -194,10 +200,10 @@ shell_app_create_icon_texture (ShellApp *app,
|
||||
|
||||
ret = NULL;
|
||||
|
||||
if (app->entry == NULL)
|
||||
if (app->info == NULL)
|
||||
return window_backed_app_get_icon (app, size);
|
||||
|
||||
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
||||
icon = g_app_info_get_icon (G_APP_INFO (app->info));
|
||||
if (icon != NULL)
|
||||
ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, size);
|
||||
|
||||
@ -245,7 +251,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
|
||||
|
||||
info = NULL;
|
||||
|
||||
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
||||
icon = g_app_info_get_icon (G_APP_INFO (app->info));
|
||||
if (icon != NULL)
|
||||
{
|
||||
info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
|
||||
@ -347,7 +353,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->entry)
|
||||
if (!app->info)
|
||||
return window_backed_app_get_icon (app, size);
|
||||
|
||||
/* Use icon: prefix so that we get evicted from the cache on
|
||||
@ -384,8 +390,8 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
|
||||
const char *
|
||||
shell_app_get_name (ShellApp *app)
|
||||
{
|
||||
if (app->entry)
|
||||
return g_app_info_get_name (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
||||
if (app->info)
|
||||
return g_app_info_get_name (G_APP_INFO (app->info));
|
||||
else
|
||||
{
|
||||
MetaWindow *window = window_backed_app_get_window (app);
|
||||
@ -401,8 +407,8 @@ shell_app_get_name (ShellApp *app)
|
||||
const char *
|
||||
shell_app_get_description (ShellApp *app)
|
||||
{
|
||||
if (app->entry)
|
||||
return g_app_info_get_description (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
||||
if (app->info)
|
||||
return g_app_info_get_description (G_APP_INFO (app->info));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@ -417,7 +423,7 @@ shell_app_get_description (ShellApp *app)
|
||||
gboolean
|
||||
shell_app_is_window_backed (ShellApp *app)
|
||||
{
|
||||
return app->entry == NULL;
|
||||
return app->info == NULL;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -633,12 +639,7 @@ shell_app_activate_full (ShellApp *app,
|
||||
case SHELL_APP_STATE_STOPPED:
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (!shell_app_launch (app,
|
||||
timestamp,
|
||||
NULL,
|
||||
workspace,
|
||||
NULL,
|
||||
&error))
|
||||
if (!shell_app_launch (app, timestamp, workspace, &error))
|
||||
{
|
||||
char *msg;
|
||||
msg = g_strdup_printf (_("Failed to launch '%s'"), shell_app_get_name (app));
|
||||
@ -670,7 +671,7 @@ void
|
||||
shell_app_open_new_window (ShellApp *app,
|
||||
int workspace)
|
||||
{
|
||||
g_return_if_fail (app->entry != NULL);
|
||||
g_return_if_fail (app->info != NULL);
|
||||
|
||||
/* Here we just always launch the application again, even if we know
|
||||
* it was already running. For most applications this
|
||||
@ -680,12 +681,7 @@ 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,
|
||||
NULL,
|
||||
workspace,
|
||||
NULL,
|
||||
NULL);
|
||||
shell_app_launch (app, 0, workspace, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -865,25 +861,24 @@ _shell_app_new_for_window (MetaWindow *window)
|
||||
}
|
||||
|
||||
ShellApp *
|
||||
_shell_app_new (GMenuTreeEntry *info)
|
||||
_shell_app_new (GDesktopAppInfo *info)
|
||||
{
|
||||
ShellApp *app;
|
||||
|
||||
app = g_object_new (SHELL_TYPE_APP, NULL);
|
||||
|
||||
_shell_app_set_entry (app, info);
|
||||
_shell_app_set_app_info (app, info);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void
|
||||
_shell_app_set_entry (ShellApp *app,
|
||||
GMenuTreeEntry *entry)
|
||||
_shell_app_set_app_info (ShellApp *app,
|
||||
GDesktopAppInfo *info)
|
||||
{
|
||||
if (app->entry != NULL)
|
||||
gmenu_tree_item_unref (app->entry);
|
||||
app->entry = gmenu_tree_item_ref (entry);
|
||||
|
||||
g_clear_object (&app->info);
|
||||
app->info = g_object_ref (info);
|
||||
|
||||
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);
|
||||
@ -1172,40 +1167,50 @@ _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 (startup_id)
|
||||
*startup_id = NULL;
|
||||
|
||||
if (app->entry == NULL)
|
||||
if (app->info == 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;
|
||||
}
|
||||
@ -1224,11 +1229,14 @@ shell_app_launch (ShellApp *app,
|
||||
gdk_app_launch_context_set_timestamp (context, timestamp);
|
||||
gdk_app_launch_context_set_desktop (context, workspace);
|
||||
|
||||
gapp = gmenu_tree_entry_get_app_info (app->entry);
|
||||
ret = g_desktop_app_info_launch_uris_as_manager (gapp, uris,
|
||||
ret = g_desktop_app_info_launch_uris_as_manager (app->info, NULL,
|
||||
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);
|
||||
@ -1245,21 +1253,7 @@ shell_app_launch (ShellApp *app,
|
||||
GDesktopAppInfo *
|
||||
shell_app_get_app_info (ShellApp *app)
|
||||
{
|
||||
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;
|
||||
return app->info;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1374,24 +1368,22 @@ shell_app_init_search_data (ShellApp *app)
|
||||
const char *exec;
|
||||
const char * const *keywords;
|
||||
char *normalized_exec;
|
||||
GDesktopAppInfo *appinfo;
|
||||
|
||||
appinfo = gmenu_tree_entry_get_app_info (app->entry);
|
||||
name = g_app_info_get_name (G_APP_INFO (appinfo));
|
||||
name = g_app_info_get_name (G_APP_INFO (app->info));
|
||||
app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name);
|
||||
|
||||
generic_name = g_desktop_app_info_get_generic_name (appinfo);
|
||||
generic_name = g_desktop_app_info_get_generic_name (app->info);
|
||||
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 (appinfo));
|
||||
exec = g_app_info_get_executable (G_APP_INFO (app->info));
|
||||
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 (appinfo);
|
||||
keywords = g_desktop_app_info_get_keywords (app->info);
|
||||
|
||||
if (keywords)
|
||||
{
|
||||
@ -1512,16 +1504,14 @@ _shell_app_do_match (ShellApp *app,
|
||||
GSList **substring_results)
|
||||
{
|
||||
ShellAppSearchMatch match;
|
||||
GAppInfo *appinfo;
|
||||
|
||||
g_assert (app != NULL);
|
||||
|
||||
/* Skip window-backed apps */
|
||||
appinfo = (GAppInfo*)shell_app_get_app_info (app);
|
||||
if (appinfo == NULL)
|
||||
if (app->info == NULL)
|
||||
return;
|
||||
/* Skip not-visible apps */
|
||||
if (!g_app_info_should_show (appinfo))
|
||||
if (!g_app_info_should_show (G_APP_INFO (app->info)))
|
||||
return;
|
||||
|
||||
match = _shell_app_match_search_terms (app, terms);
|
||||
@ -1550,11 +1540,7 @@ shell_app_dispose (GObject *object)
|
||||
{
|
||||
ShellApp *app = SHELL_APP (object);
|
||||
|
||||
if (app->entry)
|
||||
{
|
||||
gmenu_tree_item_unref (app->entry);
|
||||
app->entry = NULL;
|
||||
}
|
||||
g_clear_object (&app->info);
|
||||
|
||||
if (app->running_state)
|
||||
{
|
||||
|
@ -4,9 +4,8 @@
|
||||
|
||||
#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
|
||||
|
||||
@ -39,7 +38,6 @@ 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);
|
||||
@ -73,9 +71,7 @@ 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);
|
||||
|
@ -22,7 +22,6 @@
|
||||
#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>
|
||||
@ -34,6 +33,11 @@
|
||||
#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"
|
||||
@ -80,10 +84,11 @@ struct _ShellGlobal {
|
||||
const char *datadir;
|
||||
const char *imagedir;
|
||||
const char *userdatadir;
|
||||
StFocusManager *focus_manager;
|
||||
|
||||
GFile *userdatadir_path;
|
||||
GFile *runtime_state_path;
|
||||
|
||||
StFocusManager *focus_manager;
|
||||
|
||||
guint work_count;
|
||||
GSList *leisure_closures;
|
||||
guint leisure_function_id;
|
||||
@ -252,6 +257,7 @@ 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";
|
||||
@ -282,9 +288,16 @@ shell_global_init (ShellGlobal *global)
|
||||
NULL);
|
||||
ca_context_open (global->sound_context);
|
||||
|
||||
if (!shell_js)
|
||||
shell_js = JSDIR;
|
||||
search_path = g_strsplit (shell_js, ":", -1);
|
||||
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");
|
||||
}
|
||||
|
||||
global->js_context = g_object_new (GJS_TYPE_CONTEXT,
|
||||
"search-path", search_path,
|
||||
"js-version", "1.8",
|
||||
@ -306,6 +319,7 @@ 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);
|
||||
@ -1100,20 +1114,30 @@ shell_global_reexec_self (ShellGlobal *global)
|
||||
char *buf_p;
|
||||
char *buf_end;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Linux specific (I think, anyways). */
|
||||
|
||||
#if defined __linux__
|
||||
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
|
||||
@ -1139,44 +1163,6 @@ 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
|
||||
@ -1746,31 +1732,14 @@ shell_global_get_session_mode (ShellGlobal *global)
|
||||
return global->session_mode;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
get_runtime_state_path (ShellGlobal *global,
|
||||
const char *property_name)
|
||||
static void
|
||||
save_variant (GFile *dir,
|
||||
const char *property_name,
|
||||
GVariant *variant)
|
||||
{
|
||||
return g_file_get_child (global->runtime_state_path, property_name);
|
||||
}
|
||||
GFile *path = g_file_get_child (dir, property_name);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
if (variant == NULL || g_variant_get_data (variant) == NULL)
|
||||
(void) g_file_delete (path, NULL, NULL);
|
||||
else
|
||||
{
|
||||
@ -1783,29 +1752,17 @@ shell_global_set_runtime_state (ShellGlobal *global,
|
||||
g_object_unref (path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static GVariant *
|
||||
load_variant (GFile *dir,
|
||||
const char *property_type,
|
||||
const char *property_name)
|
||||
{
|
||||
GVariant *res = NULL;
|
||||
GMappedFile *mfile;
|
||||
GFile *path;
|
||||
GFile *path = g_file_get_child (dir, property_name);
|
||||
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)
|
||||
@ -1829,3 +1786,73 @@ shell_global_get_runtime_state (ShellGlobal *global,
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -69,10 +69,6 @@ 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);
|
||||
@ -129,13 +125,19 @@ 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
|
||||
|
||||
|
@ -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 = gjs_context_get_native_context (contexts->data);
|
||||
context = (JSContext*) gjs_context_get_native_context ((GjsContext*)contexts->data);
|
||||
g_list_free_full (contexts, g_object_unref);
|
||||
|
||||
JS_BeginRequest (context);
|
@ -844,6 +844,7 @@ ShellApp *
|
||||
shell_startup_sequence_get_app (ShellStartupSequence *sequence)
|
||||
{
|
||||
const char *appid;
|
||||
char *basename;
|
||||
ShellAppSystem *appsys;
|
||||
ShellApp *app;
|
||||
|
||||
@ -851,8 +852,10 @@ 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_for_path (appsys, appid);
|
||||
app = shell_app_system_lookup_app (appsys, basename);
|
||||
g_free (basename);
|
||||
return app;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ struct _StAdjustmentPrivate
|
||||
{
|
||||
/* Do not sanity-check values while constructing,
|
||||
* not all properties may be set yet. */
|
||||
gboolean is_constructing : 1;
|
||||
guint is_constructing : 1;
|
||||
|
||||
gdouble lower;
|
||||
gdouble upper;
|
||||
|
@ -98,8 +98,8 @@ struct _StScrollViewPrivate
|
||||
|
||||
StScrollViewFade *fade_effect;
|
||||
|
||||
gboolean row_size_set : 1;
|
||||
gboolean column_size_set : 1;
|
||||
guint row_size_set : 1;
|
||||
guint column_size_set : 1;
|
||||
guint mouse_scroll : 1;
|
||||
guint overlay_scrollbars : 1;
|
||||
guint hscrollbar_visible : 1;
|
||||
|
@ -45,10 +45,7 @@
|
||||
#include "st-theme-node.h"
|
||||
#include "st-theme-private.h"
|
||||
|
||||
static GObject *st_theme_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties);
|
||||
|
||||
static void st_theme_constructed (GObject *object);
|
||||
static void st_theme_finalize (GObject *object);
|
||||
static void st_theme_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -114,7 +111,7 @@ st_theme_class_init (StThemeClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructor = st_theme_constructor;
|
||||
object_class->constructed = st_theme_constructed;
|
||||
object_class->finalize = st_theme_finalize;
|
||||
object_class->set_property = st_theme_set_property;
|
||||
object_class->get_property = st_theme_get_property;
|
||||
@ -302,21 +299,15 @@ st_theme_get_custom_stylesheets (StTheme *theme)
|
||||
return result;
|
||||
}
|
||||
|
||||
static GObject *
|
||||
st_theme_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
static void
|
||||
st_theme_constructed (GObject *object)
|
||||
{
|
||||
GObject *object;
|
||||
StTheme *theme;
|
||||
StTheme *theme = ST_THEME (object);
|
||||
CRStyleSheet *application_stylesheet;
|
||||
CRStyleSheet *theme_stylesheet;
|
||||
CRStyleSheet *default_stylesheet;
|
||||
|
||||
object = (*G_OBJECT_CLASS (st_theme_parent_class)->constructor) (type,
|
||||
n_construct_properties,
|
||||
construct_properties);
|
||||
theme = ST_THEME (object);
|
||||
G_OBJECT_CLASS (st_theme_parent_class)->constructed (object);
|
||||
|
||||
application_stylesheet = parse_stylesheet_nofail (theme->application_stylesheet);
|
||||
theme_stylesheet = parse_stylesheet_nofail (theme->theme_stylesheet);
|
||||
@ -332,8 +323,6 @@ st_theme_constructor (GType type,
|
||||
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
|
||||
|
@ -59,13 +59,12 @@ struct _StWidgetPrivate
|
||||
|
||||
StThemeNodeTransition *transition_animation;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
gulong texture_file_changed_id;
|
||||
|
||||
@ -105,7 +104,6 @@ enum
|
||||
PROP_PSEUDO_CLASS,
|
||||
PROP_STYLE_CLASS,
|
||||
PROP_STYLE,
|
||||
PROP_STYLABLE,
|
||||
PROP_TRACK_HOVER,
|
||||
PROP_HOVER,
|
||||
PROP_CAN_FOCUS,
|
||||
@ -164,14 +162,6 @@ 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;
|
||||
@ -229,10 +219,6 @@ 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;
|
||||
@ -338,17 +324,8 @@ st_widget_dispose (GObject *gobject)
|
||||
StWidget *actor = ST_WIDGET (gobject);
|
||||
StWidgetPrivate *priv = ST_WIDGET (actor)->priv;
|
||||
|
||||
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;
|
||||
}
|
||||
g_clear_pointer (&priv->theme, g_object_unref);
|
||||
g_clear_pointer (&priv->theme_node, g_object_unref);
|
||||
|
||||
st_widget_remove_transition (actor);
|
||||
|
||||
@ -358,11 +335,7 @@ st_widget_dispose (GObject *gobject)
|
||||
if (priv->accessible)
|
||||
priv->accessible = NULL;
|
||||
|
||||
if (priv->label_actor)
|
||||
{
|
||||
g_object_unref (priv->label_actor);
|
||||
priv->label_actor = NULL;
|
||||
}
|
||||
g_clear_pointer (&priv->label_actor, g_object_unref);
|
||||
|
||||
if (priv->texture_file_changed_id != 0)
|
||||
{
|
||||
@ -551,12 +524,6 @@ 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);
|
||||
}
|
||||
@ -942,20 +909,6 @@ 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:
|
||||
*
|
||||
@ -1546,7 +1499,6 @@ 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 ();
|
||||
|
||||
|
Reference in New Issue
Block a user