Compare commits
39 Commits
2.31.2
...
shell-tool
Author | SHA1 | Date | |
---|---|---|---|
83f37da1c1 | |||
c2706add36 | |||
0a187b7222 | |||
3abe92d15d | |||
45b4d0384c | |||
083eed140c | |||
1283f0b160 | |||
3bbdc1e1e1 | |||
25f1246b6f | |||
a37c86636b | |||
4057cfaa17 | |||
76443e91cd | |||
d3c4c1f5ed | |||
040ddf077c | |||
f313d38458 | |||
304b48a15d | |||
d92b1d8da2 | |||
df3ac4b25e | |||
0ce05a04c8 | |||
c1c4adda02 | |||
595242c389 | |||
7e678ef0d2 | |||
ebbf304899 | |||
2077485827 | |||
0c0a0c66e2 | |||
2412a89445 | |||
789e268264 | |||
7507d10223 | |||
b18a8ebcae | |||
ed07413c20 | |||
f94eab803b | |||
0315a6e4a8 | |||
48085dd428 | |||
099b73a0c4 | |||
b8d46422d5 | |||
459bdfba78 | |||
66414ea3f6 | |||
d453067e24 | |||
ae320a26fc |
8
.gitignore
vendored
@ -18,16 +18,12 @@ config
|
|||||||
configure
|
configure
|
||||||
data/gnome-shell.desktop
|
data/gnome-shell.desktop
|
||||||
data/gnome-shell.desktop.in
|
data/gnome-shell.desktop.in
|
||||||
data/gnome-shell-clock-preferences.desktop
|
|
||||||
data/gnome-shell-clock-preferences.desktop.in
|
|
||||||
intltool-extract.in
|
intltool-extract.in
|
||||||
intltool-merge.in
|
intltool-merge.in
|
||||||
intltool-update.in
|
intltool-update.in
|
||||||
libtool
|
libtool
|
||||||
m4/
|
|
||||||
omf.make
|
omf.make
|
||||||
po/*.gmo
|
po/*.gmo
|
||||||
po/gnome-shell.pot
|
|
||||||
po/Makefile.in.in
|
po/Makefile.in.in
|
||||||
po/POTFILES
|
po/POTFILES
|
||||||
po/stamp-it
|
po/stamp-it
|
||||||
@ -40,13 +36,9 @@ src/Makefile
|
|||||||
src/Makefile.in
|
src/Makefile.in
|
||||||
src/gnomeshell-taskpanel
|
src/gnomeshell-taskpanel
|
||||||
src/gnome-shell
|
src/gnome-shell
|
||||||
src/gnome-shell-clock-preferences
|
|
||||||
src/test-recorder
|
src/test-recorder
|
||||||
src/test-recorder.ogg
|
src/test-recorder.ogg
|
||||||
src/test-theme
|
src/test-theme
|
||||||
src/st.h
|
|
||||||
stamp-h1
|
stamp-h1
|
||||||
tests/run-test.sh
|
tests/run-test.sh
|
||||||
xmldocs.make
|
xmldocs.make
|
||||||
*~
|
|
||||||
*.patch
|
|
||||||
|
20
Makefile.am
@ -1,13 +1,9 @@
|
|||||||
# Point to our macro directory and pick up user flags from the environment
|
SUBDIRS = data js src tests po
|
||||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
|
||||||
|
|
||||||
SUBDIRS = data js src tests po man
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
.project \
|
.project \
|
||||||
.settings \
|
.settings \
|
||||||
autogen.sh \
|
autogen.sh
|
||||||
tools/check-for-missing.py
|
|
||||||
|
|
||||||
# These are files checked into Git that we don't want to distribute
|
# These are files checked into Git that we don't want to distribute
|
||||||
DIST_EXCLUDE = \
|
DIST_EXCLUDE = \
|
||||||
@ -18,4 +14,14 @@ DIST_EXCLUDE = \
|
|||||||
|
|
||||||
distcheck-hook:
|
distcheck-hook:
|
||||||
@echo "Checking disted files against files in git"
|
@echo "Checking disted files against files in git"
|
||||||
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
|
@failed=false; \
|
||||||
|
exclude=`(for p in $(DIST_EXCLUDE) ; do echo --exclude=$$p ; done)`; \
|
||||||
|
for f in `cd $(srcdir) && git ls-files $$exclude` ; do \
|
||||||
|
if ! test -e $(distdir)/$$f ; then \
|
||||||
|
echo File missing from distribution: $$f ; \
|
||||||
|
failed=true ; \
|
||||||
|
fi \
|
||||||
|
done ; \
|
||||||
|
if $$failed ; then \
|
||||||
|
exit 1 ; \
|
||||||
|
fi
|
||||||
|
@ -5,6 +5,7 @@ srcdir=`dirname $0`
|
|||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
|
||||||
PKG_NAME="gnome-shell"
|
PKG_NAME="gnome-shell"
|
||||||
|
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||||
|
|
||||||
(test -f $srcdir/configure.ac \
|
(test -f $srcdir/configure.ac \
|
||||||
&& test -d $srcdir/src) || {
|
&& test -d $srcdir/src) || {
|
||||||
@ -14,7 +15,7 @@ PKG_NAME="gnome-shell"
|
|||||||
}
|
}
|
||||||
|
|
||||||
which gnome-autogen.sh || {
|
which gnome-autogen.sh || {
|
||||||
echo "You need to install gnome-common from GNOME Git (or from"
|
echo "You need to install gnome-common from GNOME Subversion (or from"
|
||||||
echo "your OS vendor's package manager)."
|
echo "your OS vendor's package manager)."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
73
configure.ac
@ -1,35 +1,30 @@
|
|||||||
AC_PREREQ(2.63)
|
AC_INIT(gnome-shell, 2.27.3)
|
||||||
AC_INIT([gnome-shell],[2.31.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_AUX_DIR(config)
|
||||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
AC_CONFIG_AUX_DIR([config])
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
|
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign])
|
||||||
AM_MAINTAINER_MODE
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||||
|
|
||||||
# Checks for programs.
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
|
||||||
|
AC_DISABLE_STATIC
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
# Needed for per-target cflags, like in gnomeshell-taskpanel
|
# Needed for per-target cflags, like in gnomeshell-taskpanel
|
||||||
AM_PROG_CC_C_O
|
AM_PROG_CC_C_O
|
||||||
|
AM_PROG_LIBTOOL
|
||||||
# Initialize libtool
|
|
||||||
LT_PREREQ([2.2.6])
|
|
||||||
LT_INIT([disable-static])
|
|
||||||
|
|
||||||
GETTEXT_PACKAGE=gnome-shell
|
GETTEXT_PACKAGE=gnome-shell
|
||||||
AC_SUBST(GETTEXT_PACKAGE)
|
AC_SUBST(GETTEXT_PACKAGE)
|
||||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
||||||
[The prefix for our gettext translation domains.])
|
[The prefix for our gettext translation domains.])
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG(0.16)
|
||||||
|
|
||||||
IT_PROG_INTLTOOL(0.26)
|
IT_PROG_INTLTOOL(0.26)
|
||||||
AM_GLIB_GNU_GETTEXT
|
AM_GLIB_GNU_GETTEXT
|
||||||
|
|
||||||
PKG_PROG_PKG_CONFIG([0.22])
|
|
||||||
|
|
||||||
# GConf stuff
|
|
||||||
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
||||||
AM_GCONF_SOURCE_2
|
AM_GCONF_SOURCE_2
|
||||||
|
|
||||||
@ -55,36 +50,15 @@ fi
|
|||||||
|
|
||||||
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||||
|
|
||||||
CLUTTER_MIN_VERSION=1.2.8
|
|
||||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.6.11
|
|
||||||
GJS_MIN_VERSION=0.7
|
|
||||||
MUTTER_MIN_VERSION=2.31.2
|
|
||||||
GTK_MIN_VERSION=2.18.0
|
|
||||||
|
|
||||||
# Collect more than 20 libraries for a prize!
|
# Collect more than 20 libraries for a prize!
|
||||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 dbus-glib-1
|
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins
|
||||||
gtk+-2.0 >= $GTK_MIN_VERSION
|
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
|
||||||
mutter-plugins >= $MUTTER_MIN_VERSION
|
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
|
||||||
gjs-gi-1.0 >= $GJS_MIN_VERSION
|
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
||||||
libgnome-menu $recorder_modules gconf-2.0
|
gobject-introspection-1.0 >= 0.6.5)
|
||||||
gdk-x11-2.0
|
|
||||||
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
|
|
||||||
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
|
|
||||||
libstartup-notification-1.0
|
|
||||||
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION)
|
|
||||||
|
|
||||||
# This is for the newly added application id bits, we can replace this with
|
|
||||||
# a version check later
|
|
||||||
saved_CFLAGS=$CFLAGS
|
|
||||||
saved_LIBS=$LIBS
|
|
||||||
CFLAGS=$MUTTER_PLUGIN_CFLAGS
|
|
||||||
LIBS=$MUTTER_PLUGIN_LIBS
|
|
||||||
AC_CHECK_FUNCS(sn_startup_sequence_get_application_id)
|
|
||||||
CFLAGS=$saved_CFLAGS
|
|
||||||
LIBS=$saved_LIBS
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libcroco-0.6 gnome-desktop-2.0 >= 2.26)
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1 libcroco-0.6)
|
||||||
|
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
||||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
|
|
||||||
@ -98,10 +72,8 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
|
|||||||
|
|
||||||
GJS_JS_DIR=`$PKG_CONFIG --variable=jsdir gjs-1.0`
|
GJS_JS_DIR=`$PKG_CONFIG --variable=jsdir gjs-1.0`
|
||||||
GJS_JS_NATIVE_DIR=`$PKG_CONFIG --variable=jsnativedir gjs-1.0`
|
GJS_JS_NATIVE_DIR=`$PKG_CONFIG --variable=jsnativedir gjs-1.0`
|
||||||
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
|
|
||||||
AC_SUBST(GJS_JS_DIR)
|
AC_SUBST(GJS_JS_DIR)
|
||||||
AC_SUBST(GJS_JS_NATIVE_DIR)
|
AC_SUBST(GJS_JS_NATIVE_DIR)
|
||||||
AC_SUBST(GJS_CONSOLE)
|
|
||||||
|
|
||||||
AC_CHECK_FUNCS(fdwalk)
|
AC_CHECK_FUNCS(fdwalk)
|
||||||
AC_CHECK_HEADERS([sys/resource.h])
|
AC_CHECK_HEADERS([sys/resource.h])
|
||||||
@ -122,7 +94,8 @@ AC_SUBST(TYPELIBDIR)
|
|||||||
# Stay command-line compatible with the gnome-common configure option. Here
|
# Stay command-line compatible with the gnome-common configure option. Here
|
||||||
# minimum/yes/maximum are the same, however.
|
# minimum/yes/maximum are the same, however.
|
||||||
AC_ARG_ENABLE(compile_warnings,
|
AC_ARG_ENABLE(compile_warnings,
|
||||||
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
|
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
|
||||||
|
[Turn on compiler warnings]),,
|
||||||
enable_compile_warnings=error)
|
enable_compile_warnings=error)
|
||||||
|
|
||||||
changequote(,)dnl
|
changequote(,)dnl
|
||||||
@ -149,17 +122,13 @@ changequote([,])dnl
|
|||||||
AC_PATH_PROG(mutter, [mutter])
|
AC_PATH_PROG(mutter, [mutter])
|
||||||
AC_SUBST(mutter)
|
AC_SUBST(mutter)
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_OUTPUT([
|
||||||
Makefile
|
Makefile
|
||||||
data/Makefile
|
data/Makefile
|
||||||
js/Makefile
|
js/Makefile
|
||||||
js/misc/Makefile
|
js/misc/Makefile
|
||||||
js/ui/Makefile
|
js/ui/Makefile
|
||||||
js/perf/Makefile
|
|
||||||
js/prefs/Makefile
|
|
||||||
src/Makefile
|
src/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
po/Makefile.in
|
po/Makefile.in
|
||||||
man/Makefile
|
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
|
||||||
|
@ -1,50 +1,36 @@
|
|||||||
desktopdir=$(datadir)/applications
|
desktopdir=$(datadir)/applications
|
||||||
desktop_DATA = gnome-shell.desktop gnome-shell-clock-preferences.desktop
|
desktop_DATA = gnome-shell.desktop
|
||||||
|
|
||||||
# We substitute in bindir so it works as an autostart
|
# We substitute in bindir so it works as an autostart
|
||||||
# file when built in a non-system prefix
|
# file when built in a non-system prefix
|
||||||
%.desktop.in:%.desktop.in.in
|
gnome-shell.desktop.in: gnome-shell.desktop.in.in
|
||||||
$(AM_V_GEN) sed -e "s|@bindir[@]|$(bindir)|" \
|
$(AM_V_GEN) sed -e "s|@bindir[@]|$(bindir)|" \
|
||||||
-e "s|@VERSION[@]|$(VERSION)|" \
|
-e "s|@VERSION[@]|$(VERSION)|" \
|
||||||
$< > $@ || rm $@
|
$< > $@ || rm $@
|
||||||
|
|
||||||
# Placeholder until we add intltool
|
# Placeholder until we add intltool
|
||||||
%.desktop:%.desktop.in
|
gnome-shell.desktop: gnome-shell.desktop.in
|
||||||
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
||||||
|
|
||||||
dist_pkgdata_DATA = clock-preferences.ui
|
|
||||||
|
|
||||||
imagesdir = $(pkgdatadir)/images
|
imagesdir = $(pkgdatadir)/images
|
||||||
dist_images_DATA = \
|
dist_images_DATA = \
|
||||||
|
add-workspace.svg \
|
||||||
|
app-well-glow.png \
|
||||||
|
back.svg \
|
||||||
|
close.svg \
|
||||||
close-black.svg \
|
close-black.svg \
|
||||||
magnifier.svg
|
info.svg \
|
||||||
|
magnifier.svg \
|
||||||
|
remove-workspace.svg
|
||||||
|
|
||||||
themedir = $(pkgdatadir)/theme
|
themedir = $(pkgdatadir)/theme
|
||||||
dist_theme_DATA = \
|
dist_theme_DATA = \
|
||||||
theme/add-workspace.svg \
|
|
||||||
theme/close-window.svg \
|
|
||||||
theme/close.svg \
|
|
||||||
theme/corner-ripple.png \
|
|
||||||
theme/dialog-error.svg \
|
|
||||||
theme/gnome-shell.css \
|
theme/gnome-shell.css \
|
||||||
theme/mosaic-view-active.svg \
|
|
||||||
theme/mosaic-view.svg \
|
|
||||||
theme/move-window-on-new.svg \
|
|
||||||
theme/remove-workspace.svg \
|
|
||||||
theme/scroll-button-down-hover.png \
|
|
||||||
theme/scroll-button-down.png \
|
theme/scroll-button-down.png \
|
||||||
theme/scroll-button-up-hover.png \
|
theme/scroll-button-down-hover.png \
|
||||||
theme/scroll-button-up.png \
|
theme/scroll-button-up.png \
|
||||||
theme/scroll-hhandle.svg \
|
theme/scroll-button-up-hover.png \
|
||||||
theme/scroll-vhandle.svg \
|
theme/scroll-vhandle.png
|
||||||
theme/section-back.svg \
|
|
||||||
theme/section-more.svg \
|
|
||||||
theme/section-more-open.svg \
|
|
||||||
theme/single-view-active.svg \
|
|
||||||
theme/single-view.svg \
|
|
||||||
theme/ws-switch-arrow-left.svg \
|
|
||||||
theme/ws-switch-arrow-right.svg
|
|
||||||
|
|
||||||
|
|
||||||
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||||
schema_DATA = gnome-shell.schemas
|
schema_DATA = gnome-shell.schemas
|
||||||
@ -52,13 +38,11 @@ schema_DATA = gnome-shell.schemas
|
|||||||
install-data-local:
|
install-data-local:
|
||||||
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(schema_DATA)
|
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(schema_DATA)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
gnome-shell.desktop.in.in \
|
gnome-shell.desktop.in.in \
|
||||||
gnome-shell-clock-preferences.desktop.in.in \
|
|
||||||
$(schema_DATA)
|
$(schema_DATA)
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
gnome-shell.desktop.in \
|
gnome-shell.desktop.in \
|
||||||
gnome-shell-clock-preferences.desktop.in \
|
|
||||||
$(desktop_DATA)
|
$(desktop_DATA)
|
||||||
|
|
||||||
|
70
data/add-workspace.svg
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="59.995201"
|
||||||
|
height="59.995102"
|
||||||
|
id="svg3113"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
version="1.0"
|
||||||
|
sodipodi:docname="add-workspace.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||||
|
<defs
|
||||||
|
id="defs3115">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
id="perspective3121" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.35"
|
||||||
|
inkscape:cx="375"
|
||||||
|
inkscape:cy="520"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="641"
|
||||||
|
inkscape:window-height="683"
|
||||||
|
inkscape:window-x="4"
|
||||||
|
inkscape:window-y="54" />
|
||||||
|
<metadata
|
||||||
|
id="metadata3118">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-498.57383,-439.50749)">
|
||||||
|
<path
|
||||||
|
id="path3269"
|
||||||
|
d="M 528.57143,439.91129 C 512.23433,439.91129 498.97763,453.16795 498.97763,469.50504 C 498.97763,485.84214 512.23433,499.09881 528.57143,499.09879 C 544.90853,499.09879 558.16513,485.84215 558.16523,469.50504 C 558.16523,453.16794 544.90853,439.9113 528.57143,439.91129 z M 525.29023,451.16129 L 531.88393,451.16129 C 533.75363,451.16129 535.25893,452.66659 535.25893,454.53629 L 535.25893,462.84879 L 543.54023,462.84879 C 545.40973,462.84879 546.91523,464.35409 546.91523,466.22379 L 546.91523,472.81754 C 546.91523,474.68728 545.40993,476.19255 543.54023,476.19254 L 535.25893,476.19254 L 535.25893,484.47379 C 535.25893,486.34353 533.75363,487.8488 531.88393,487.84879 L 525.29023,487.84879 C 523.42053,487.84881 521.91523,486.34351 521.91523,484.47379 L 521.91523,476.19254 L 513.60263,476.19254 C 511.73313,476.19257 510.22773,474.68726 510.22763,472.81754 L 510.22763,466.22379 C 510.22763,464.35407 511.73303,462.8488 513.60263,462.84879 L 521.91523,462.84879 L 521.91523,454.53629 C 521.91523,452.66657 523.42043,451.1613 525.29023,451.16129 z"
|
||||||
|
style="opacity:0.30701785;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.807603px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
BIN
data/app-well-glow.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@ -1,188 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<interface>
|
|
||||||
<requires lib="gtk+" version="2.16"/>
|
|
||||||
<!-- interface-naming-policy project-wide -->
|
|
||||||
<object class="GtkDialog" id="prefs-dialog">
|
|
||||||
<property name="border_width">5</property>
|
|
||||||
<property name="title" translatable="yes">Clock Preferences</property>
|
|
||||||
<property name="window_position">center</property>
|
|
||||||
<property name="type_hint">normal</property>
|
|
||||||
<property name="has_separator">False</property>
|
|
||||||
<child internal-child="vbox">
|
|
||||||
<object class="GtkVBox" id="dialog-vbox1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="spacing">2</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkVBox" id="vbox1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="spacing">18</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkFrame" id="frame1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">none</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkAlignment" id="alignment1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="top_padding">6</property>
|
|
||||||
<property name="left_padding">12</property>
|
|
||||||
<property name="right_padding">6</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkHBox" id="hbox1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="spacing">12</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkRadioButton" id="12hr_radio">
|
|
||||||
<property name="label" translatable="yes">_12 hour format</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkRadioButton" id="24hr_radio">
|
|
||||||
<property name="label" translatable="yes">_24 hour format</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
|
||||||
<property name="group">12hr_radio</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child type="label">
|
|
||||||
<object class="GtkLabel" id="label_format">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="label" translatable="yes">Clock Format</property>
|
|
||||||
<attributes>
|
|
||||||
<attribute name="weight" value="bold"/>
|
|
||||||
</attributes>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkFrame" id="frame2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="label_xalign">0</property>
|
|
||||||
<property name="shadow_type">none</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkAlignment" id="alignment2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="top_padding">6</property>
|
|
||||||
<property name="left_padding">12</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkVBox" id="vbox2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="spacing">6</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkCheckButton" id="date_check">
|
|
||||||
<property name="label" translatable="yes">Show the _date</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkCheckButton" id="seconds_check">
|
|
||||||
<property name="label" translatable="yes">Show seco_nds</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child type="label">
|
|
||||||
<object class="GtkLabel" id="label_display">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="label" translatable="yes">Panel Display</property>
|
|
||||||
<attributes>
|
|
||||||
<attribute name="weight" value="bold"/>
|
|
||||||
</attributes>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="padding">6</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child internal-child="action_area">
|
|
||||||
<object class="GtkHButtonBox" id="dialog-action_area1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="layout_style">end</property>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="prefs_close_button">
|
|
||||||
<property name="label">gtk-close</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
<property name="use_stock">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="pack_type">end</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<action-widgets>
|
|
||||||
<action-widget response="0">prefs_close_button</action-widget>
|
|
||||||
</action-widgets>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
@ -62,5 +62,5 @@
|
|||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
d="M10.5,3.5l2,2L10,8l2.5,2.5l-2,2L8,10l-2.5,2.5l-2-2L6,8L3.5,5.5l2-2L8,6L10.5,3.5 z M0,8c0-4.418,3.582-8,8-8s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
|
d="M10.5,3.5l2,2L10,8l2.5,2.5l-2,2L8,10l-2.5,2.5l-2-2L6,8L3.5,5.5l2-2L8,6L10.5,3.5 z M0,8c0-4.418,3.582-8,8-8s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
|
||||||
id="path2394"
|
id="path2394"
|
||||||
style="fill-opacity:1;fill:#545454" />
|
style="fill-opacity:1;fill:#000000" />
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -1,15 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
_Name=Clock
|
|
||||||
_Comment=Customize the panel clock
|
|
||||||
Exec=@bindir@/gnome-shell-clock-preferences
|
|
||||||
Icon=gnome-panel-clock
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
StartupNotify=true
|
|
||||||
Categories=GNOME;GTK;Settings;DesktopSettings;
|
|
||||||
OnlyShowIn=GNOME;
|
|
||||||
X-GNOME-ShellOnly=true
|
|
||||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
|
||||||
X-GNOME-Bugzilla-Product=gnome-shell
|
|
||||||
X-GNOME-Bugzilla-Component=general
|
|
||||||
X-GNOME-Bugzilla-Version=@VERSION@
|
|
@ -46,398 +46,48 @@
|
|||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema>
|
<schema>
|
||||||
<key>/schemas/desktop/gnome/shell/run_dialog/history</key>
|
<key>/schemas/desktop/gnome/shell/sidebar/visible</key>
|
||||||
<applyto>/desktop/gnome/shell/run_dialog/history</applyto>
|
<applyto>/desktop/gnome/shell/sidebar/visible</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>false</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Whether or not to display the sidebar</short>
|
||||||
|
<long>
|
||||||
|
Determines whether or not the sidebar is visible.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/sidebar/expanded</key>
|
||||||
|
<applyto>/desktop/gnome/shell/sidebar/expanded</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>true</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Whether the sidebar should be in the expanded (wide) mode</short>
|
||||||
|
<long>
|
||||||
|
Controls the expanded/collapsed state of the sidebar.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/sidebar/widgets</key>
|
||||||
|
<applyto>/desktop/gnome/shell/sidebar/widgets</applyto>
|
||||||
<owner>gnome-shell</owner>
|
<owner>gnome-shell</owner>
|
||||||
<type>list</type>
|
<type>list</type>
|
||||||
<list_type>string</list_type>
|
<list_type>string</list_type>
|
||||||
<default>[]</default>
|
<default>[imports.ui.widget.ClockWidget,imports.ui.widget.AppsWidget,imports.ui.widget.RecentDocsWidget]</default>
|
||||||
<locale name="C">
|
<locale name="C">
|
||||||
<short>History for command (Alt-F2) dialog</short>
|
<short>The widgets to display in the sidebar</short>
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/clock/format</key>
|
|
||||||
<applyto>/desktop/gnome/shell/clock/format</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default>
|
|
||||||
<!-- Translators:
|
|
||||||
This controls whether the GNOME panel clock should display time
|
|
||||||
in 24 hour mode or 12 hour mode by default. The only valid values
|
|
||||||
for this are "24-hour" and "12-hour".
|
|
||||||
If your locale uses 24 hour time notation, translate this to
|
|
||||||
"24-hour".
|
|
||||||
If your locale uses 12 hour time notation with am/pm, translate
|
|
||||||
this to "12-hour".
|
|
||||||
|
|
||||||
Do NOT translate this into anything else than "24-hour" or
|
|
||||||
"12-hour". For example, if you translate this to "24 sata" or
|
|
||||||
anything else that isn't "24-hour" or "12-hour", things will
|
|
||||||
not work.
|
|
||||||
-->
|
|
||||||
24-hour
|
|
||||||
</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Hour format</short>
|
|
||||||
<long>
|
<long>
|
||||||
This key specifies the hour format used by the panel clock.
|
The widgets to display in the sidebar, in order from top to bottom. Each widget "name" is actually a JavaScript expression referring to a widget constructor object.
|
||||||
Possible values are "12-hour", "24-hour", "unix" and "custom".
|
|
||||||
If set to "unix", the clock will display time in seconds since Epoch,
|
|
||||||
i.e. 1970-01-01.
|
|
||||||
If set to "custom", the clock will display time according to the format
|
|
||||||
specified in the custom_format key.
|
|
||||||
Note that if set to either "unix" or "custom", the show_date and
|
|
||||||
show_seconds keys are ignored.
|
|
||||||
</long>
|
</long>
|
||||||
</locale>
|
</locale>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/clock/custom_format</key>
|
|
||||||
<applyto>/desktop/gnome/shell/clock/custom_format</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default></default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Custom format of the clock</short>
|
|
||||||
<long>
|
|
||||||
This key specifies the format used by the panel clock when the
|
|
||||||
format key is set to "custom". You can use conversion specifiers
|
|
||||||
understood by strftime() to obtain a specific format. See the
|
|
||||||
strftime() manual for more information.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/clock/show_seconds</key>
|
|
||||||
<applyto>/desktop/gnome/shell/clock/show_seconds</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Show time with seconds</short>
|
|
||||||
<long>
|
|
||||||
If true and format is either "12-hour" or "24-hour",
|
|
||||||
display seconds in time.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/clock/show_date</key>
|
|
||||||
<applyto>/desktop/gnome/shell/clock/show_date</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Show date in clock</short>
|
|
||||||
<long>
|
|
||||||
If true and format is either "12-hour" or "24-hour",
|
|
||||||
display date in the clock, in addition to time.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/disabled_extensions</key>
|
|
||||||
<applyto>/desktop/gnome/shell/disabled_extensions</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>list</type>
|
|
||||||
<list_type>string</list_type>
|
|
||||||
<default>[]</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Uuids of extensions to disable</short>
|
|
||||||
<long>
|
|
||||||
GNOME Shell extensions have a uuid property; this key lists extensions which should not be loaded.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/recorder/framerate</key>
|
|
||||||
<applyto>/desktop/gnome/shell/recorder/framerate</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>15</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Framerate used for recording screencasts.</short>
|
|
||||||
<long>
|
|
||||||
The framerate of the resulting screencast recordered by GNOME Shell's screencast recorder in frames-per-second.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/recorder/pipeline</key>
|
|
||||||
<applyto>/desktop/gnome/shell/recorder/pipeline</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default></default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>The gstreamer pipeline used to encode the screencast</short>
|
|
||||||
<long>
|
|
||||||
Sets the GStreamer pipeline used to encode recordings. It follows the syntax used for gst-launch.
|
|
||||||
The pipeline should have an unconnected sink pad where the recorded video is recorded. It will
|
|
||||||
normally have a unconnected source pad; output from that pad will be written into the output file.
|
|
||||||
However the pipeline can also take care of its own output - this might be used to send the output to an icecast server via shout2send or similar.
|
|
||||||
When unset or set to an empty value, the default pipeline will be used. This is currently 'videorate ! theoraenc ! oggmux' and records to Ogg Theora.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/recorder/file_extension</key>
|
|
||||||
<applyto>/desktop/gnome/shell/recorder/file_extension</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default>ogv</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>File extension used for storing the screencast</short>
|
|
||||||
<long>
|
|
||||||
The filename for recorded screencasts will be a unique filename based on the current date, and use this extension.
|
|
||||||
It should be changed when recording to a different container format.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/overview/workspaces_view</key>
|
|
||||||
<applyto>/desktop/gnome/shell/overview/workspaces_view</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default>single</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Overview workspace view mode</short>
|
|
||||||
<long>
|
|
||||||
The selected workspace view mode in the overview.
|
|
||||||
Supported values are "single" and "grid".
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/shell/windows/button_layout</key>
|
|
||||||
<applyto>/desktop/gnome/shell/windows/button_layout</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default>:minimize,maximize,close</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Arrangement of buttons on the titlebar</short>
|
|
||||||
<long>
|
|
||||||
Arrangement of buttons on the titlebar. The
|
|
||||||
value should be a string, such as
|
|
||||||
"menu:minimize,maximize,spacer,close"; the colon separates the
|
|
||||||
left corner of the window from the right corner, and
|
|
||||||
the button names are comma-separated. Duplicate buttons
|
|
||||||
are not allowed. Unknown button names are silently ignored
|
|
||||||
so that buttons can be added in future gnome-shell versions
|
|
||||||
without breaking older versions.
|
|
||||||
A special spacer tag can be used to insert some space between
|
|
||||||
two adjacent buttons.
|
|
||||||
|
|
||||||
This key overrides /apps/metacity/general/button_layout when
|
|
||||||
running GNOME Shell.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<!-- Magnifier -->
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/show_magnifier</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/show_magnifier</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Show or hide the magnifier</short>
|
|
||||||
<long>
|
|
||||||
Show or hide the magnifier and all of its zoom regions.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/mouse_tracking</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/mouse_tracking</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>1</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Mouse Tracking Mode</short>
|
|
||||||
<long>
|
|
||||||
Determines the position of the magnified mouse image within
|
|
||||||
the magnified view and how it reacts to system mouse movement.
|
|
||||||
The values are 0 - none: no mouse tracking; 1 - centered: the
|
|
||||||
mouse image is displayed at the center of the zoom region
|
|
||||||
(which also represents the point under the system mouse) and the
|
|
||||||
magnified contents are scrolled as the system mouse moves; 2 -
|
|
||||||
proportional: the position of the magnified mouse in the zoom
|
|
||||||
region is proportionally the same as the position of the system
|
|
||||||
mouse on screen; or 3 - push: when the magnified mouse
|
|
||||||
intersects a boundary of the zoom region, the contents are
|
|
||||||
scrolled into view.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/screen_position</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/screen_position</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>3</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Screen position</short>
|
|
||||||
<long>
|
|
||||||
The magnified view either fills the entire screen (1), or
|
|
||||||
occupies the top-half (2), bottom-half (3), left-half (4), or
|
|
||||||
right-half (5) of the screen.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/mag_factor</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/mag_factor</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>float</type>
|
|
||||||
<default>2.0</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Magnification factor</short>
|
|
||||||
<long>
|
|
||||||
The power of the magnification. A value of 1.0 means no
|
|
||||||
magnification. A value of 2.0 doubles the size.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/lens_mode</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/lens_mode</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Enable lens mode</short>
|
|
||||||
<long>
|
|
||||||
Whether the magnified view should be centered over the location
|
|
||||||
of the system mouse and move with it.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/scroll_at_edges</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/scroll_at_edges</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Scroll magnified contents beyond the edges of the desktop</short>
|
|
||||||
<long>
|
|
||||||
For centered mouse tracking, when the system pointer is at
|
|
||||||
or near the edge of the screen, the magnified contents continue
|
|
||||||
to scroll such that the screen edge moves into the magnified
|
|
||||||
view.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<!-- Magnifier: Crosshairs -->
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/show_cross_hairs</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/show_cross_hairs</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Show or hide crosshairs</short>
|
|
||||||
<long>
|
|
||||||
Enables/disables display of crosshairs centered on the magnified mouse
|
|
||||||
sprite.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/cross_hairs_thickness</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/cross_hairs_thickness</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>8</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Thickness of the crosshairs</short>
|
|
||||||
<long>
|
|
||||||
Width of the vertical and horizontal lines that make up the
|
|
||||||
crosshairs.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/cross_hairs_color</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/cross_hairs_color</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>string</type>
|
|
||||||
<default>#ff0000</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Color of the crosshairs</short>
|
|
||||||
<long>
|
|
||||||
The color of the the vertical and horizontal lines that make up
|
|
||||||
the crosshairs.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/cross_hairs_opacity</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/cross_hairs_opacity</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>169</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Opacity of the crosshairs</short>
|
|
||||||
<long>
|
|
||||||
Determines the transparency of the crosshairs, from fully opaque
|
|
||||||
to fully transparent.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/cross_hairs_length</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/cross_hairs_length</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>4096</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Length of the crosshairs</short>
|
|
||||||
<long>
|
|
||||||
Determines the length of the vertical and horizontal lines that
|
|
||||||
make up the crosshairs.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/accessibility/magnifier/cross_hairs_clip</key>
|
|
||||||
<applyto>/desktop/gnome/accessibility/magnifier/cross_hairs_clip</applyto>
|
|
||||||
<owner>gnome-shell</owner>
|
|
||||||
<type>bool</type>
|
|
||||||
<default>false</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>Clip the crosshairs at the center</short>
|
|
||||||
<long>
|
|
||||||
Determines whether the crosshairs intersect the magnified mouse
|
|
||||||
sprite, or are clipped such that the ends of the horizontal
|
|
||||||
and vertical lines surround the mouse image.
|
|
||||||
</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
</schemalist>
|
</schemalist>
|
||||||
|
|
||||||
</gconfschemafile>
|
</gconfschemafile>
|
||||||
|
74
data/info.svg
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="Foreground"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
enable-background="new 0 0 16 16"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
sodipodi:docname="info_16.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||||
|
id="metadata2389"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs2387"><linearGradient
|
||||||
|
id="linearGradient3710"><stop
|
||||||
|
style="stop-color:#c4c4c4;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3712" /><stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3714" /></linearGradient><inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 8 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="16 : 8 : 1"
|
||||||
|
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
||||||
|
id="perspective2391" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3710"
|
||||||
|
id="linearGradient3716"
|
||||||
|
x1="7.9066148"
|
||||||
|
y1="15.937743"
|
||||||
|
x2="7.9377432"
|
||||||
|
y2="0.031128405"
|
||||||
|
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="713"
|
||||||
|
inkscape:window-width="722"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="32.125"
|
||||||
|
inkscape:cx="8"
|
||||||
|
inkscape:cy="8.154146"
|
||||||
|
inkscape:window-x="20"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:current-layer="Foreground" />
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M7,3h2v2H7V3z M5.5,12H7V8H5.5V7H9v5h1.5v1h-5V12z M0,8c0-4.418,3.582-8,8-8 s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
|
||||||
|
id="path2384"
|
||||||
|
style="fill-opacity:1;fill:url(#linearGradient3716)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
71
data/remove-workspace.svg
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="59.995201"
|
||||||
|
height="59.995102"
|
||||||
|
id="svg3113"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
version="1.0"
|
||||||
|
sodipodi:docname="remove-workspace.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||||
|
<defs
|
||||||
|
id="defs3115">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
id="perspective3121" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="4.5"
|
||||||
|
inkscape:cx="-8.1974244"
|
||||||
|
inkscape:cy="38.948933"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1400"
|
||||||
|
inkscape:window-height="971"
|
||||||
|
inkscape:window-x="454"
|
||||||
|
inkscape:window-y="105" />
|
||||||
|
<metadata
|
||||||
|
id="metadata3118">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-498.57383,-439.50749)">
|
||||||
|
<path
|
||||||
|
style="opacity:0.30701785;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.807603px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||||
|
d="M 30 0.40625 C 13.662899 0.40624999 0.40625 13.66291 0.40625 30 C 0.40624999 46.337101 13.6629 59.59377 30 59.59375 C 46.337099 59.593749 59.59365 46.33711 59.59375 30 C 59.59375 13.662901 46.3371 0.40626 30 0.40625 z M 15.03125 23.34375 L 44.96875 23.34375 C 46.83825 23.343751 48.34375 24.84905 48.34375 26.71875 L 48.34375 33.3125 C 48.34375 35.182239 46.83845 36.68751 44.96875 36.6875 L 15.03125 36.6875 C 13.16175 36.687529 11.65635 35.18222 11.65625 33.3125 L 11.65625 26.71875 C 11.65625 24.849031 13.16165 23.34376 15.03125 23.34375 z "
|
||||||
|
transform="translate(498.57383,439.50749)"
|
||||||
|
id="path2382" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
@ -1,98 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="23"
|
|
||||||
height="15"
|
|
||||||
id="svg6375"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47pre4 r22446"
|
|
||||||
sodipodi:docname="New document 13">
|
|
||||||
<defs
|
|
||||||
id="defs6377">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective6383" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective6366"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="11.197802"
|
|
||||||
inkscape:cx="16"
|
|
||||||
inkscape:cy="16"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata6380">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-17)">
|
|
||||||
<g
|
|
||||||
style="display:inline"
|
|
||||||
id="g6243"
|
|
||||||
transform="translate(-986.28859,-658.2796)">
|
|
||||||
<rect
|
|
||||||
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5318"
|
|
||||||
width="22"
|
|
||||||
height="14"
|
|
||||||
x="986.89801"
|
|
||||||
y="675.86743"
|
|
||||||
rx="0.49999979"
|
|
||||||
ry="0.5" />
|
|
||||||
<g
|
|
||||||
id="g5320"
|
|
||||||
transform="translate(402.77304,-12.882544)">
|
|
||||||
<path
|
|
||||||
id="path5322"
|
|
||||||
d="m 595.125,692.53048 0,6.43903"
|
|
||||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
|
||||||
<path
|
|
||||||
id="path5324"
|
|
||||||
d="m 598.34451,695.75 -6.43902,0"
|
|
||||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.2 KiB |
@ -1,76 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
version="1.0"
|
|
||||||
id="Foreground"
|
|
||||||
x="0px"
|
|
||||||
y="0px"
|
|
||||||
width="22"
|
|
||||||
height="22"
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
enable-background="new 0 0 16 16"
|
|
||||||
xml:space="preserve"
|
|
||||||
sodipodi:version="0.32"
|
|
||||||
inkscape:version="0.46"
|
|
||||||
sodipodi:docname="close-window.svg"
|
|
||||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
|
||||||
id="metadata2399"><rdf:RDF><cc:Work
|
|
||||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
|
||||||
id="defs2397"><linearGradient
|
|
||||||
id="linearGradient3173"><stop
|
|
||||||
style="stop-color:#c4c4c4;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop3175" /><stop
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1;"
|
|
||||||
offset="1"
|
|
||||||
id="stop3177" /></linearGradient><inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 8 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="16 : 8 : 1"
|
|
||||||
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
|
||||||
id="perspective2401" /></defs><sodipodi:namedview
|
|
||||||
inkscape:window-height="999"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
guidetolerance="10.0"
|
|
||||||
gridtolerance="10.0"
|
|
||||||
objecttolerance="10.0"
|
|
||||||
borderopacity="1.0"
|
|
||||||
bordercolor="#666666"
|
|
||||||
pagecolor="#000000"
|
|
||||||
id="base"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="25.648691"
|
|
||||||
inkscape:cx="8.8097603"
|
|
||||||
inkscape:cy="9.0472789"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:current-layer="Foreground"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:guide-bbox="true" />
|
|
||||||
|
|
||||||
<g
|
|
||||||
id="g3175"><path
|
|
||||||
sodipodi:nodetypes="csssc"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.59217799;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path2394"
|
|
||||||
d="M 0.83987936,8.0425327 C 0.83987936,4.0805265 4.0712155,0.86823453 8.0567103,0.86823453 C 12.042205,0.86823453 15.273542,4.0805265 15.273542,8.0425327 C 15.273542,12.004539 12.042205,15.216831 8.0567103,15.216831 C 4.0712155,15.216831 0.83987936,12.004539 0.83987936,8.0425327 z"
|
|
||||||
clip-rule="evenodd" /><g
|
|
||||||
id="g3172"><path
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.67127273;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="M 5.4242673,5.3313047 L 10.515414,10.421272 L 10.714004,10.646491"
|
|
||||||
id="path3152" /></g></g><path
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.67127273;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="M 5.4402527,10.650392 L 10.688082,5.3573033"
|
|
||||||
id="path3154"
|
|
||||||
sodipodi:nodetypes="cc" /></svg>
|
|
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.4 KiB |
@ -1,222 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
id="svg4908"
|
|
||||||
sodipodi:version="0.32"
|
|
||||||
inkscape:version="0.47 r22583"
|
|
||||||
sodipodi:docname="dialog-error.svg"
|
|
||||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
|
||||||
inkscape:export-filename="/home/andreas/project/gnome-icon-theme/scalable/actions/process-stop.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
version="1.0">
|
|
||||||
<defs
|
|
||||||
id="defs4910">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 24 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="48 : 24 : 1"
|
|
||||||
inkscape:persp3d-origin="24 : 16 : 1"
|
|
||||||
id="perspective25" />
|
|
||||||
<radialGradient
|
|
||||||
gradientTransform="matrix(1.349881,0,0,1.349881,-3.498814,-1.810859)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
r="9.7183542"
|
|
||||||
fy="4.9892726"
|
|
||||||
fx="9.6893959"
|
|
||||||
cy="4.9892726"
|
|
||||||
cx="9.6893959"
|
|
||||||
id="radialGradient5177"
|
|
||||||
xlink:href="#linearGradient5171"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<radialGradient
|
|
||||||
gradientTransform="matrix(2.417917,0,0,2.417917,-14.17917,-4.903184)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
r="9.7785711"
|
|
||||||
fy="3.458019"
|
|
||||||
fx="10"
|
|
||||||
cy="3.458019"
|
|
||||||
cx="10"
|
|
||||||
id="radialGradient5157"
|
|
||||||
xlink:href="#linearGradient5151"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<radialGradient
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.928125,0,0,0.3143011,0.7718789,12.358015)"
|
|
||||||
r="9.0598059"
|
|
||||||
fy="18.022524"
|
|
||||||
fx="10.739184"
|
|
||||||
cy="18.022524"
|
|
||||||
cx="10.739184"
|
|
||||||
id="radialGradient5145"
|
|
||||||
xlink:href="#linearGradient5139"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient5139"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop5141"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:black;stop-opacity:1;" />
|
|
||||||
<stop
|
|
||||||
id="stop5143"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:black;stop-opacity:0;" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient5151"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop5153"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:white;stop-opacity:1;" />
|
|
||||||
<stop
|
|
||||||
id="stop5155"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:white;stop-opacity:0;" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient5171">
|
|
||||||
<stop
|
|
||||||
id="stop5173"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#fe3a00;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
id="stop5175"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#c00;stop-opacity:1;" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="22.627417"
|
|
||||||
inkscape:cx="24.442987"
|
|
||||||
inkscape:cy="10.142308"
|
|
||||||
inkscape:current-layer="g7001"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:guide-bbox="true"
|
|
||||||
inkscape:window-width="1674"
|
|
||||||
inkscape:window-height="970"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
width="48px"
|
|
||||||
height="48px"
|
|
||||||
inkscape:window-maximized="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata4913">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title>Stop Process</dc:title>
|
|
||||||
<dc:date>December 2006</dc:date>
|
|
||||||
<dc:creator>
|
|
||||||
<cc:Agent>
|
|
||||||
<dc:title>Jakub Steiner</dc:title>
|
|
||||||
</cc:Agent>
|
|
||||||
</dc:creator>
|
|
||||||
<dc:contributor>
|
|
||||||
<cc:Agent>
|
|
||||||
<dc:title>Andreas Nilsson</dc:title>
|
|
||||||
</cc:Agent>
|
|
||||||
</dc:contributor>
|
|
||||||
<cc:license
|
|
||||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
|
||||||
<dc:subject>
|
|
||||||
<rdf:Bag>
|
|
||||||
<rdf:li>stop</rdf:li>
|
|
||||||
<rdf:li>halt</rdf:li>
|
|
||||||
</rdf:Bag>
|
|
||||||
</dc:subject>
|
|
||||||
</cc:Work>
|
|
||||||
<cc:License
|
|
||||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
|
||||||
<cc:permits
|
|
||||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
|
||||||
<cc:permits
|
|
||||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
|
||||||
<cc:requires
|
|
||||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
|
||||||
<cc:permits
|
|
||||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
|
||||||
<cc:requires
|
|
||||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
|
||||||
<cc:requires
|
|
||||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
|
||||||
</cc:License>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-24)">
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
id="g7001"
|
|
||||||
transform="matrix(1.4566048,0,0,1.4455352,0.4112881,1.2324709)">
|
|
||||||
<path
|
|
||||||
transform="matrix(0.91468137,0,0,0.70055266,-1.8812476,17.474032)"
|
|
||||||
d="m 19.79899,18.022524 a 9.0598059,3.0935922 0 1 1 -18.1196115,0 9.0598059,3.0935922 0 1 1 18.1196115,0 z"
|
|
||||||
sodipodi:ry="3.0935922"
|
|
||||||
sodipodi:rx="9.0598059"
|
|
||||||
sodipodi:cy="18.022524"
|
|
||||||
sodipodi:cx="10.739184"
|
|
||||||
id="path5137"
|
|
||||||
style="color:#000000;fill:url(#radialGradient5145);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
|
||||||
sodipodi:type="arc" />
|
|
||||||
<path
|
|
||||||
transform="matrix(0.87347736,0,0,0.83068052,-0.79308842,15.602788)"
|
|
||||||
d="m 19.25,9.625 a 9.25,9.25 0 1 1 -18.5,0 9.25,9.25 0 1 1 18.5,0 z"
|
|
||||||
sodipodi:ry="9.25"
|
|
||||||
sodipodi:rx="9.25"
|
|
||||||
sodipodi:cy="9.625"
|
|
||||||
sodipodi:cx="10"
|
|
||||||
id="path4262"
|
|
||||||
style="color:#000000;fill:url(#radialGradient5177);fill-opacity:1;fill-rule:nonzero;stroke:#a40000;stroke-width:0.47435912;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
|
||||||
sodipodi:type="arc" />
|
|
||||||
<path
|
|
||||||
sodipodi:type="arc"
|
|
||||||
style="opacity:0.35393258;color:#000000;fill:none;stroke:url(#radialGradient5157);stroke-width:0.49999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
|
||||||
id="path5149"
|
|
||||||
sodipodi:cx="10"
|
|
||||||
sodipodi:cy="9.625"
|
|
||||||
sodipodi:rx="9.25"
|
|
||||||
sodipodi:ry="9.25"
|
|
||||||
d="m 19.25,9.625 a 9.25,9.25 0 1 1 -18.5,0 9.25,9.25 0 1 1 18.5,0 z"
|
|
||||||
transform="matrix(0.82868359,0,0,0.78808147,-0.34515141,16.012803)" />
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cc"
|
|
||||||
id="path5159"
|
|
||||||
d="m 4.834121,20.642783 6.215127,5.91061"
|
|
||||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.21219134;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
|
|
||||||
<path
|
|
||||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.21219146;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
|
||||||
d="M 11.04925,20.622826 4.8159529,26.553393"
|
|
||||||
id="path5161"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 8.0 KiB |
@ -1,113 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="16"
|
|
||||||
id="svg6503"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47pre4 r22446"
|
|
||||||
sodipodi:docname="mosaic-view-active.svg">
|
|
||||||
<defs
|
|
||||||
id="defs6505">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective6511" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective6494"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="11.197802"
|
|
||||||
inkscape:cx="-15.97056"
|
|
||||||
inkscape:cy="16"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata6508">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-16)">
|
|
||||||
<g
|
|
||||||
style="display:inline;fill:#cbcbcb;fill-opacity:1"
|
|
||||||
transform="translate(-449.85476,-685.85869)"
|
|
||||||
id="g5306">
|
|
||||||
<rect
|
|
||||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none"
|
|
||||||
id="rect5308"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="450.5"
|
|
||||||
y="710.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
<rect
|
|
||||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5310"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="462.5"
|
|
||||||
y="702.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
<rect
|
|
||||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999976000000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5312"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="450.5"
|
|
||||||
y="702.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
<rect
|
|
||||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5314"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="462.5"
|
|
||||||
y="710.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.7 KiB |
@ -1,113 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="16"
|
|
||||||
id="svg6503"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47pre4 r22446"
|
|
||||||
sodipodi:docname="New document 19">
|
|
||||||
<defs
|
|
||||||
id="defs6505">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective6511" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective6494"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="11.197802"
|
|
||||||
inkscape:cx="16"
|
|
||||||
inkscape:cy="16"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata6508">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-16)">
|
|
||||||
<g
|
|
||||||
style="display:inline"
|
|
||||||
transform="translate(-449.85476,-685.85869)"
|
|
||||||
id="g5306">
|
|
||||||
<rect
|
|
||||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none"
|
|
||||||
id="rect5308"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="450.5"
|
|
||||||
y="710.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
<rect
|
|
||||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5310"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="462.5"
|
|
||||||
y="702.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
<rect
|
|
||||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5312"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="450.5"
|
|
||||||
y="702.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
<rect
|
|
||||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5314"
|
|
||||||
width="11"
|
|
||||||
height="7"
|
|
||||||
x="462.5"
|
|
||||||
y="710.5"
|
|
||||||
rx="0.99999958"
|
|
||||||
ry="1" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.6 KiB |
@ -1,89 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="98"
|
|
||||||
height="98"
|
|
||||||
id="svg6375"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47 r22583"
|
|
||||||
sodipodi:docname="add-workspace.svg">
|
|
||||||
<defs
|
|
||||||
id="defs6377">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective6383" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective6366"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="3.9590209"
|
|
||||||
inkscape:cx="56.650687"
|
|
||||||
inkscape:cy="20.635343"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata6380">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,66)">
|
|
||||||
<g
|
|
||||||
id="g2824"
|
|
||||||
transform="matrix(11.568551,0,0,11.698271,-78.828159,-304.81518)">
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
|
||||||
d="m 11.07363,21.36834 0,6.43903"
|
|
||||||
id="path5322" />
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
|
||||||
d="m 14.29314,24.58786 -6.43902,0"
|
|
||||||
id="path5324" />
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
style="fill:#000000;fill-opacity:0.98823529"
|
|
||||||
d="m 48.239516,97.908047 c -0.41677,-0.05102 -1.269253,-0.222408 -1.894408,-0.380859 -4.088493,-1.036262 -7.520781,-4.753234 -8.330163,-9.021094 -0.154947,-0.817026 -0.257819,-6.68112 -0.257819,-14.696556 l 0,-13.337088 -13.829177,-0.08909 C 10.802042,60.298796 10.026884,60.268266 8.6851548,59.783022 3.6288503,57.954375 0.62673331,53.828648 0.62673331,48.708554 c 0,-5.625522 4.25936019,-10.425065 9.97721469,-11.242548 0.987903,-0.141242 7.368912,-0.254994 14.460646,-0.257791 l 12.692532,-0.005 0,-13.586668 c 0,-14.6441583 0.03287,-15.0698926 1.364686,-17.6753047 2.185477,-4.2754229 6.938193,-6.75739913 11.687647,-6.10355607 3.382776,0.46569661 6.737962,2.72496967 8.414081,5.66577137 1.480816,2.5981315 1.519067,3.0522448 1.519067,18.0333334 l 0,13.666424 12.692533,0.005 c 7.091733,0.0028 13.472742,0.116549 14.460646,0.257791 6.395303,0.914337 10.804785,6.623716 9.941157,12.871766 -0.698243,5.051565 -4.792685,9.104635 -9.941157,9.840713 -0.987904,0.141242 -7.368913,0.254995 -14.460646,0.257791 l -12.692533,0.005 0,13.801945 c 0,13.031417 -0.02798,13.895893 -0.501177,15.484801 -1.526902,5.127058 -6.919246,8.802262 -12.001914,8.18002 z"
|
|
||||||
id="path2828"
|
|
||||||
transform="translate(0,-66)" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.0 KiB |
@ -1,92 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="23"
|
|
||||||
height="15"
|
|
||||||
id="svg5501"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47pre4 r22446"
|
|
||||||
sodipodi:docname="add-workspace.svg">
|
|
||||||
<defs
|
|
||||||
id="defs5503">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective5509" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective5314"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="11.197802"
|
|
||||||
inkscape:cx="-0.074583208"
|
|
||||||
inkscape:cy="16"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-grids="true"
|
|
||||||
inkscape:snap-bbox="true" />
|
|
||||||
<metadata
|
|
||||||
id="metadata5506">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-17)">
|
|
||||||
<g
|
|
||||||
style="display:inline"
|
|
||||||
id="g6239"
|
|
||||||
transform="translate(-953.97989,-657.32287)">
|
|
||||||
<rect
|
|
||||||
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
|
||||||
id="rect5318-6"
|
|
||||||
width="22"
|
|
||||||
height="14"
|
|
||||||
x="954.5"
|
|
||||||
y="675"
|
|
||||||
rx="0.49999979"
|
|
||||||
ry="0.5" />
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
|
||||||
d="m 968.71951,682 -6.43902,0"
|
|
||||||
id="path5324-5" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.9 KiB |
@ -1,64 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="10"
|
|
||||||
height="4"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47 r22583"
|
|
||||||
sodipodi:docname="scroll-hhandle.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4">
|
|
||||||
</defs>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<rect
|
|
||||||
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
|
||||||
id="rect3592"
|
|
||||||
width="2"
|
|
||||||
height="4"
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
rx="0"
|
|
||||||
ry="0" />
|
|
||||||
<use
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
xlink:href="#rect3592"
|
|
||||||
id="use2825"
|
|
||||||
transform="translate(8,0)"
|
|
||||||
width="10"
|
|
||||||
height="4" />
|
|
||||||
<use
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
xlink:href="#use2825"
|
|
||||||
id="use2827"
|
|
||||||
transform="translate(-4,0)"
|
|
||||||
width="10"
|
|
||||||
height="4" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.6 KiB |
BIN
data/theme/scroll-vhandle.png
Normal file
After Width: | Height: | Size: 323 B |
@ -1,62 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="4"
|
|
||||||
height="10"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47 r22583"
|
|
||||||
sodipodi:docname="scroll-hhandle.svg">
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<rect
|
|
||||||
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
|
||||||
id="rect3592"
|
|
||||||
width="2"
|
|
||||||
height="4"
|
|
||||||
x="0"
|
|
||||||
y="-4"
|
|
||||||
rx="0"
|
|
||||||
ry="0"
|
|
||||||
transform="matrix(0,1,-1,0,0,0)" />
|
|
||||||
<use
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
xlink:href="#rect3592"
|
|
||||||
id="use3705"
|
|
||||||
transform="translate(0,4)"
|
|
||||||
width="4"
|
|
||||||
height="10" />
|
|
||||||
<use
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
xlink:href="#use3705"
|
|
||||||
id="use3707"
|
|
||||||
transform="translate(0,4)"
|
|
||||||
width="4"
|
|
||||||
height="10" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,87 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="5.8600588"
|
|
||||||
height="9"
|
|
||||||
id="svg3647"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47 r22583"
|
|
||||||
sodipodi:docname="section-more.svg">
|
|
||||||
<defs
|
|
||||||
id="defs3649">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 526.18109 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
|
||||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
|
||||||
id="perspective3655" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective3603"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="82.777778"
|
|
||||||
inkscape:cx="2.9300294"
|
|
||||||
inkscape:cy="5.466443"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata3652">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-262.78425,-490.71933)">
|
|
||||||
<path
|
|
||||||
transform="matrix(0,-0.98149546,0.71467449,0,25.404986,578.15569)"
|
|
||||||
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
sodipodi:arg2="1.5707963"
|
|
||||||
sodipodi:arg1="0.52359878"
|
|
||||||
sodipodi:r2="2.5"
|
|
||||||
sodipodi:r1="5"
|
|
||||||
sodipodi:cy="337.5"
|
|
||||||
sodipodi:cx="84.5"
|
|
||||||
sodipodi:sides="3"
|
|
||||||
id="path5497-5"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
|
||||||
sodipodi:type="star" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.8 KiB |
@ -1,87 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="5.8600588"
|
|
||||||
height="9"
|
|
||||||
id="svg3647"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.46+devel"
|
|
||||||
sodipodi:docname="New document 6">
|
|
||||||
<defs
|
|
||||||
id="defs3649">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 526.18109 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
|
||||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
|
||||||
id="perspective3655" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective3603"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="0.35"
|
|
||||||
inkscape:cx="112.21575"
|
|
||||||
inkscape:cy="-32.642856"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="609"
|
|
||||||
inkscape:window-height="501"
|
|
||||||
inkscape:window-x="164"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata3652">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-262.78425,-490.71933)">
|
|
||||||
<path
|
|
||||||
transform="matrix(0,0.98149546,-0.71467449,0,506.02358,412.28296)"
|
|
||||||
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
sodipodi:arg2="1.5707963"
|
|
||||||
sodipodi:arg1="0.52359878"
|
|
||||||
sodipodi:r2="2.5"
|
|
||||||
sodipodi:r1="5"
|
|
||||||
sodipodi:cy="337.5"
|
|
||||||
sodipodi:cx="84.5"
|
|
||||||
sodipodi:sides="3"
|
|
||||||
id="path5497-5"
|
|
||||||
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
|
||||||
sodipodi:type="star" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.8 KiB |
@ -1,81 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="16"
|
|
||||||
id="svg6446"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47pre4 r22446"
|
|
||||||
sodipodi:docname="single-view-active.svg">
|
|
||||||
<defs
|
|
||||||
id="defs6448">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective6454" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective6441"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="11.197802"
|
|
||||||
inkscape:cx="0.014720032"
|
|
||||||
inkscape:cy="16"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata6451">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-17)">
|
|
||||||
<rect
|
|
||||||
ry="0.5"
|
|
||||||
rx="0.49999979"
|
|
||||||
y="17.483809"
|
|
||||||
x="0.53483802"
|
|
||||||
height="15"
|
|
||||||
width="23"
|
|
||||||
id="rect5304"
|
|
||||||
style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.4 KiB |
@ -1,81 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="16"
|
|
||||||
id="svg6446"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.47pre4 r22446"
|
|
||||||
sodipodi:docname="single-view.svg">
|
|
||||||
<defs
|
|
||||||
id="defs6448">
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 16 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="32 : 16 : 1"
|
|
||||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
|
||||||
id="perspective6454" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective6441"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="11.197802"
|
|
||||||
inkscape:cx="0.014720032"
|
|
||||||
inkscape:cy="16"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
inkscape:grid-bbox="true"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:window-width="1680"
|
|
||||||
inkscape:window-height="997"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="26"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata6451">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
transform="translate(0,-17)">
|
|
||||||
<rect
|
|
||||||
ry="0.5"
|
|
||||||
rx="0.49999979"
|
|
||||||
y="17.483809"
|
|
||||||
x="0.53483802"
|
|
||||||
height="15"
|
|
||||||
width="23"
|
|
||||||
id="rect5304"
|
|
||||||
style="fill:#626262;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.4 KiB |
@ -1,96 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="96" height="96" id="svg25070" version="1.1" inkscape:version="0.47 r22583" sodipodi:docname="dark-arrow-larger.svg">
|
|
||||||
<defs id="defs25072">
|
|
||||||
<inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 24 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="48 : 24 : 1" inkscape:persp3d-origin="24 : 16 : 1" id="perspective25078"/>
|
|
||||||
<inkscape:perspective id="perspective24985" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 0.5 : 1" sodipodi:type="inkscape:persp3d"/>
|
|
||||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4034-0-4" id="linearGradient24957" gradientUnits="userSpaceOnUse" gradientTransform="translate(6)" x1="-86.552246" y1="185.439" x2="-83.37072" y2="197.31261"/>
|
|
||||||
<linearGradient inkscape:collect="always" id="linearGradient4034-0-4">
|
|
||||||
<stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="0" id="stop4036-5-7"/>
|
|
||||||
<stop style="stop-color: rgb(186, 189, 182); stop-opacity: 1;" offset="1" id="stop4038-9-6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<filter id="filter24765" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix24767" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix24769" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4632-1-3-9-3-2" id="linearGradient24955" gradientUnits="userSpaceOnUse" gradientTransform="translate(-5)" x1="-74.520325" y1="169.06032" x2="-74.520325" y2="205.94189"/>
|
|
||||||
<linearGradient id="linearGradient4632-1-3-9-3-2">
|
|
||||||
<stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="0" id="stop4634-1-8-3-9-0"/>
|
|
||||||
<stop id="stop4636-1-9-9-8-8" offset="0.0274937" style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"/>
|
|
||||||
<stop id="stop4638-8-3-9-6-6" offset="0.274937" style="stop-color: rgb(242, 242, 242); stop-opacity: 1;"/>
|
|
||||||
<stop id="stop4640-8-5-7-8-9" offset="0.38707438" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
|
|
||||||
<stop id="stop4642-5-41-9-6-9" offset="0.66528589" style="stop-color: rgb(217, 218, 216); stop-opacity: 1;"/>
|
|
||||||
<stop id="stop4644-5-2-7-9-2" offset="0.76745707" style="stop-color: rgb(223, 224, 221); stop-opacity: 1;"/>
|
|
||||||
<stop style="stop-color: rgb(240, 240, 240); stop-opacity: 1;" offset="1" id="stop4646-3-2-3-7-3"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient inkscape:collect="always" xlink:href="#linearGradient4869-4-1" id="radialGradient24959" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)" cx="-33.412369" cy="185.74171" fx="-33.412369" fy="185.74171" r="2.3554697"/>
|
|
||||||
<linearGradient id="linearGradient4869-4-1">
|
|
||||||
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4871-6-2"/>
|
|
||||||
<stop id="stop4879-7-4" offset="0.31807542" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
|
|
||||||
<stop id="stop4877-6-1" offset="0.74691135" style="stop-color: rgb(200, 201, 198); stop-opacity: 1;"/>
|
|
||||||
<stop style="stop-color: rgb(211, 215, 207); stop-opacity: 1;" offset="1" id="stop4873-1-0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<filter id="filter25011" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix25013" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix25015" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<radialGradient inkscape:collect="always" xlink:href="#linearGradient4869-4-0" id="radialGradient24961" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)" cx="-33.412369" cy="185.74171" fx="-33.412369" fy="185.74171" r="2.3554697"/>
|
|
||||||
<linearGradient id="linearGradient4869-4-0">
|
|
||||||
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4871-6-8"/>
|
|
||||||
<stop id="stop4879-7-5" offset="0.31807542" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
|
|
||||||
<stop id="stop4877-6-5" offset="0.74691135" style="stop-color: rgb(200, 201, 198); stop-opacity: 1;"/>
|
|
||||||
<stop style="stop-color: rgb(211, 215, 207); stop-opacity: 1;" offset="1" id="stop4873-1-4"/>
|
|
||||||
</linearGradient>
|
|
||||||
<filter id="filter25023" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix25025" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix25027" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4941" id="linearGradient24963" gradientUnits="userSpaceOnUse" x1="-39.858727" y1="184.61784" x2="-38.244785" y2="188.84898"/>
|
|
||||||
<linearGradient inkscape:collect="always" id="linearGradient4941">
|
|
||||||
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4943"/>
|
|
||||||
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop4945"/>
|
|
||||||
</linearGradient>
|
|
||||||
<filter id="filter25033" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix25035" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix25037" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4941-7" id="linearGradient24965" gradientUnits="userSpaceOnUse" x1="-39.858727" y1="184.61784" x2="-38.244785" y2="188.84898"/>
|
|
||||||
<linearGradient inkscape:collect="always" id="linearGradient4941-7">
|
|
||||||
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4943-2"/>
|
|
||||||
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop4945-5"/>
|
|
||||||
</linearGradient>
|
|
||||||
<filter id="filter25043" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix25045" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix25047" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter25049" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix25051" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix25053" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter25055" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
|
|
||||||
<feColorMatrix id="feColorMatrix25057" type="saturate" values="1" result="fbSourceGraphic"/>
|
|
||||||
<feColorMatrix id="feColorMatrix25059" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="2.8284271" inkscape:cx="48.631638" inkscape:cy="57.536221" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="1200" inkscape:window-height="851" inkscape:window-x="0" inkscape:window-y="52" inkscape:window-maximized="0"/>
|
|
||||||
<metadata id="metadata25075">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
|
||||||
<dc:title/>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer" transform="translate(0, 48)">
|
|
||||||
<g id="g4030-1-8" transform="matrix(2, 0, 0, 2, 193.25, -374.967)" style="stroke: rgb(0, 0, 0); display: inline; stroke-opacity: 1;">
|
|
||||||
<path sodipodi:nodetypes="ccc" id="path3165-7-3" d="m -72.5,173.5 -14,14 14,14" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 7; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;"/>
|
|
||||||
</g>
|
|
||||||
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 0.523439; visibility: visible; display: inline;" id="path4050-2-7-9-4" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(3.34328, 0, 0, 3.34328, 185.28, -623.176)"/>
|
|
||||||
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 0.523439; visibility: visible; display: inline;" id="path4050-2-7-9-4-8" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(3.34328, 0, 0, 3.34328, 207.28, -623.176)"/>
|
|
||||||
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.697921; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;" id="path4050-2-7-9-4-0" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(2.86565, 0, 0, 2.86565, 166.846, -534.143)"/>
|
|
||||||
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.697921; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;" id="path4050-2-7-9-4-0-9" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(2.86565, 0, 0, 2.86565, 188.846, -534.143)"/>
|
|
||||||
<path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; opacity: 0.35; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 1; stroke-miterlimit: 4; stroke-dasharray: none; visibility: visible; display: inline; font-family: Bitstream Vera Sans; stroke-opacity: 1;" d="m 317.06251,365.96875 c -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 l -16.125,16.125 16.125,16.125 c 1.11265,1.11265 3.13735,1.11265 4.25,0 1.11265,-1.11264 1.11265,-3.13735 0,-4.25 l -11.875,-11.875 11.875,-11.875 c 0.86584,-0.83655 1.1475,-2.22114 0.6773,-3.32947 -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 z" id="path3165-7-3-1" sodipodi:nodetypes="ccccscccsc" transform="matrix(2, 0, 0, 2, -586, -765.967)"/>
|
|
||||||
<path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 1; stroke-linecap: round; stroke-miterlimit: 4; stroke-dasharray: none; visibility: visible; display: inline; font-family: Bitstream Vera Sans; stroke-opacity: 1;" d="m 320.08435,397.03059 c 0.007,-0.79449 -0.27079,-1.59203 -0.83434,-2.15559 L 307.37501,383 m 12.5523,-15.20447 c -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 L 298.87501,383" id="path3165-7-3-1-9" sodipodi:nodetypes="ccccccc" transform="matrix(2, 0, 0, 2, -586, -765.967)"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 13 KiB |
@ -1,331 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
version="1.1"
|
|
||||||
width="96"
|
|
||||||
height="96"
|
|
||||||
id="svg25070">
|
|
||||||
<defs
|
|
||||||
id="defs25072">
|
|
||||||
<linearGradient
|
|
||||||
x1="-86.552246"
|
|
||||||
y1="185.439"
|
|
||||||
x2="-83.37072"
|
|
||||||
y2="197.31261"
|
|
||||||
id="linearGradient24957"
|
|
||||||
xlink:href="#linearGradient4034-0-4"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(6,0)" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient4034-0-4">
|
|
||||||
<stop
|
|
||||||
id="stop4036-5-7"
|
|
||||||
style="stop-color:#eeeeec;stop-opacity:1"
|
|
||||||
offset="0" />
|
|
||||||
<stop
|
|
||||||
id="stop4038-9-6"
|
|
||||||
style="stop-color:#babdb6;stop-opacity:1"
|
|
||||||
offset="1" />
|
|
||||||
</linearGradient>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter24765">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix24767" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix24769" />
|
|
||||||
</filter>
|
|
||||||
<linearGradient
|
|
||||||
x1="-74.520325"
|
|
||||||
y1="169.06032"
|
|
||||||
x2="-74.520325"
|
|
||||||
y2="205.94189"
|
|
||||||
id="linearGradient24955"
|
|
||||||
xlink:href="#linearGradient4632-1-3-9-3-2"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(-5,0)" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient4632-1-3-9-3-2">
|
|
||||||
<stop
|
|
||||||
id="stop4634-1-8-3-9-0"
|
|
||||||
style="stop-color:#eeeeec;stop-opacity:1"
|
|
||||||
offset="0" />
|
|
||||||
<stop
|
|
||||||
id="stop4636-1-9-9-8-8"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1"
|
|
||||||
offset="0.0274937" />
|
|
||||||
<stop
|
|
||||||
id="stop4638-8-3-9-6-6"
|
|
||||||
style="stop-color:#f2f2f2;stop-opacity:1"
|
|
||||||
offset="0.274937" />
|
|
||||||
<stop
|
|
||||||
id="stop4640-8-5-7-8-9"
|
|
||||||
style="stop-color:#eeeeec;stop-opacity:1"
|
|
||||||
offset="0.38707438" />
|
|
||||||
<stop
|
|
||||||
id="stop4642-5-41-9-6-9"
|
|
||||||
style="stop-color:#d9dad8;stop-opacity:1"
|
|
||||||
offset="0.66528589" />
|
|
||||||
<stop
|
|
||||||
id="stop4644-5-2-7-9-2"
|
|
||||||
style="stop-color:#dfe0dd;stop-opacity:1"
|
|
||||||
offset="0.76745707" />
|
|
||||||
<stop
|
|
||||||
id="stop4646-3-2-3-7-3"
|
|
||||||
style="stop-color:#f0f0f0;stop-opacity:1"
|
|
||||||
offset="1" />
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient
|
|
||||||
cx="-33.412369"
|
|
||||||
cy="185.74171"
|
|
||||||
r="2.3554697"
|
|
||||||
fx="-33.412369"
|
|
||||||
fy="185.74171"
|
|
||||||
id="radialGradient24959"
|
|
||||||
xlink:href="#linearGradient4869-4-1"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient4869-4-1">
|
|
||||||
<stop
|
|
||||||
id="stop4871-6-2"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1"
|
|
||||||
offset="0" />
|
|
||||||
<stop
|
|
||||||
id="stop4879-7-4"
|
|
||||||
style="stop-color:#eeeeec;stop-opacity:1"
|
|
||||||
offset="0.31807542" />
|
|
||||||
<stop
|
|
||||||
id="stop4877-6-1"
|
|
||||||
style="stop-color:#c8c9c6;stop-opacity:1"
|
|
||||||
offset="0.74691135" />
|
|
||||||
<stop
|
|
||||||
id="stop4873-1-0"
|
|
||||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
|
||||||
offset="1" />
|
|
||||||
</linearGradient>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter25011">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix25013" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix25015" />
|
|
||||||
</filter>
|
|
||||||
<radialGradient
|
|
||||||
cx="-33.412369"
|
|
||||||
cy="185.74171"
|
|
||||||
r="2.3554697"
|
|
||||||
fx="-33.412369"
|
|
||||||
fy="185.74171"
|
|
||||||
id="radialGradient24961"
|
|
||||||
xlink:href="#linearGradient4869-4-0"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient4869-4-0">
|
|
||||||
<stop
|
|
||||||
id="stop4871-6-8"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1"
|
|
||||||
offset="0" />
|
|
||||||
<stop
|
|
||||||
id="stop4879-7-5"
|
|
||||||
style="stop-color:#eeeeec;stop-opacity:1"
|
|
||||||
offset="0.31807542" />
|
|
||||||
<stop
|
|
||||||
id="stop4877-6-5"
|
|
||||||
style="stop-color:#c8c9c6;stop-opacity:1"
|
|
||||||
offset="0.74691135" />
|
|
||||||
<stop
|
|
||||||
id="stop4873-1-4"
|
|
||||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
|
||||||
offset="1" />
|
|
||||||
</linearGradient>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter25023">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix25025" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix25027" />
|
|
||||||
</filter>
|
|
||||||
<linearGradient
|
|
||||||
x1="-39.858727"
|
|
||||||
y1="184.61784"
|
|
||||||
x2="-38.244785"
|
|
||||||
y2="188.84898"
|
|
||||||
id="linearGradient24963"
|
|
||||||
xlink:href="#linearGradient4941"
|
|
||||||
gradientUnits="userSpaceOnUse" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient4941">
|
|
||||||
<stop
|
|
||||||
id="stop4943"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1"
|
|
||||||
offset="0" />
|
|
||||||
<stop
|
|
||||||
id="stop4945"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:0"
|
|
||||||
offset="1" />
|
|
||||||
</linearGradient>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter25033">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix25035" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix25037" />
|
|
||||||
</filter>
|
|
||||||
<linearGradient
|
|
||||||
x1="-39.858727"
|
|
||||||
y1="184.61784"
|
|
||||||
x2="-38.244785"
|
|
||||||
y2="188.84898"
|
|
||||||
id="linearGradient24965"
|
|
||||||
xlink:href="#linearGradient4941-7"
|
|
||||||
gradientUnits="userSpaceOnUse" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient4941-7">
|
|
||||||
<stop
|
|
||||||
id="stop4943-2"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1"
|
|
||||||
offset="0" />
|
|
||||||
<stop
|
|
||||||
id="stop4945-5"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:0"
|
|
||||||
offset="1" />
|
|
||||||
</linearGradient>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter25043">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix25045" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix25047" />
|
|
||||||
</filter>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter25049">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix25051" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix25053" />
|
|
||||||
</filter>
|
|
||||||
<filter
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
id="filter25055">
|
|
||||||
<feColorMatrix
|
|
||||||
result="fbSourceGraphic"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
id="feColorMatrix25057" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
||||||
in="fbSourceGraphic"
|
|
||||||
id="feColorMatrix25059" />
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<g
|
|
||||||
transform="translate(0,48)"
|
|
||||||
id="layer1">
|
|
||||||
<g
|
|
||||||
transform="matrix(-2,0,0,2,-97.2497,-374.967)"
|
|
||||||
id="g4030-1-8"
|
|
||||||
style="stroke:#000000;stroke-opacity:1;display:inline">
|
|
||||||
<path
|
|
||||||
d="m -72.5,173.5 -14,14 14,14"
|
|
||||||
id="path3165-7-3"
|
|
||||||
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
|
||||||
transform="matrix(-3.34328,0,0,3.34328,-89.2797,-623.176)"
|
|
||||||
id="path4050-2-7-9-4"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible" />
|
|
||||||
<path
|
|
||||||
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
|
||||||
transform="matrix(-3.34328,0,0,3.34328,-111.2797,-623.176)"
|
|
||||||
id="path4050-2-7-9-4-8"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible" />
|
|
||||||
<path
|
|
||||||
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
|
||||||
transform="matrix(-2.86565,0,0,2.86565,-70.8457,-534.143)"
|
|
||||||
id="path4050-2-7-9-4-0"
|
|
||||||
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
|
|
||||||
<path
|
|
||||||
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
|
||||||
transform="matrix(-2.86565,0,0,2.86565,-92.8457,-534.143)"
|
|
||||||
id="path4050-2-7-9-4-0-9"
|
|
||||||
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
|
|
||||||
<path
|
|
||||||
d="m 47.87528,-34.0295 c 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25 -32.25,32.25 c -2.2253,2.2253 -6.2747,2.2253 -8.5,0 -2.2253,-2.22528 -2.2253,-6.2747 0,-8.5 l 23.75,-23.75 -23.75,-23.75 c -1.73168,-1.6731 -2.295,-4.44228 -1.3546,-6.65894 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 z"
|
|
||||||
id="path3165-7-3-1"
|
|
||||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" />
|
|
||||||
<path
|
|
||||||
d="m 41.8316,28.09418 c -0.014,-1.58898 0.54158,-3.18406 1.66868,-4.31118 l 23.75,-23.75 m -25.1046,-30.40894 c 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25"
|
|
||||||
id="path3165-7-3-1-9"
|
|
||||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 12 KiB |
@ -1 +1 @@
|
|||||||
SUBDIRS = misc ui perf prefs
|
SUBDIRS = misc ui
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
jsmiscdir = $(pkgdatadir)/js/misc
|
jsmiscdir = $(pkgdatadir)/js/misc
|
||||||
|
|
||||||
dist_jsmisc_DATA = \
|
dist_jsmisc_DATA = \
|
||||||
docInfo.js \
|
docInfo.js
|
||||||
format.js \
|
|
||||||
gnomeSession.js \
|
|
||||||
params.js \
|
|
||||||
telepathy.js
|
|
||||||
|
@ -3,12 +3,10 @@
|
|||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Search = imports.ui.search;
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const THUMBNAIL_ICON_MARGIN = 2;
|
const THUMBNAIL_ICON_MARGIN = 2;
|
||||||
@ -19,43 +17,69 @@ function DocInfo(recentInfo) {
|
|||||||
|
|
||||||
DocInfo.prototype = {
|
DocInfo.prototype = {
|
||||||
_init : function(recentInfo) {
|
_init : function(recentInfo) {
|
||||||
this.recentInfo = recentInfo;
|
this._recentInfo = recentInfo;
|
||||||
// We actually used get_modified() instead of get_visited()
|
// We actually used get_modified() instead of get_visited()
|
||||||
// here, as GtkRecentInfo doesn't updated get_visited()
|
// here, as GtkRecentInfo doesn't updated get_visited()
|
||||||
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
|
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
|
||||||
this.timestamp = recentInfo.get_modified().getTime() / 1000;
|
this.timestamp = recentInfo.get_modified().getTime() / 1000;
|
||||||
this.name = recentInfo.get_display_name();
|
this.name = recentInfo.get_display_name();
|
||||||
this._lowerName = this.name.toLowerCase();
|
|
||||||
this.uri = recentInfo.get_uri();
|
this.uri = recentInfo.get_uri();
|
||||||
this.mimeType = recentInfo.get_mime_type();
|
this.mimeType = recentInfo.get_mime_type();
|
||||||
},
|
},
|
||||||
|
|
||||||
createIcon : function(size) {
|
createIcon : function(size) {
|
||||||
return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
|
return Shell.TextureCache.get_default().load_recent_thumbnail(size, this._recentInfo);
|
||||||
},
|
},
|
||||||
|
|
||||||
launch : function() {
|
launch : function() {
|
||||||
Shell.DocSystem.get_default().open(this.recentInfo);
|
// While using Gio.app_info_launch_default_for_uri() would be
|
||||||
},
|
// shorter in terms of lines of code, we are not doing so
|
||||||
|
// because that would duplicate the work of retrieving the
|
||||||
|
// mime type.
|
||||||
|
|
||||||
matchTerms: function(terms) {
|
let appInfo = Gio.app_info_get_default_for_type(this.mimeType, true);
|
||||||
let mtype = Search.MatchType.NONE;
|
|
||||||
for (let i = 0; i < terms.length; i++) {
|
if (appInfo != null) {
|
||||||
let term = terms[i];
|
appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
|
||||||
let idx = this._lowerName.indexOf(term);
|
} else {
|
||||||
if (idx == 0) {
|
log("Failed to get default application info for mime type " + this.mimeType +
|
||||||
if (mtype != Search.MatchType.NONE)
|
". Will try to use the last application that registered the document.");
|
||||||
return Search.MatchType.MULTIPLE;
|
let appName = this._recentInfo.last_application();
|
||||||
mtype = Search.MatchType.PREFIX;
|
let [success, appExec, count, time] = this._recentInfo.get_application_info(appName);
|
||||||
} else if (idx > 0) {
|
if (success) {
|
||||||
if (mtype != Search.MatchType.NONE)
|
log("Will open a document with the following command: " + appExec);
|
||||||
return Search.MatchType.MULTIPLE;
|
// TODO: Change this once better support for creating
|
||||||
mtype = Search.MatchType.SUBSTRING;
|
// GAppInfo is added to GtkRecentInfo, as right now
|
||||||
|
// this relies on the fact that the file uri is
|
||||||
|
// already a part of appExec, so we don't supply any
|
||||||
|
// files to appInfo.launch().
|
||||||
|
|
||||||
|
// The 'command line' passed to
|
||||||
|
// create_from_command_line is allowed to contain
|
||||||
|
// '%<something>' macros that are expanded to file
|
||||||
|
// name / icon name, etc, so we need to escape % as %%
|
||||||
|
appExec = appExec.replace(/%/g, "%%");
|
||||||
|
|
||||||
|
let appInfo = Gio.app_info_create_from_commandline(appExec, null, 0, null);
|
||||||
|
|
||||||
|
// The point of passing an app launch context to
|
||||||
|
// launch() is mostly to get startup notification and
|
||||||
|
// associated benefits like the app appearing on the
|
||||||
|
// right desktop; but it doesn't really work for now
|
||||||
|
// because with the way we create the appInfo we
|
||||||
|
// aren't reading the application's desktop file, and
|
||||||
|
// thus don't find the StartupNotify=true in it. So,
|
||||||
|
// despite passing the app launch context, no startup
|
||||||
|
// notification occurs.
|
||||||
|
appInfo.launch([], Main.createAppLaunchContext());
|
||||||
} else {
|
} else {
|
||||||
continue;
|
log("Failed to get application info for " + this.uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mtype;
|
},
|
||||||
|
|
||||||
|
exists : function() {
|
||||||
|
return this._recentInfo.exists();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,87 +91,51 @@ function getDocManager() {
|
|||||||
return docManagerInstance;
|
return docManagerInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DocManager wraps the DocSystem, primarily to expose DocInfo objects
|
|
||||||
* which conform to the GenericDisplay item API.
|
|
||||||
*/
|
|
||||||
function DocManager() {
|
function DocManager() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
DocManager.prototype = {
|
DocManager.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._docSystem = Shell.DocSystem.get_default();
|
this._recentManager = Gtk.RecentManager.get_default();
|
||||||
this._infosByTimestamp = [];
|
this._items = {};
|
||||||
this._infosByUri = {};
|
this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
|
||||||
this._docSystem.connect('changed', Lang.bind(this, this._reload));
|
this._reload();
|
||||||
|
this.emit('changed');
|
||||||
|
}));
|
||||||
this._reload();
|
this._reload();
|
||||||
},
|
},
|
||||||
|
|
||||||
_reload: function() {
|
_reload: function() {
|
||||||
let docs = this._docSystem.get_all();
|
let docs = this._recentManager.get_items();
|
||||||
this._infosByTimestamp = [];
|
let newItems = {};
|
||||||
this._infosByUri = {};
|
|
||||||
for (let i = 0; i < docs.length; i++) {
|
for (let i = 0; i < docs.length; i++) {
|
||||||
let recentInfo = docs[i];
|
let recentInfo = docs[i];
|
||||||
|
if (!recentInfo.exists())
|
||||||
|
continue;
|
||||||
|
|
||||||
let docInfo = new DocInfo(recentInfo);
|
let docInfo = new DocInfo(recentInfo);
|
||||||
this._infosByTimestamp.push(docInfo);
|
|
||||||
this._infosByUri[docInfo.uri] = docInfo;
|
// we use GtkRecentInfo URI as an item Id
|
||||||
|
newItems[docInfo.uri] = docInfo;
|
||||||
}
|
}
|
||||||
this.emit('changed');
|
let deleted = {};
|
||||||
},
|
for (var uri in this._items) {
|
||||||
|
if (!(uri in newItems))
|
||||||
getTimestampOrderedInfos: function() {
|
deleted[uri] = this._items[uri];
|
||||||
return this._infosByTimestamp;
|
|
||||||
},
|
|
||||||
|
|
||||||
getInfosByUri: function() {
|
|
||||||
return this._infosByUri;
|
|
||||||
},
|
|
||||||
|
|
||||||
lookupByUri: function(uri) {
|
|
||||||
return this._infosByUri[uri];
|
|
||||||
},
|
|
||||||
|
|
||||||
queueExistenceCheck: function(count) {
|
|
||||||
return this._docSystem.queue_existence_check(count);
|
|
||||||
},
|
|
||||||
|
|
||||||
initialSearch: function(terms) {
|
|
||||||
let multipleMatches = [];
|
|
||||||
let prefixMatches = [];
|
|
||||||
let substringMatches = [];
|
|
||||||
for (let i = 0; i < this._infosByTimestamp.length; i++) {
|
|
||||||
let item = this._infosByTimestamp[i];
|
|
||||||
let mtype = item.matchTerms(terms);
|
|
||||||
if (mtype == Search.MatchType.MULTIPLE)
|
|
||||||
multipleMatches.push(item.uri);
|
|
||||||
else if (mtype == Search.MatchType.PREFIX)
|
|
||||||
prefixMatches.push(item.uri);
|
|
||||||
else if (mtype == Search.MatchType.SUBSTRING)
|
|
||||||
substringMatches.push(item.uri);
|
|
||||||
}
|
|
||||||
return multipleMatches.concat(prefixMatches.concat(substringMatches));
|
|
||||||
},
|
|
||||||
|
|
||||||
subsearch: function(previousResults, terms) {
|
|
||||||
let multipleMatches = [];
|
|
||||||
let prefixMatches = [];
|
|
||||||
let substringMatches = [];
|
|
||||||
for (let i = 0; i < previousResults.length; i++) {
|
|
||||||
let uri = previousResults[i];
|
|
||||||
let item = this._infosByUri[uri];
|
|
||||||
let mtype = item.matchTerms(terms);
|
|
||||||
if (mtype == Search.MatchType.MULTIPLE)
|
|
||||||
multipleMatches.push(uri);
|
|
||||||
else if (mtype == Search.MatchType.PREFIX)
|
|
||||||
prefixMatches.push(uri);
|
|
||||||
else if (mtype == Search.MatchType.SUBSTRING)
|
|
||||||
substringMatches.push(uri);
|
|
||||||
}
|
}
|
||||||
return multipleMatches.concat(prefixMatches.concat(substringMatches));
|
/* If we'd cached any thumbnail references that no longer exist,
|
||||||
|
dump them here */
|
||||||
|
let texCache = Shell.TextureCache.get_default();
|
||||||
|
for (var uri in deleted) {
|
||||||
|
texCache.evict_recent_thumbnail(this._items[uri]);
|
||||||
|
}
|
||||||
|
this._items = newItems;
|
||||||
|
},
|
||||||
|
|
||||||
|
getItems: function() {
|
||||||
|
return this._items;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Signals.addSignalMethods(DocManager.prototype);
|
Signals.addSignalMethods(DocManager.prototype);
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is intended to extend the String object and provide
|
|
||||||
* an String.format API for string formatting.
|
|
||||||
* It has to be set up using String.prototype.format = Format.format;
|
|
||||||
* Usage:
|
|
||||||
* "somestring %s %d".format('hello', 5);
|
|
||||||
* It supports %s, %d and %f, for %f it also support precisions like
|
|
||||||
* "%.2f".format(1.526)
|
|
||||||
*/
|
|
||||||
|
|
||||||
function format() {
|
|
||||||
let str = this;
|
|
||||||
let i = 0;
|
|
||||||
let args = arguments;
|
|
||||||
|
|
||||||
return str.replace(/%(?:\.([0-9]+))?(.)/g, function (str, precisionGroup, genericGroup) {
|
|
||||||
|
|
||||||
if (precisionGroup != '' && genericGroup != 'f')
|
|
||||||
throw new Error("Precision can only be specified for 'f'");
|
|
||||||
|
|
||||||
switch (genericGroup) {
|
|
||||||
case '%':
|
|
||||||
return '%';
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
return args[i++].toString();
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
return parseInt(args[i++]);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (precisionGroup == '')
|
|
||||||
return parseFloat(args[i++]);
|
|
||||||
else
|
|
||||||
return parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('Unsupported conversion character %' + genericGroup);
|
|
||||||
}
|
|
||||||
return ""; // Suppress warning
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
const PresenceIface = {
|
|
||||||
name: 'org.gnome.SessionManager.Presence',
|
|
||||||
methods: [{ name: 'SetStatus',
|
|
||||||
inSignature: 'u' }],
|
|
||||||
properties: [{ name: 'status',
|
|
||||||
signature: 'u',
|
|
||||||
access: 'readwrite' }],
|
|
||||||
signals: [{ name: 'StatusChanged',
|
|
||||||
inSignature: 'u' }]
|
|
||||||
};
|
|
||||||
|
|
||||||
const PresenceStatus = {
|
|
||||||
AVAILABLE: 0,
|
|
||||||
INVISIBLE: 1,
|
|
||||||
BUSY: 2,
|
|
||||||
IDLE: 3
|
|
||||||
};
|
|
||||||
|
|
||||||
function Presence() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Presence.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
|
|
||||||
},
|
|
||||||
|
|
||||||
getStatus: function(callback) {
|
|
||||||
this.GetRemote('status', Lang.bind(this,
|
|
||||||
function(status, ex) {
|
|
||||||
if (!ex)
|
|
||||||
callback(this, status);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
setStatus: function(status) {
|
|
||||||
this.SetStatusRemote(status);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
DBus.proxifyPrototype(Presence.prototype, PresenceIface);
|
|
@ -1,35 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
// parse:
|
|
||||||
// @params: caller-provided parameter object, or %null
|
|
||||||
// @defaults: function-provided defaults object
|
|
||||||
// @allowExtras: whether or not to allow properties not in @default
|
|
||||||
//
|
|
||||||
// Examines @params and fills in default values from @defaults for
|
|
||||||
// any properties in @defaults that don't appear in @params. If
|
|
||||||
// @allowExtras is not %true, it will throw an error if @params
|
|
||||||
// contains any properties that aren't in @defaults.
|
|
||||||
//
|
|
||||||
// If @params is %null, this returns the values from @defaults.
|
|
||||||
//
|
|
||||||
// Return value: a new object, containing the merged parameters from
|
|
||||||
// @params and @defaults
|
|
||||||
function parse(params, defaults, allowExtras) {
|
|
||||||
let ret = {}, prop;
|
|
||||||
|
|
||||||
if (!params)
|
|
||||||
params = {};
|
|
||||||
|
|
||||||
for (prop in params) {
|
|
||||||
if (!(prop in defaults) && !allowExtras)
|
|
||||||
throw new Error('Unrecognized parameter "' + prop + '"');
|
|
||||||
ret[prop] = params[prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (prop in defaults) {
|
|
||||||
if (!(prop in params))
|
|
||||||
ret[prop] = defaults[prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,372 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
|
|
||||||
// D-Bus utils; should eventually move to gjs.
|
|
||||||
// https://bugzilla.gnome.org/show_bug.cgi?id=610859
|
|
||||||
|
|
||||||
function makeProxyClass(iface) {
|
|
||||||
let constructor = function() { this._init.apply(this, arguments); };
|
|
||||||
|
|
||||||
constructor.prototype._init = function(bus, name, path) {
|
|
||||||
bus.proxifyObject(this, name, path);
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(constructor.prototype, iface);
|
|
||||||
return constructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
function nameToPath(name) {
|
|
||||||
return '/' + name.replace('.', '/', 'g');
|
|
||||||
};
|
|
||||||
|
|
||||||
function pathToName(path) {
|
|
||||||
if (path[0] != '/')
|
|
||||||
throw new Error('not a D-Bus path: ' + path);
|
|
||||||
return path.substr(1).replace('/', '.', 'g');
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is tp_escape_as_identifier() from telepathy-glib
|
|
||||||
function escapeAsIdentifier(name) {
|
|
||||||
if (!name)
|
|
||||||
return '_';
|
|
||||||
|
|
||||||
// first char is replaced with _XX if it's non-alpha,
|
|
||||||
// later chars are replaced with _XX if they're non-alphanumeric
|
|
||||||
if (name.length == 1) {
|
|
||||||
return name.replace(/[^a-zA-Z]/, _hexEscape);
|
|
||||||
} else {
|
|
||||||
return (name[0].replace(/[^a-zA-Z]/, _hexEscape) +
|
|
||||||
name.substring(1).replace(/[^a-zA-Z0-9]/g, _hexEscape));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _hexEscape(ch) {
|
|
||||||
return '_' + ch.charCodeAt(0).toString(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Telepathy D-Bus interface definitions. Note that most of these are
|
|
||||||
// incomplete, and only cover the methods/properties/signals that
|
|
||||||
// we're currently using.
|
|
||||||
|
|
||||||
const TELEPATHY = 'org.freedesktop.Telepathy';
|
|
||||||
|
|
||||||
const CLIENT_NAME = TELEPATHY + '.Client';
|
|
||||||
const ClientIface = {
|
|
||||||
name: CLIENT_NAME,
|
|
||||||
properties: [
|
|
||||||
{ name: 'Interfaces',
|
|
||||||
signature: 'as',
|
|
||||||
access: 'read' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const CLIENT_APPROVER_NAME = TELEPATHY + '.Client.Approver';
|
|
||||||
const ClientApproverIface = {
|
|
||||||
name: CLIENT_APPROVER_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'AddDispatchOperation',
|
|
||||||
inSignature: 'a(oa{sv})oa{sv}',
|
|
||||||
outSignature: '' }
|
|
||||||
],
|
|
||||||
properties: [
|
|
||||||
{ name: 'ApproverChannelFilter',
|
|
||||||
signature: 'aa{sv}',
|
|
||||||
access: 'read' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const CLIENT_HANDLER_NAME = TELEPATHY + '.Client.Handler';
|
|
||||||
const ClientHandlerIface = {
|
|
||||||
name: CLIENT_HANDLER_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'HandleChannels',
|
|
||||||
inSignature: 'ooa(oa{sv})aota{sv}',
|
|
||||||
outSignature: '' }
|
|
||||||
],
|
|
||||||
properties: [
|
|
||||||
{ name: 'HandlerChannelFilter',
|
|
||||||
signature: 'aa{sv}',
|
|
||||||
access: 'read' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const CLIENT_OBSERVER_NAME = TELEPATHY + '.Client.Observer';
|
|
||||||
const ClientObserverIface = {
|
|
||||||
name: CLIENT_OBSERVER_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'ObserveChannels',
|
|
||||||
inSignature: 'ooa(oa{sv})oaoa{sv}',
|
|
||||||
outSignature: '' }
|
|
||||||
],
|
|
||||||
properties: [
|
|
||||||
{ name: 'ObserverChannelFilter',
|
|
||||||
signature: 'aa{sv}',
|
|
||||||
access: 'read' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const CHANNEL_DISPATCH_OPERATION_NAME = TELEPATHY + '.ChannelDispatchOperation';
|
|
||||||
const ChannelDispatchOperationIface = {
|
|
||||||
name: CHANNEL_DISPATCH_OPERATION_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'HandleWith',
|
|
||||||
inSignature: 's',
|
|
||||||
outSignature: '' },
|
|
||||||
{ name: 'Claim',
|
|
||||||
inSignature: '',
|
|
||||||
outSignature: '' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ChannelDispatchOperation = makeProxyClass(ChannelDispatchOperationIface);
|
|
||||||
|
|
||||||
const CONNECTION_NAME = TELEPATHY + '.Connection';
|
|
||||||
const ConnectionIface = {
|
|
||||||
name: CONNECTION_NAME,
|
|
||||||
signals: [
|
|
||||||
{ name: 'StatusChanged',
|
|
||||||
inSignature: 'uu' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let Connection = makeProxyClass(ConnectionIface);
|
|
||||||
|
|
||||||
const ConnectionStatus = {
|
|
||||||
CONNECTED: 0,
|
|
||||||
CONNECTING: 1,
|
|
||||||
DISCONNECTED: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
const CONNECTION_ALIASING_NAME = CONNECTION_NAME + '.Interface.Aliasing';
|
|
||||||
const ConnectionAliasingIface = {
|
|
||||||
name: CONNECTION_ALIASING_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'RequestAliases',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: 'as'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'AliasesChanged',
|
|
||||||
inSignature: 'a(us)' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ConnectionAliasing = makeProxyClass(ConnectionAliasingIface);
|
|
||||||
|
|
||||||
const CONNECTION_AVATARS_NAME = CONNECTION_NAME + '.Interface.Avatars';
|
|
||||||
const ConnectionAvatarsIface = {
|
|
||||||
name: CONNECTION_AVATARS_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'GetKnownAvatarTokens',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: 'a{us}'
|
|
||||||
},
|
|
||||||
{ name: 'RequestAvatars',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: ''
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'AvatarRetrieved',
|
|
||||||
inSignature: 'usays'
|
|
||||||
},
|
|
||||||
{ name: 'AvatarUpdated',
|
|
||||||
inSignature: 'us'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ConnectionAvatars = makeProxyClass(ConnectionAvatarsIface);
|
|
||||||
|
|
||||||
const CONNECTION_CONTACTS_NAME = CONNECTION_NAME + '.Interface.Contacts';
|
|
||||||
const ConnectionContactsIface = {
|
|
||||||
name: CONNECTION_CONTACTS_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'GetContactAttributes',
|
|
||||||
inSignature: 'auasb',
|
|
||||||
outSignature: 'a{ua{sv}}'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ConnectionContacts = makeProxyClass(ConnectionContactsIface);
|
|
||||||
|
|
||||||
const CONNECTION_REQUESTS_NAME = CONNECTION_NAME + '.Interface.Requests';
|
|
||||||
const ConnectionRequestsIface = {
|
|
||||||
name: CONNECTION_REQUESTS_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'CreateChannel',
|
|
||||||
inSignature: 'a{sv}',
|
|
||||||
outSignature: 'oa{sv}'
|
|
||||||
},
|
|
||||||
{ name: 'EnsureChannel',
|
|
||||||
inSignature: 'a{sv}',
|
|
||||||
outSignature: 'boa{sv}'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
properties: [
|
|
||||||
{ name: 'Channels',
|
|
||||||
signature: 'a(oa{sv})',
|
|
||||||
access: 'read' }
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'NewChannels',
|
|
||||||
inSignature: 'a(oa{sv})'
|
|
||||||
},
|
|
||||||
{ name: 'ChannelClosed',
|
|
||||||
inSignature: 'o'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ConnectionRequests = makeProxyClass(ConnectionRequestsIface);
|
|
||||||
|
|
||||||
const CONNECTION_SIMPLE_PRESENCE_NAME = CONNECTION_NAME + '.Interface.SimplePresence';
|
|
||||||
const ConnectionSimplePresenceIface = {
|
|
||||||
name: CONNECTION_SIMPLE_PRESENCE_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'SetPresence',
|
|
||||||
inSignature: 'ss'
|
|
||||||
},
|
|
||||||
{ name: 'GetPresences',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: 'a{u(uss)}'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'PresencesChanged',
|
|
||||||
inSignature: 'a{u(uss)}' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ConnectionSimplePresence = makeProxyClass(ConnectionSimplePresenceIface);
|
|
||||||
|
|
||||||
const ConnectionPresenceType = {
|
|
||||||
UNSET: 0,
|
|
||||||
OFFLINE: 1,
|
|
||||||
AVAILABLE: 2,
|
|
||||||
AWAY: 3,
|
|
||||||
EXTENDED_AWAY: 4,
|
|
||||||
HIDDEN: 5,
|
|
||||||
BUSY: 6,
|
|
||||||
UNKNOWN: 7,
|
|
||||||
ERROR: 8
|
|
||||||
};
|
|
||||||
|
|
||||||
const HandleType = {
|
|
||||||
NONE: 0,
|
|
||||||
CONTACT: 1,
|
|
||||||
ROOM: 2,
|
|
||||||
LIST: 3,
|
|
||||||
GROUP: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
const CHANNEL_NAME = TELEPATHY + '.Channel';
|
|
||||||
const ChannelIface = {
|
|
||||||
name: CHANNEL_NAME,
|
|
||||||
signals: [
|
|
||||||
{ name: 'Closed',
|
|
||||||
inSignature: '' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let Channel = makeProxyClass(ChannelIface);
|
|
||||||
|
|
||||||
const CHANNEL_TEXT_NAME = CHANNEL_NAME + '.Type.Text';
|
|
||||||
const ChannelTextIface = {
|
|
||||||
name: CHANNEL_TEXT_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'ListPendingMessages',
|
|
||||||
inSignature: 'b',
|
|
||||||
outSignature: 'a(uuuuus)'
|
|
||||||
},
|
|
||||||
{ name: 'AcknowledgePendingMessages',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: ''
|
|
||||||
},
|
|
||||||
{ name: 'Send',
|
|
||||||
inSignature: 'us',
|
|
||||||
outSignature: ''
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'Received',
|
|
||||||
inSignature: 'uuuuus' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ChannelText = makeProxyClass(ChannelTextIface);
|
|
||||||
|
|
||||||
const ChannelTextMessageType = {
|
|
||||||
NORMAL: 0,
|
|
||||||
ACTION: 1,
|
|
||||||
NOTICE: 2,
|
|
||||||
AUTO_REPLY: 3,
|
|
||||||
DELIVERY_REPORT: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
const CHANNEL_CONTACT_LIST_NAME = CHANNEL_NAME + '.Type.ContactList';
|
|
||||||
// There is no interface associated with ContactList; it's just a
|
|
||||||
// special kind of Channel.Interface.Group
|
|
||||||
|
|
||||||
const CHANNEL_GROUP_NAME = CHANNEL_NAME + '.Interface.Group';
|
|
||||||
const ChannelGroupIface = {
|
|
||||||
name: CHANNEL_GROUP_NAME,
|
|
||||||
properties: [
|
|
||||||
{ name: 'Members',
|
|
||||||
signature: 'au',
|
|
||||||
access: 'read' }
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'MembersChanged',
|
|
||||||
inSignature: 'sauauauauuu' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ChannelGroup = makeProxyClass(ChannelGroupIface);
|
|
||||||
|
|
||||||
const ACCOUNT_MANAGER_NAME = TELEPATHY + '.AccountManager';
|
|
||||||
const AccountManagerIface = {
|
|
||||||
name: ACCOUNT_MANAGER_NAME,
|
|
||||||
properties: [
|
|
||||||
{ name: 'ValidAccounts',
|
|
||||||
signature: 'ao',
|
|
||||||
access: 'read' }
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'AccountValidityChanged',
|
|
||||||
inSignature: 'ob' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let AccountManager = makeProxyClass(AccountManagerIface);
|
|
||||||
|
|
||||||
const ACCOUNT_NAME = TELEPATHY + '.Account';
|
|
||||||
const AccountIface = {
|
|
||||||
name: ACCOUNT_NAME,
|
|
||||||
properties: [
|
|
||||||
{ name: 'Connection',
|
|
||||||
signature: 'o',
|
|
||||||
access: 'read' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let Account = makeProxyClass(AccountIface);
|
|
||||||
|
|
||||||
const CHANNEL_DISPATCHER_NAME = TELEPATHY + '.ChannelDispatcher';
|
|
||||||
const ChannelDispatcherIface = {
|
|
||||||
name: CHANNEL_DISPATCHER_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'EnsureChannel',
|
|
||||||
inSignature: 'oa{sv}xs',
|
|
||||||
outSignature: 'o' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ChannelDispatcher = makeProxyClass(ChannelDispatcherIface);
|
|
||||||
|
|
||||||
const CHANNEL_REQUEST_NAME = TELEPATHY + '.ChannelRequest';
|
|
||||||
const ChannelRequestIface = {
|
|
||||||
name: CHANNEL_REQUEST_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'Proceed',
|
|
||||||
inSignature: '',
|
|
||||||
outSignature: '' }
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'Failed',
|
|
||||||
signature: 'ss' },
|
|
||||||
{ name: 'Succeeded',
|
|
||||||
signature: '' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
let ChannelRequest = makeProxyClass(ChannelRequestIface);
|
|
@ -1,4 +0,0 @@
|
|||||||
jsperfdir = $(pkgdatadir)/js/perf
|
|
||||||
|
|
||||||
dist_jsperf_DATA = \
|
|
||||||
core.js
|
|
102
js/perf/core.js
@ -1,102 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Scripting = imports.ui.scripting;
|
|
||||||
|
|
||||||
// This performance script measure the most important (core) performance
|
|
||||||
// metrics for the shell. By looking at the output metrics of this script
|
|
||||||
// someone should be able to get an idea of how well the shell is performing
|
|
||||||
// on a particular system.
|
|
||||||
|
|
||||||
let METRICS = {
|
|
||||||
overviewLatencyFirst:
|
|
||||||
{ description: "Time to first frame after triggering overview, first time",
|
|
||||||
units: "us" },
|
|
||||||
overviewFramesFirst:
|
|
||||||
{ description: "Frames displayed when going to overview, first time",
|
|
||||||
units: "frames" },
|
|
||||||
overviewLatencySubsequent:
|
|
||||||
{ description: "Time to first frame after triggering overview, second time",
|
|
||||||
units: "us"},
|
|
||||||
overviewFramesSubsequent:
|
|
||||||
{ description: "Frames displayed when going to overview, second time",
|
|
||||||
units: "us" },
|
|
||||||
usedAfterOverview:
|
|
||||||
{ description: "Malloc'ed bytes after the overview is shown once",
|
|
||||||
units: "B" },
|
|
||||||
leakedAfterOverview:
|
|
||||||
{ description: "Additional malloc'ed bytes the second time the overview is shown",
|
|
||||||
units: "B" }
|
|
||||||
};
|
|
||||||
|
|
||||||
function run() {
|
|
||||||
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
|
|
||||||
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
|
|
||||||
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
|
|
||||||
|
|
||||||
yield Scripting.sleep(1000);
|
|
||||||
yield Scripting.waitLeisure();
|
|
||||||
for (let i = 0; i < 2; i++) {
|
|
||||||
Scripting.scriptEvent('overviewShowStart');
|
|
||||||
Main.overview.show();
|
|
||||||
yield Scripting.waitLeisure();
|
|
||||||
Scripting.scriptEvent('overviewShowDone');
|
|
||||||
|
|
||||||
Main.overview.hide();
|
|
||||||
yield Scripting.waitLeisure();
|
|
||||||
|
|
||||||
global.gc();
|
|
||||||
yield Scripting.sleep(1000);
|
|
||||||
Scripting.collectStatistics();
|
|
||||||
Scripting.scriptEvent('afterShowHide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let showingOverview = false;
|
|
||||||
let overviewShowStart;
|
|
||||||
let overviewFrames;
|
|
||||||
let overviewLatency;
|
|
||||||
let mallocUsedSize = 0;
|
|
||||||
let overviewShowCount = 0;
|
|
||||||
let firstOverviewUsedSize;
|
|
||||||
|
|
||||||
function script_overviewShowStart(time) {
|
|
||||||
showingOverview = true;
|
|
||||||
overviewShowStart = time;
|
|
||||||
overviewFrames = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function script_overviewShowDone(time) {
|
|
||||||
showingOverview = false;
|
|
||||||
|
|
||||||
overviewShowCount++;
|
|
||||||
|
|
||||||
if (overviewShowCount == 1) {
|
|
||||||
METRICS.overviewLatencyFirst.value = overviewLatency;
|
|
||||||
METRICS.overviewFramesFirst.value = overviewFrames;
|
|
||||||
} else {
|
|
||||||
METRICS.overviewLatencySubsequent.value = overviewLatency;
|
|
||||||
METRICS.overviewFramesSubsequent.value = overviewFrames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function script_afterShowHide(time) {
|
|
||||||
if (overviewShowCount == 1) {
|
|
||||||
METRICS.usedAfterOverview.value = mallocUsedSize;
|
|
||||||
} else {
|
|
||||||
METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function malloc_usedSize(time, bytes) {
|
|
||||||
mallocUsedSize = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clutter_stagePaintDone(time) {
|
|
||||||
if (showingOverview) {
|
|
||||||
if (overviewFrames == 0)
|
|
||||||
overviewLatency = time - overviewShowStart;
|
|
||||||
|
|
||||||
overviewFrames++;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
jsprefsdir = $(pkgdatadir)/js/prefs
|
|
||||||
|
|
||||||
dist_jsprefs_DATA = \
|
|
||||||
clockPreferences.js
|
|
@ -1,93 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const GConf = imports.gi.GConf;
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const GCONF_DIR = '/desktop/gnome/shell/clock';
|
|
||||||
const FORMAT_KEY = GCONF_DIR + '/format';
|
|
||||||
const SHOW_DATE_KEY = GCONF_DIR + '/show_date';
|
|
||||||
const SHOW_SECONDS_KEY = GCONF_DIR + '/show_seconds';
|
|
||||||
|
|
||||||
|
|
||||||
function ClockPreferences(uiFile) {
|
|
||||||
this._init(uiFile);
|
|
||||||
};
|
|
||||||
|
|
||||||
ClockPreferences.prototype = {
|
|
||||||
_init: function(uiFile) {
|
|
||||||
let builder = new Gtk.Builder();
|
|
||||||
builder.add_from_file(uiFile);
|
|
||||||
|
|
||||||
this._dialog = builder.get_object('prefs-dialog');
|
|
||||||
this._dialog.connect('response', Lang.bind(this, this._onResponse));
|
|
||||||
|
|
||||||
this._12hrRadio = builder.get_object('12hr_radio');
|
|
||||||
this._24hrRadio = builder.get_object('24hr_radio');
|
|
||||||
this._dateCheck = builder.get_object('date_check');
|
|
||||||
this._secondsCheck = builder.get_object('seconds_check');
|
|
||||||
|
|
||||||
delete builder;
|
|
||||||
|
|
||||||
this._gconf = GConf.Client.get_default();
|
|
||||||
this._gconf.add_dir(GCONF_DIR, GConf.ClientPreloadType.PRELOAD_NONE);
|
|
||||||
this._notifyId = this._gconf.notify_add(GCONF_DIR,
|
|
||||||
Lang.bind(this,
|
|
||||||
this._updateDialog));
|
|
||||||
|
|
||||||
this._12hrRadio.connect('toggled', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
let format = this._12hrRadio.active ? '12-hour' : '24-hour';
|
|
||||||
this._gconf.set_string(FORMAT_KEY, format);
|
|
||||||
}));
|
|
||||||
this._dateCheck.connect('toggled', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._gconf.set_bool(SHOW_DATE_KEY, this._dateCheck.active);
|
|
||||||
}));
|
|
||||||
this._secondsCheck.connect('toggled', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._gconf.set_bool(SHOW_SECONDS_KEY,
|
|
||||||
this._secondsCheck.active);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._updateDialog();
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function() {
|
|
||||||
this._dialog.show_all();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateDialog: function() {
|
|
||||||
let format = this._gconf.get_string(FORMAT_KEY);
|
|
||||||
this._12hrRadio.active = (format == "12-hour");
|
|
||||||
this._24hrRadio.active = (format == "24-hour");
|
|
||||||
|
|
||||||
this._dateCheck.active = this._gconf.get_bool(SHOW_DATE_KEY);
|
|
||||||
this._secondsCheck.active = this._gconf.get_bool(SHOW_SECONDS_KEY);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onResponse: function() {
|
|
||||||
this._dialog.destroy();
|
|
||||||
this._gconf.notify_remove(this._notifyId);
|
|
||||||
this.emit('destroy');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(ClockPreferences.prototype);
|
|
||||||
|
|
||||||
function main(params) {
|
|
||||||
if ('progName' in params)
|
|
||||||
GLib.set_prgname(params['progName']);
|
|
||||||
Gtk.init(null, null);
|
|
||||||
|
|
||||||
let clockPrefs = new ClockPreferences(params['uiFile']);
|
|
||||||
clockPrefs.connect('destroy',
|
|
||||||
function() {
|
|
||||||
Gtk.main_quit();
|
|
||||||
});
|
|
||||||
clockPrefs.show();
|
|
||||||
|
|
||||||
Gtk.main();
|
|
||||||
}
|
|
@ -3,36 +3,26 @@ jsuidir = $(pkgdatadir)/js/ui
|
|||||||
dist_jsui_DATA = \
|
dist_jsui_DATA = \
|
||||||
altTab.js \
|
altTab.js \
|
||||||
appDisplay.js \
|
appDisplay.js \
|
||||||
appFavorites.js \
|
appIcon.js \
|
||||||
boxpointer.js \
|
button.js \
|
||||||
calendar.js \
|
|
||||||
chrome.js \
|
chrome.js \
|
||||||
dash.js \
|
dash.js \
|
||||||
dnd.js \
|
dnd.js \
|
||||||
docDisplay.js \
|
docDisplay.js \
|
||||||
environment.js \
|
environment.js \
|
||||||
extensionSystem.js \
|
|
||||||
genericDisplay.js \
|
genericDisplay.js \
|
||||||
lightbox.js \
|
lightbox.js \
|
||||||
link.js \
|
link.js \
|
||||||
lookingGlass.js \
|
lookingGlass.js \
|
||||||
magnifier.js \
|
|
||||||
magnifierDBus.js \
|
|
||||||
main.js \
|
main.js \
|
||||||
messageTray.js \
|
|
||||||
notificationDaemon.js \
|
|
||||||
overview.js \
|
overview.js \
|
||||||
panel.js \
|
panel.js \
|
||||||
placeDisplay.js \
|
places.js \
|
||||||
runDialog.js \
|
runDialog.js \
|
||||||
scripting.js \
|
|
||||||
search.js \
|
|
||||||
shellDBus.js \
|
shellDBus.js \
|
||||||
statusMenu.js \
|
sidebar.js \
|
||||||
telepathyClient.js \
|
|
||||||
tweener.js \
|
tweener.js \
|
||||||
windowAttentionHandler.js \
|
widget.js \
|
||||||
|
widgetBox.js \
|
||||||
windowManager.js \
|
windowManager.js \
|
||||||
workspacesView.js \
|
workspaces.js
|
||||||
workspaceSwitcherPopup.js \
|
|
||||||
workspace.js
|
|
||||||
|
1070
js/ui/altTab.js
1645
js/ui/appDisplay.js
@ -1,120 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
function AppFavorites() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppFavorites.prototype = {
|
|
||||||
FAVORITE_APPS_KEY: 'favorite_apps',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._favorites = {};
|
|
||||||
this._gconf = Shell.GConf.get_default();
|
|
||||||
this._gconf.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged));
|
|
||||||
this._reload();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onFavsChanged: function() {
|
|
||||||
this._reload();
|
|
||||||
this.emit('changed');
|
|
||||||
},
|
|
||||||
|
|
||||||
_reload: function() {
|
|
||||||
let ids = Shell.GConf.get_default().get_string_list('favorite_apps');
|
|
||||||
let appSys = Shell.AppSystem.get_default();
|
|
||||||
let apps = ids.map(function (id) {
|
|
||||||
return appSys.get_app(id);
|
|
||||||
}).filter(function (app) {
|
|
||||||
return app != null;
|
|
||||||
});
|
|
||||||
this._favorites = {};
|
|
||||||
for (let i = 0; i < apps.length; i++) {
|
|
||||||
let app = apps[i];
|
|
||||||
this._favorites[app.get_id()] = app;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getIds: function() {
|
|
||||||
let ret = [];
|
|
||||||
for (let id in this._favorites)
|
|
||||||
ret.push(id);
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
|
|
||||||
getFavoriteMap: function() {
|
|
||||||
return this._favorites;
|
|
||||||
},
|
|
||||||
|
|
||||||
getFavorites: function() {
|
|
||||||
let ret = [];
|
|
||||||
for (let id in this._favorites)
|
|
||||||
ret.push(this._favorites[id]);
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
|
|
||||||
isFavorite: function(appId) {
|
|
||||||
return appId in this._favorites;
|
|
||||||
},
|
|
||||||
|
|
||||||
_addFavorite: function(appId) {
|
|
||||||
if (appId in this._favorites)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let app = Shell.AppSystem.get_default().get_app(appId);
|
|
||||||
|
|
||||||
if (!app)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let ids = this._getIds();
|
|
||||||
ids.push(appId);
|
|
||||||
this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
|
|
||||||
this._favorites[appId] = app;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
addFavorite: function(appId) {
|
|
||||||
if (!this._addFavorite(appId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let app = Shell.AppSystem.get_default().get_app(appId);
|
|
||||||
|
|
||||||
Main.overview.infoBar.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
|
|
||||||
this._removeFavorite(appId);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeFavorite: function(appId) {
|
|
||||||
if (!appId in this._favorites)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let ids = this._getIds().filter(function (id) { return id != appId; });
|
|
||||||
this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
removeFavorite: function(appId) {
|
|
||||||
if (!this._removeFavorite(appId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Main.overview.infoBar.setMessage(_("%s has been removed from your favorites.").format(this._favorites[appId].get_name()),
|
|
||||||
Lang.bind(this, function () {
|
|
||||||
this._addFavorite(appId);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(AppFavorites.prototype);
|
|
||||||
|
|
||||||
var appFavoritesInstance = null;
|
|
||||||
function getAppFavorites() {
|
|
||||||
if (appFavoritesInstance == null)
|
|
||||||
appFavoritesInstance = new AppFavorites();
|
|
||||||
return appFavoritesInstance;
|
|
||||||
}
|
|
572
js/ui/appIcon.js
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Workspaces = imports.ui.workspaces;
|
||||||
|
|
||||||
|
const GLOW_COLOR = new Clutter.Color();
|
||||||
|
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
||||||
|
const GLOW_PADDING_HORIZONTAL = 3;
|
||||||
|
const GLOW_PADDING_VERTICAL = 3;
|
||||||
|
|
||||||
|
const APPICON_ICON_SIZE = 48;
|
||||||
|
|
||||||
|
const APPICON_PADDING = 1;
|
||||||
|
const APPICON_BORDER_WIDTH = 1;
|
||||||
|
const APPICON_CORNER_RADIUS = 4;
|
||||||
|
|
||||||
|
const APPICON_MENU_POPUP_TIMEOUT_MS = 600;
|
||||||
|
|
||||||
|
const APPICON_DEFAULT_BORDER_COLOR = new Clutter.Color();
|
||||||
|
APPICON_DEFAULT_BORDER_COLOR.from_pixel(0x787878ff);
|
||||||
|
const APPICON_MENU_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
|
||||||
|
const APPICON_MENU_FONT = 'Sans 14px';
|
||||||
|
const APPICON_MENU_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_COLOR.from_pixel(0xffffffff);
|
||||||
|
const APPICON_MENU_SELECTED_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
|
||||||
|
const APPICON_MENU_SEPARATOR_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
|
||||||
|
const APPICON_MENU_BORDER_WIDTH = 1;
|
||||||
|
const APPICON_MENU_ARROW_SIZE = 12;
|
||||||
|
const APPICON_MENU_CORNER_RADIUS = 4;
|
||||||
|
const APPICON_MENU_PADDING = 4;
|
||||||
|
|
||||||
|
const TRANSPARENT_COLOR = new Clutter.Color();
|
||||||
|
TRANSPARENT_COLOR.from_pixel(0x00000000);
|
||||||
|
|
||||||
|
const MenuType = { NONE: 0, ON_RIGHT: 1, BELOW: 2 };
|
||||||
|
|
||||||
|
function AppIcon(appInfo, menuType) {
|
||||||
|
this._init(appInfo, menuType || MenuType.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppIcon.prototype = {
|
||||||
|
_init : function(appInfo, menuType) {
|
||||||
|
this.appInfo = appInfo;
|
||||||
|
this._menuType = menuType;
|
||||||
|
|
||||||
|
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
border: APPICON_BORDER_WIDTH,
|
||||||
|
corner_radius: APPICON_CORNER_RADIUS,
|
||||||
|
padding: APPICON_PADDING,
|
||||||
|
reactive: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
this.highlight_border_color = APPICON_DEFAULT_BORDER_COLOR;
|
||||||
|
|
||||||
|
if (menuType != MenuType.NONE) {
|
||||||
|
this.windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
||||||
|
for (let i = 0; i < this.windows.length; i++) {
|
||||||
|
this.windows[i].connect('notify::user-time', Lang.bind(this, this._resortWindows));
|
||||||
|
}
|
||||||
|
this._resortWindows();
|
||||||
|
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, this._updateMenuOnButtonPress));
|
||||||
|
this.actor.connect('notify::hover', Lang.bind(this, this._updateMenuOnHoverChanged));
|
||||||
|
this.actor.connect('activate', Lang.bind(this, this._updateMenuOnActivate));
|
||||||
|
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
this._menu = null;
|
||||||
|
} else
|
||||||
|
this.windows = [];
|
||||||
|
|
||||||
|
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
|
width: APPICON_ICON_SIZE,
|
||||||
|
height: APPICON_ICON_SIZE });
|
||||||
|
this.icon = appInfo.create_icon_texture(APPICON_ICON_SIZE);
|
||||||
|
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
let nameBox = new Shell.GenericContainer();
|
||||||
|
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
|
||||||
|
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
|
||||||
|
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
|
||||||
|
this._nameBox = nameBox;
|
||||||
|
|
||||||
|
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
|
font_name: "Sans 12px",
|
||||||
|
line_alignment: Pango.Alignment.CENTER,
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
text: appInfo.get_name() });
|
||||||
|
nameBox.add_actor(this._name);
|
||||||
|
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
|
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
|
||||||
|
for (let i = 0; i < this.windows.length && i < 3; i++) {
|
||||||
|
let glow = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
|
glowPath, -1, -1);
|
||||||
|
glow.keep_aspect_ratio = false;
|
||||||
|
this._glowBox.append(glow, Big.BoxPackFlags.EXPAND);
|
||||||
|
}
|
||||||
|
this._nameBox.add_actor(this._glowBox);
|
||||||
|
this._glowBox.lower(this._name);
|
||||||
|
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
|
||||||
|
let [min, natural] = this._name.get_preferred_width(forHeight);
|
||||||
|
alloc.min_size = min + GLOW_PADDING_HORIZONTAL * 2;
|
||||||
|
alloc.natural_size = natural + GLOW_PADDING_HORIZONTAL * 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
|
||||||
|
let [min, natural] = this._name.get_preferred_height(forWidth);
|
||||||
|
alloc.min_size = min + GLOW_PADDING_VERTICAL * 2;
|
||||||
|
alloc.natural_size = natural + GLOW_PADDING_VERTICAL * 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxAllocate: function (nameBox, box, flags) {
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
let [minWidth, naturalWidth] = this._name.get_preferred_width(-1);
|
||||||
|
let [minHeight, naturalHeight] = this._name.get_preferred_height(-1);
|
||||||
|
let availWidth = box.x2 - box.x1;
|
||||||
|
let availHeight = box.y2 - box.y1;
|
||||||
|
let targetWidth = availWidth;
|
||||||
|
let xPadding = 0;
|
||||||
|
if (naturalWidth < availWidth) {
|
||||||
|
xPadding = Math.floor((availWidth - naturalWidth) / 2);
|
||||||
|
}
|
||||||
|
childBox.x1 = xPadding;
|
||||||
|
childBox.x2 = availWidth - xPadding;
|
||||||
|
childBox.y1 = GLOW_PADDING_VERTICAL;
|
||||||
|
childBox.y2 = availHeight - GLOW_PADDING_VERTICAL;
|
||||||
|
this._name.allocate(childBox, flags);
|
||||||
|
|
||||||
|
// Now the glow
|
||||||
|
if (this._glowBox != null) {
|
||||||
|
let glowPaddingHoriz = Math.max(0, xPadding - GLOW_PADDING_HORIZONTAL);
|
||||||
|
glowPaddingHoriz = Math.max(GLOW_PADDING_HORIZONTAL, glowPaddingHoriz);
|
||||||
|
childBox.x1 = glowPaddingHoriz;
|
||||||
|
childBox.x2 = availWidth - glowPaddingHoriz;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = availHeight;
|
||||||
|
this._glowBox.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_resortWindows: function() {
|
||||||
|
this.windows.sort(function (a, b) {
|
||||||
|
let visA = a.showing_on_its_workspace();
|
||||||
|
let visB = b.showing_on_its_workspace();
|
||||||
|
|
||||||
|
if (visA && !visB)
|
||||||
|
return -1;
|
||||||
|
else if (visB && !visA)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return b.get_user_time() - a.get_user_time();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// AppIcon itself is not a draggable, but if you want to make
|
||||||
|
// a subclass of it draggable, you can use this method to create
|
||||||
|
// a drag actor
|
||||||
|
createDragActor: function() {
|
||||||
|
return this.appInfo.create_icon_texture(APPICON_ICON_SIZE);
|
||||||
|
},
|
||||||
|
|
||||||
|
setHighlight: function(highlight) {
|
||||||
|
if (highlight) {
|
||||||
|
this.actor.border_color = this.highlight_border_color;
|
||||||
|
} else {
|
||||||
|
this.actor.border_color = TRANSPARENT_COLOR;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateMenuOnActivate: function(actor, event) {
|
||||||
|
if (this._menuTimeoutId != 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
this.emit('activate');
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateMenuOnHoverChanged: function() {
|
||||||
|
if (!this.actor.hover && this._menuTimeoutId != 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateMenuOnButtonPress: function(actor, event) {
|
||||||
|
if (this._menuTimeoutId != 0)
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = Mainloop.timeout_add(APPICON_MENU_POPUP_TIMEOUT_MS,
|
||||||
|
Lang.bind(this, this.popupMenu));
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
popupMenu: function() {
|
||||||
|
if (this._menuTimeoutId != 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.fake_release();
|
||||||
|
|
||||||
|
if (!this._menu) {
|
||||||
|
this._menu = new AppIconMenu(this, this._menuType);
|
||||||
|
this._menu.connect('highlight-window', Lang.bind(this, function (menu, window) {
|
||||||
|
this.highlightWindow(window);
|
||||||
|
}));
|
||||||
|
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
|
||||||
|
this.activateWindow(window);
|
||||||
|
}));
|
||||||
|
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
|
||||||
|
if (isPoppedUp)
|
||||||
|
this.menuPoppedUp();
|
||||||
|
else
|
||||||
|
this.menuPoppedDown();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._menu.popup();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Default implementations; AppDisplay.RunningWellItem overrides these
|
||||||
|
highlightWindow: function(window) {
|
||||||
|
this.emit('highlight-window', window);
|
||||||
|
},
|
||||||
|
|
||||||
|
activateWindow: function(window) {
|
||||||
|
this.emit('activate-window', window);
|
||||||
|
},
|
||||||
|
|
||||||
|
menuPoppedUp: function() {
|
||||||
|
this.emit('menu-popped-up', this._menu);
|
||||||
|
},
|
||||||
|
|
||||||
|
menuPoppedDown: function() {
|
||||||
|
this.emit('menu-popped-down', this._menu);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(AppIcon.prototype);
|
||||||
|
|
||||||
|
function AppIconMenu(source, type) {
|
||||||
|
this._init(source, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppIconMenu.prototype = {
|
||||||
|
_init: function(source, type) {
|
||||||
|
this._source = source;
|
||||||
|
this._type = type;
|
||||||
|
|
||||||
|
this.actor = new Shell.GenericContainer({ reactive: true });
|
||||||
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
|
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
|
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
|
|
||||||
|
this._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
border_color: source.highlight_border_color,
|
||||||
|
border: APPICON_MENU_BORDER_WIDTH,
|
||||||
|
background_color: APPICON_MENU_BACKGROUND_COLOR,
|
||||||
|
padding: 4,
|
||||||
|
corner_radius: APPICON_MENU_CORNER_RADIUS,
|
||||||
|
width: Main.overview._dash.actor.width * 0.75 });
|
||||||
|
this._windowContainer.connect('unselected', Lang.bind(this, this._onItemUnselected));
|
||||||
|
this._windowContainer.connect('selected', Lang.bind(this, this._onItemSelected));
|
||||||
|
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
|
||||||
|
this._windowContainer.connect('activate', Lang.bind(this, this._onItemActivate));
|
||||||
|
this.actor.add_actor(this._windowContainer);
|
||||||
|
|
||||||
|
// Stay popped up on release over application icon
|
||||||
|
this._windowContainer.set_persistent_source(this._source.actor);
|
||||||
|
|
||||||
|
// Intercept events while the menu has the pointer grab to do window-related effects
|
||||||
|
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
|
||||||
|
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
|
||||||
|
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
|
||||||
|
|
||||||
|
this._arrow = new Shell.DrawingArea();
|
||||||
|
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
|
||||||
|
Shell.draw_box_pointer(texture,
|
||||||
|
this._type == MenuType.ON_RIGHT ? Clutter.Gravity.WEST : Clutter.Gravity.NORTH,
|
||||||
|
source.highlight_border_color,
|
||||||
|
APPICON_MENU_BACKGROUND_COLOR);
|
||||||
|
}));
|
||||||
|
this.actor.add_actor(this._arrow);
|
||||||
|
|
||||||
|
// Chain our visibility and lifecycle to that of the source
|
||||||
|
source.actor.connect('notify::mapped', Lang.bind(this, function () {
|
||||||
|
if (!source.actor.mapped)
|
||||||
|
this._windowContainer.popdown();
|
||||||
|
}));
|
||||||
|
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
|
||||||
|
|
||||||
|
global.stage.add_actor(this.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||||
|
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
|
||||||
|
if (this._type == MenuType.ON_RIGHT) {
|
||||||
|
min += APPICON_MENU_ARROW_SIZE;
|
||||||
|
natural += APPICON_MENU_ARROW_SIZE;
|
||||||
|
}
|
||||||
|
alloc.min_size = min;
|
||||||
|
alloc.natural_size = natural;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||||
|
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
|
||||||
|
if (this._type == MenuType.BELOW) {
|
||||||
|
min += APPICON_MENU_ARROW_SIZE;
|
||||||
|
natural += APPICON_MENU_ARROW_SIZE;
|
||||||
|
}
|
||||||
|
alloc.min_size = min;
|
||||||
|
alloc.natural_size = natural;
|
||||||
|
},
|
||||||
|
|
||||||
|
_allocate: function(actor, box, flags) {
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
|
||||||
|
let width = box.x2 - box.x1;
|
||||||
|
let height = box.y2 - box.y1;
|
||||||
|
|
||||||
|
if (this._type == MenuType.ON_RIGHT) {
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = APPICON_MENU_ARROW_SIZE;
|
||||||
|
childBox.y1 = Math.floor((height / 2) - (APPICON_MENU_ARROW_SIZE / 2));
|
||||||
|
childBox.y2 = childBox.y1 + APPICON_MENU_ARROW_SIZE;
|
||||||
|
this._arrow.allocate(childBox, flags);
|
||||||
|
|
||||||
|
childBox.x1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
|
||||||
|
childBox.x2 = width;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = height;
|
||||||
|
this._windowContainer.allocate(childBox, flags);
|
||||||
|
} else /* MenuType.BELOW */ {
|
||||||
|
childBox.x1 = Math.floor((width / 2) - (APPICON_MENU_ARROW_SIZE / 2));
|
||||||
|
childBox.x2 = childBox.x1 + APPICON_MENU_ARROW_SIZE;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = APPICON_MENU_ARROW_SIZE;
|
||||||
|
this._arrow.allocate(childBox, flags);
|
||||||
|
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = width;
|
||||||
|
childBox.y1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
|
||||||
|
childBox.y2 = height;
|
||||||
|
this._windowContainer.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplay: function() {
|
||||||
|
this._windowContainer.remove_all();
|
||||||
|
|
||||||
|
let windows = this._source.windows;
|
||||||
|
|
||||||
|
this._windowContainer.show();
|
||||||
|
|
||||||
|
let iconsDiffer = false;
|
||||||
|
let texCache = Shell.TextureCache.get_default();
|
||||||
|
let firstIcon = windows[0].mini_icon;
|
||||||
|
for (let i = 1; i < windows.length; i++) {
|
||||||
|
if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
|
||||||
|
iconsDiffer = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
|
|
||||||
|
let currentWorkspaceWindows = windows.filter(function (w) {
|
||||||
|
return w.get_workspace() == activeWorkspace;
|
||||||
|
});
|
||||||
|
let otherWorkspaceWindows = windows.filter(function (w) {
|
||||||
|
return w.get_workspace() != activeWorkspace;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._appendWindows(currentWorkspaceWindows, iconsDiffer);
|
||||||
|
if (currentWorkspaceWindows.length > 0 && otherWorkspaceWindows.length > 0) {
|
||||||
|
this._appendSeparator();
|
||||||
|
}
|
||||||
|
this._appendWindows(otherWorkspaceWindows, iconsDiffer);
|
||||||
|
|
||||||
|
this._appendSeparator();
|
||||||
|
|
||||||
|
this._newWindowMenuItem = this._appendMenuItem(null, _("New Window"));
|
||||||
|
|
||||||
|
this._highlightedItem = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendSeparator: function () {
|
||||||
|
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
|
||||||
|
box.append(new Clutter.Rectangle({ height: 1,
|
||||||
|
color: APPICON_MENU_SEPARATOR_COLOR }),
|
||||||
|
Big.BoxPackFlags.EXPAND);
|
||||||
|
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendMenuItem: function(iconTexture, labelText) {
|
||||||
|
/* Use padding here rather than spacing in the box above so that
|
||||||
|
* we have a larger reactive area.
|
||||||
|
*/
|
||||||
|
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
padding_top: 4,
|
||||||
|
padding_bottom: 4,
|
||||||
|
spacing: 4,
|
||||||
|
reactive: true });
|
||||||
|
let vCenter;
|
||||||
|
if (iconTexture != null) {
|
||||||
|
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
|
vCenter.append(iconTexture, Big.BoxPackFlags.NONE);
|
||||||
|
box.append(vCenter, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
|
let label = new Clutter.Text({ text: labelText,
|
||||||
|
font_name: APPICON_MENU_FONT,
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
color: APPICON_MENU_COLOR });
|
||||||
|
vCenter.append(label, Big.BoxPackFlags.NONE);
|
||||||
|
box.append(vCenter, Big.BoxPackFlags.NONE);
|
||||||
|
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
|
||||||
|
return box;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendWindows: function (windows, iconsDiffer) {
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
let metaWindow = windows[i];
|
||||||
|
|
||||||
|
let icon = null;
|
||||||
|
if (iconsDiffer) {
|
||||||
|
icon = Shell.TextureCache.get_default().bind_pixbuf_property(metaWindow, "mini-icon");
|
||||||
|
}
|
||||||
|
let box = this._appendMenuItem(icon, metaWindow.title);
|
||||||
|
box._window = metaWindow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
popup: function() {
|
||||||
|
let [stageX, stageY] = this._source.actor.get_transformed_position();
|
||||||
|
let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
|
||||||
|
|
||||||
|
this._redisplay();
|
||||||
|
|
||||||
|
this._windowContainer.popup(0, Main.currentTime());
|
||||||
|
|
||||||
|
this.emit('popup', true);
|
||||||
|
|
||||||
|
let x, y;
|
||||||
|
if (this._type == MenuType.ON_RIGHT) {
|
||||||
|
x = Math.floor(stageX + stageWidth);
|
||||||
|
y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
|
||||||
|
} else {
|
||||||
|
x = Math.floor(stageX + (stageWidth / 2) - (this.actor.width / 2));
|
||||||
|
y = Math.floor(stageY + stageHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.set_position(x, y);
|
||||||
|
this.actor.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
popdown: function() {
|
||||||
|
this._windowContainer.popdown();
|
||||||
|
this.emit('popup', false);
|
||||||
|
this.actor.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
selectWindow: function(metaWindow) {
|
||||||
|
this._selectMenuItemForWindow(metaWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
_findMetaWindowForActor: function (actor) {
|
||||||
|
if (actor._delegate instanceof Workspaces.WindowClone)
|
||||||
|
return actor._delegate.metaWindow;
|
||||||
|
else if (actor.get_meta_window)
|
||||||
|
return actor.get_meta_window();
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// This function is called while the menu has a pointer grab; what we want
|
||||||
|
// to do is see if the mouse was released over a window representation
|
||||||
|
_onMenuButtonRelease: function (actor, event) {
|
||||||
|
let metaWindow = this._findMetaWindowForActor(event.get_source());
|
||||||
|
if (metaWindow) {
|
||||||
|
this.emit('activate-window', metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateHighlight: function (item) {
|
||||||
|
if (this._highlightedItem) {
|
||||||
|
this._highlightedItem.background_color = TRANSPARENT_COLOR;
|
||||||
|
this.emit('highlight-window', null);
|
||||||
|
}
|
||||||
|
this._highlightedItem = item;
|
||||||
|
if (this._highlightedItem) {
|
||||||
|
this._highlightedItem.background_color = APPICON_MENU_SELECTED_COLOR;
|
||||||
|
let window = this._highlightedItem._window;
|
||||||
|
if (window)
|
||||||
|
this.emit('highlight-window', window);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_selectMenuItemForWindow: function (metaWindow) {
|
||||||
|
let children = this._windowContainer.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
let child = children[i];
|
||||||
|
let menuMetaWindow = child._window;
|
||||||
|
if (menuMetaWindow == metaWindow)
|
||||||
|
this._updateHighlight(child);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called while menu has a pointer grab
|
||||||
|
_onMenuEnter: function (actor, event) {
|
||||||
|
let metaWindow = this._findMetaWindowForActor(event.get_source());
|
||||||
|
if (metaWindow) {
|
||||||
|
this._selectMenuItemForWindow(metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called while menu has a pointer grab
|
||||||
|
_onMenuLeave: function (actor, event) {
|
||||||
|
let metaWindow = this._findMetaWindowForActor(event.get_source());
|
||||||
|
if (metaWindow) {
|
||||||
|
this._updateHighlight(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onItemUnselected: function (actor, child) {
|
||||||
|
this._updateHighlight(null);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onItemSelected: function (actor, child) {
|
||||||
|
this._updateHighlight(child);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onItemActivate: function (actor, child) {
|
||||||
|
if (child._window) {
|
||||||
|
let metaWindow = child._window;
|
||||||
|
this.emit('activate-window', metaWindow);
|
||||||
|
} else if (child == this._newWindowMenuItem) {
|
||||||
|
this._source.appInfo.launch();
|
||||||
|
this.emit('activate-window', null);
|
||||||
|
}
|
||||||
|
this.popdown();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onWindowSelectionCancelled: function () {
|
||||||
|
this.emit('highlight-window', null);
|
||||||
|
this.popdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(AppIconMenu.prototype);
|
@ -1,164 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Cairo = imports.cairo;
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BoxPointer:
|
|
||||||
* @side: A St.Side type; currently only St.Side.TOP is implemented
|
|
||||||
* @binProperties: Properties to set on contained bin
|
|
||||||
*
|
|
||||||
* An actor which displays a triangle "arrow" pointing to a given
|
|
||||||
* side. The .bin property is a container in which content can be
|
|
||||||
* placed. The arrow position may be controlled via setArrowOrigin().
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function BoxPointer(side, binProperties) {
|
|
||||||
this._init(side, binProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
BoxPointer.prototype = {
|
|
||||||
_init: function(arrowSide, binProperties) {
|
|
||||||
if (arrowSide != St.Side.TOP)
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
this._arrowSide = arrowSide;
|
|
||||||
this._arrowOrigin = 0;
|
|
||||||
this.actor = new St.Bin({ x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
this._container = new Shell.GenericContainer();
|
|
||||||
this.actor.set_child(this._container);
|
|
||||||
this._container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
|
||||||
this._container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
|
||||||
this._container.connect('allocate', Lang.bind(this, this._allocate));
|
|
||||||
this.bin = new St.Bin(binProperties);
|
|
||||||
this._container.add_actor(this.bin);
|
|
||||||
this._border = new St.DrawingArea();
|
|
||||||
this._border.connect('repaint', Lang.bind(this, this._drawBorder));
|
|
||||||
this._container.add_actor(this._border);
|
|
||||||
this.bin.raise(this._border);
|
|
||||||
},
|
|
||||||
|
|
||||||
_adjustAllocationForArrow: function(isWidth, alloc) {
|
|
||||||
let themeNode = this.actor.get_theme_node();
|
|
||||||
let found, borderWidth, base, rise;
|
|
||||||
[found, borderWidth] = themeNode.get_length('-arrow-border-width', false);
|
|
||||||
alloc.min_size += borderWidth * 2;
|
|
||||||
alloc.natural_size += borderWidth * 2;
|
|
||||||
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
|
|
||||||
|| (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
|
|
||||||
let [found, rise] = themeNode.get_length('-arrow-rise', false);
|
|
||||||
alloc.min_size += rise;
|
|
||||||
alloc.natural_size += rise;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
|
||||||
let [minInternalSize, natInternalSize] = this.bin.get_preferred_width(forHeight);
|
|
||||||
alloc.min_size = minInternalSize;
|
|
||||||
alloc.natural_size = natInternalSize;
|
|
||||||
this._adjustAllocationForArrow(true, alloc);
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
|
||||||
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth);
|
|
||||||
alloc.min_size = minSize;
|
|
||||||
alloc.natural_size = naturalSize;
|
|
||||||
this._adjustAllocationForArrow(false, alloc);
|
|
||||||
},
|
|
||||||
|
|
||||||
_allocate: function(actor, box, flags) {
|
|
||||||
let themeNode = this.actor.get_theme_node();
|
|
||||||
let found, borderWidth, borderRadius, rise, base;
|
|
||||||
[found, borderWidth] = themeNode.get_length('-arrow-border-width', false);
|
|
||||||
[found, rise] = themeNode.get_length('-arrow-rise', false);
|
|
||||||
let childBox = new Clutter.ActorBox();
|
|
||||||
let availWidth = box.x2 - box.x1;
|
|
||||||
let availHeight = box.y2 - box.y1;
|
|
||||||
|
|
||||||
childBox.x1 = 0;
|
|
||||||
childBox.y1 = 0;
|
|
||||||
childBox.x2 = availWidth;
|
|
||||||
childBox.y2 = availHeight;
|
|
||||||
this._border.allocate(childBox, flags);
|
|
||||||
switch (this._arrowSide) {
|
|
||||||
case St.Side.TOP:
|
|
||||||
childBox.x1 = borderWidth;
|
|
||||||
childBox.y1 = rise + borderWidth;
|
|
||||||
childBox.x2 = availWidth - borderWidth;
|
|
||||||
childBox.y2 = availHeight - borderWidth;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.bin.allocate(childBox, flags);
|
|
||||||
},
|
|
||||||
|
|
||||||
_drawBorder: function(area) {
|
|
||||||
let themeNode = this.actor.get_theme_node();
|
|
||||||
|
|
||||||
let found, borderWidth, borderRadius, rise, base;
|
|
||||||
[found, borderWidth] = themeNode.get_length('-arrow-border-width', false);
|
|
||||||
[found, base] = themeNode.get_length('-arrow-base', false);
|
|
||||||
[found, rise] = themeNode.get_length('-arrow-rise', false);
|
|
||||||
[found, borderRadius] = themeNode.get_length('-arrow-border-radius', false);
|
|
||||||
|
|
||||||
let halfBorder = borderWidth / 2;
|
|
||||||
|
|
||||||
let borderColor = new Clutter.Color();
|
|
||||||
themeNode.get_color('-arrow-border-color', false, borderColor);
|
|
||||||
let backgroundColor = new Clutter.Color();
|
|
||||||
themeNode.get_color('-arrow-background-color', false, backgroundColor);
|
|
||||||
|
|
||||||
let [width, height] = area.get_surface_size();
|
|
||||||
let [boxWidth, boxHeight] = [width, height];
|
|
||||||
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) {
|
|
||||||
boxHeight -= rise;
|
|
||||||
} else {
|
|
||||||
boxWidth -= rise;
|
|
||||||
}
|
|
||||||
let cr = area.get_context();
|
|
||||||
Clutter.cairo_set_source_color(cr, borderColor);
|
|
||||||
if (this._arrowSide == St.Side.TOP) {
|
|
||||||
cr.translate(0, rise);
|
|
||||||
}
|
|
||||||
cr.moveTo(borderRadius, halfBorder);
|
|
||||||
if (this._arrowSide == St.Side.TOP) {
|
|
||||||
cr.translate(0, -rise);
|
|
||||||
let halfBase = Math.floor(base/2);
|
|
||||||
cr.lineTo(this._arrowOrigin - halfBase, rise + halfBorder);
|
|
||||||
cr.lineTo(this._arrowOrigin, halfBorder);
|
|
||||||
cr.lineTo(this._arrowOrigin + halfBase, rise + halfBorder);
|
|
||||||
cr.translate(0, rise);
|
|
||||||
}
|
|
||||||
cr.lineTo(boxWidth - borderRadius, halfBorder);
|
|
||||||
cr.arc(boxWidth - borderRadius - halfBorder, borderRadius + halfBorder, borderRadius,
|
|
||||||
3*Math.PI/2, Math.PI*2);
|
|
||||||
cr.lineTo(boxWidth - halfBorder, boxHeight - borderRadius);
|
|
||||||
cr.arc(boxWidth - borderRadius - halfBorder, boxHeight - borderRadius - halfBorder, borderRadius,
|
|
||||||
0, Math.PI/2);
|
|
||||||
cr.lineTo(borderRadius, boxHeight - halfBorder);
|
|
||||||
cr.arc(borderRadius + halfBorder, boxHeight - borderRadius - halfBorder, borderRadius,
|
|
||||||
Math.PI/2, Math.PI);
|
|
||||||
cr.lineTo(halfBorder, borderRadius);
|
|
||||||
cr.arc(borderRadius + halfBorder, borderRadius + halfBorder, borderRadius,
|
|
||||||
Math.PI, 3*Math.PI/2);
|
|
||||||
Clutter.cairo_set_source_color(cr, backgroundColor);
|
|
||||||
cr.fillPreserve();
|
|
||||||
Clutter.cairo_set_source_color(cr, borderColor);
|
|
||||||
cr.setLineWidth(borderWidth);
|
|
||||||
cr.stroke();
|
|
||||||
},
|
|
||||||
|
|
||||||
// @origin: Coordinate specifying middle of the arrow, along
|
|
||||||
// the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
|
|
||||||
// the left for St.Side.TOP and St.Side.BOTTOM.
|
|
||||||
setArrowOrigin: function(origin) {
|
|
||||||
if (this._arrowOrigin != origin) {
|
|
||||||
this._arrowOrigin = origin;
|
|
||||||
this._border.queue_repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
172
js/ui/button.js
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
|
||||||
|
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
|
||||||
|
|
||||||
|
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
|
||||||
|
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaa66);
|
||||||
|
|
||||||
|
const DEFAULT_TEXT_COLOR = new Clutter.Color();
|
||||||
|
DEFAULT_TEXT_COLOR.from_pixel(0x000000ff);
|
||||||
|
|
||||||
|
const DEFAULT_FONT = 'Sans Bold 16px';
|
||||||
|
|
||||||
|
// Padding on the left and right side of the button.
|
||||||
|
const SIDE_PADDING = 14;
|
||||||
|
|
||||||
|
function Button(widget, buttonColor, pressedButtonColor, textColor, font) {
|
||||||
|
this._init(widget, buttonColor, pressedButtonColor, textColor, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.prototype = {
|
||||||
|
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
|
||||||
|
this._buttonColor = buttonColor
|
||||||
|
if (buttonColor == null)
|
||||||
|
this._buttonColor = DEFAULT_BUTTON_COLOR;
|
||||||
|
|
||||||
|
this._pressedButtonColor = pressedButtonColor
|
||||||
|
if (pressedButtonColor == null)
|
||||||
|
this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
|
||||||
|
|
||||||
|
this._textColor = textColor;
|
||||||
|
if (textColor == null)
|
||||||
|
this._textColor = DEFAULT_TEXT_COLOR;
|
||||||
|
|
||||||
|
this._font = font;
|
||||||
|
if (font == null)
|
||||||
|
this._font = DEFAULT_FONT;
|
||||||
|
|
||||||
|
this._isBetweenPressAndRelease = false;
|
||||||
|
this._mouseIsOverButton = false;
|
||||||
|
|
||||||
|
this.actor = new Shell.ButtonBox({ reactive: true,
|
||||||
|
corner_radius: 5,
|
||||||
|
padding_left: SIDE_PADDING,
|
||||||
|
padding_right: SIDE_PADDING,
|
||||||
|
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
y_align: Big.BoxAlignment.CENTER
|
||||||
|
});
|
||||||
|
if (typeof widgetOrText == 'string') {
|
||||||
|
this._widget = new Clutter.Text({ font_name: this._font,
|
||||||
|
color: this._textColor,
|
||||||
|
text: widgetOrText });
|
||||||
|
} else {
|
||||||
|
this._widget = widgetOrText;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
this.actor.connect('notify::hover', Lang.bind(this, this._updateColors));
|
||||||
|
this.actor.connect('notify::pressed', Lang.bind(this, this._updateColors));
|
||||||
|
this.actor.connect('notify::active', Lang.bind(this, this._updateColors));
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateColors : function() {
|
||||||
|
if (this.actor.active || this.actor.pressed)
|
||||||
|
this.actor.backgroundColor = this._pressedButtonColor;
|
||||||
|
else if (this.actor.hover)
|
||||||
|
this.actor.backgroundColor = this._buttonColor;
|
||||||
|
else
|
||||||
|
this.actor.backgroundColor = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(Button.prototype);
|
||||||
|
|
||||||
|
/* Delay before the icon should appear, in seconds after the pointer has entered the parent */
|
||||||
|
const ANIMATION_TIME = 0.25;
|
||||||
|
|
||||||
|
/* This is an icon button that fades in/out when mouse enters/leaves the parent.
|
||||||
|
* A delay is used before the fading starts. You can force it to be shown if needed.
|
||||||
|
*
|
||||||
|
* parent -- used to show/hide the button depending on mouse entering/leaving it
|
||||||
|
* size -- size in pixels of both the button and the icon it contains
|
||||||
|
* texture -- optional, must be used if the texture for the icon is already created (else, use setIconFromName)
|
||||||
|
*/
|
||||||
|
function IconButton(parent, size, texture) {
|
||||||
|
this._init(parent, size, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton.prototype = {
|
||||||
|
_init : function(parent, size, texture) {
|
||||||
|
this._size = size;
|
||||||
|
if (texture)
|
||||||
|
this.actor = texture;
|
||||||
|
else
|
||||||
|
this.actor = new Clutter.Texture({ width: this._size, height: this._size });
|
||||||
|
this.actor.set_reactive(true);
|
||||||
|
this.actor.set_opacity(0);
|
||||||
|
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
|
||||||
|
this._shouldHide = false;
|
||||||
|
// Nothing to do if the cursor has come back from a child of the parent actor
|
||||||
|
if (actor.get_children().indexOf(event.get_related()) != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._fadeIn();
|
||||||
|
}));
|
||||||
|
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
|
||||||
|
// Nothing to do if the cursor has merely entered a child of the parent actor
|
||||||
|
if (actor.get_children().indexOf(event.get_related()) != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remember that we should not be visible to hide the button if forceShow is unset
|
||||||
|
if (this._forceShow) {
|
||||||
|
this._shouldHide = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fadeOut();
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Private methods ///
|
||||||
|
|
||||||
|
setIconFromName : function(iconName) {
|
||||||
|
let iconTheme = Gtk.IconTheme.get_default();
|
||||||
|
let iconInfo = iconTheme.lookup_icon(iconName, this._size, 0);
|
||||||
|
if (!iconInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let iconPath = iconInfo.get_filename();
|
||||||
|
this.actor.set_from_file(iconPath);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Useful if we want to show the button immediately,
|
||||||
|
// e.g. in case the mouse is already in the parent when the button is created
|
||||||
|
show : function() {
|
||||||
|
this.actor.set_opacity(255);
|
||||||
|
},
|
||||||
|
|
||||||
|
// If show is true, prevents the button from fading out
|
||||||
|
forceShow : function(show) {
|
||||||
|
this._forceShow = show;
|
||||||
|
// Hide the button if it should have been hidden under normal conditions
|
||||||
|
if (!this._forceShow && this._shouldHide) {
|
||||||
|
this._fadeOut();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Private methods ///
|
||||||
|
|
||||||
|
_fadeIn : function() {
|
||||||
|
Tweener.removeTweens(this.actor);
|
||||||
|
Tweener.addTween(this.actor, { opacity: 255,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition :"easeInQuad" });
|
||||||
|
},
|
||||||
|
|
||||||
|
_fadeOut : function() {
|
||||||
|
Tweener.removeTweens(this.actor);
|
||||||
|
Tweener.addTween(this.actor, { opacity: 0,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition :"easeOutQuad" });
|
||||||
|
}
|
||||||
|
};
|
@ -1,182 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Gettext_gtk20 = imports.gettext.domain('gtk20');
|
|
||||||
|
|
||||||
const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
|
|
||||||
|
|
||||||
function _sameDay(dateA, dateB) {
|
|
||||||
return (dateA.getDate() == dateB.getDate() &&
|
|
||||||
dateA.getMonth() == dateB.getMonth() &&
|
|
||||||
dateA.getYear() == dateB.getYear());
|
|
||||||
}
|
|
||||||
|
|
||||||
function Calendar() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Calendar.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
// FIXME: This is actually the fallback method for GTK+ for the week start;
|
|
||||||
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
|
|
||||||
// should add a C function so we can do the full handling.
|
|
||||||
this._weekStart = NaN;
|
|
||||||
let weekStartString = Gettext_gtk20.gettext('calendar:week_start:0');
|
|
||||||
if (weekStartString.indexOf('calendar:week_start:') == 0) {
|
|
||||||
this._weekStart = parseInt(weekStartString.substring(20));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNaN(this._weekStart) || this._weekStart < 0 || this._weekStart > 6) {
|
|
||||||
log('Translation of "calendar:week_start:0" in GTK+ is not correct');
|
|
||||||
this._weekStart = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the ordering for month/year in the calendar heading
|
|
||||||
switch (Gettext_gtk20.gettext('calendar:MY')) {
|
|
||||||
case 'calendar:MY':
|
|
||||||
this._headerFormat = '%B %Y';
|
|
||||||
break;
|
|
||||||
case 'calendar:YM':
|
|
||||||
this._headerFormat = '%Y %B';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log('Translation of "calendar:MY" in GTK+ is not correct');
|
|
||||||
this._headerFormat = '%B %Y';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start off with the current date
|
|
||||||
this.date = new Date();
|
|
||||||
|
|
||||||
this.actor = new St.Table({ homogeneous: false,
|
|
||||||
style_class: 'calendar',
|
|
||||||
reactive: true });
|
|
||||||
|
|
||||||
this.actor.connect('scroll-event',
|
|
||||||
Lang.bind(this, this._onScroll));
|
|
||||||
|
|
||||||
// Top line of the calendar '<| September 2009 |>'
|
|
||||||
this._topBox = new St.BoxLayout();
|
|
||||||
this.actor.add(this._topBox,
|
|
||||||
{ row: 0, col: 0, col_span: 7 });
|
|
||||||
|
|
||||||
let [backlabel, forwardlabel] = ['<', '>'];
|
|
||||||
if (St.Widget.get_default_direction () == St.TextDirection.RTL) {
|
|
||||||
[backlabel, forwardlabel] = [forwardlabel, backlabel];
|
|
||||||
}
|
|
||||||
|
|
||||||
let back = new St.Button({ label: backlabel, style_class: 'calendar-change-month' });
|
|
||||||
this._topBox.add(back);
|
|
||||||
back.connect('clicked', Lang.bind(this, this._prevMonth));
|
|
||||||
|
|
||||||
this._dateLabel = new St.Label();
|
|
||||||
this._topBox.add(this._dateLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
|
|
||||||
|
|
||||||
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' });
|
|
||||||
this._topBox.add(forward);
|
|
||||||
forward.connect('clicked', Lang.bind(this, this._nextMonth));
|
|
||||||
|
|
||||||
// We need to figure out the abbreviated localized names for the days of the week;
|
|
||||||
// we do this by just getting the next 7 days starting from right now and then putting
|
|
||||||
// them in the right cell in the table. It doesn't matter if we add them in order
|
|
||||||
let iter = new Date(this.date);
|
|
||||||
iter.setSeconds(0); // Leap second protection. Hah!
|
|
||||||
iter.setHours(12);
|
|
||||||
for (let i = 0; i < 7; i++) {
|
|
||||||
this.actor.add(new St.Label({ text: iter.toLocaleFormat('%a') }),
|
|
||||||
{ row: 1,
|
|
||||||
col: (7 + iter.getDay() - this._weekStart) % 7,
|
|
||||||
x_fill: false, x_align: St.Align.END });
|
|
||||||
iter.setTime(iter.getTime() + MSECS_IN_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// All the children after this are days, and get removed when we update the calendar
|
|
||||||
this._firstDayIndex = this.actor.get_children().length;
|
|
||||||
|
|
||||||
this._update();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Sets the calendar to show a specific date
|
|
||||||
setDate: function(date) {
|
|
||||||
if (!_sameDay(date, this.date)) {
|
|
||||||
this.date = date;
|
|
||||||
this._update();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onScroll : function(actor, event) {
|
|
||||||
switch (event.get_scroll_direction()) {
|
|
||||||
case Clutter.ScrollDirection.UP:
|
|
||||||
case Clutter.ScrollDirection.LEFT:
|
|
||||||
this._prevMonth();
|
|
||||||
break;
|
|
||||||
case Clutter.ScrollDirection.DOWN:
|
|
||||||
case Clutter.ScrollDirection.RIGHT:
|
|
||||||
this._nextMonth();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_prevMonth: function() {
|
|
||||||
if (this.date.getMonth() == 0) {
|
|
||||||
this.date.setMonth(11);
|
|
||||||
this.date.setFullYear(this.date.getFullYear() - 1);
|
|
||||||
} else {
|
|
||||||
this.date.setMonth(this.date.getMonth() - 1);
|
|
||||||
}
|
|
||||||
this._update();
|
|
||||||
},
|
|
||||||
|
|
||||||
_nextMonth: function() {
|
|
||||||
if (this.date.getMonth() == 11) {
|
|
||||||
this.date.setMonth(0);
|
|
||||||
this.date.setFullYear(this.date.getFullYear() + 1);
|
|
||||||
} else {
|
|
||||||
this.date.setMonth(this.date.getMonth() + 1);
|
|
||||||
}
|
|
||||||
this._update();
|
|
||||||
},
|
|
||||||
|
|
||||||
_update: function() {
|
|
||||||
this._dateLabel.text = this.date.toLocaleFormat(this._headerFormat);
|
|
||||||
|
|
||||||
// Remove everything but the topBox and the weekday labels
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
for (let i = this._firstDayIndex; i < children.length; i++)
|
|
||||||
children[i].destroy();
|
|
||||||
|
|
||||||
// Start at the beginning of the week before the start of the month
|
|
||||||
let iter = new Date(this.date);
|
|
||||||
iter.setDate(1);
|
|
||||||
iter.setSeconds(0);
|
|
||||||
iter.setHours(12);
|
|
||||||
iter.setTime(iter.getTime() - (iter.getDay() - this._weekStart) * MSECS_IN_DAY);
|
|
||||||
|
|
||||||
let now = new Date();
|
|
||||||
|
|
||||||
let row = 2;
|
|
||||||
while (true) {
|
|
||||||
let label = new St.Label({ text: iter.getDate().toString() });
|
|
||||||
if (_sameDay(now, iter))
|
|
||||||
label.style_class = 'calendar-day calendar-today';
|
|
||||||
else if (iter.getMonth() != this.date.getMonth())
|
|
||||||
label.style_class = 'calendar-day calendar-other-month-day';
|
|
||||||
else
|
|
||||||
label.style_class = 'calendar-day';
|
|
||||||
this.actor.add(label,
|
|
||||||
{ row: row, col: (7 + iter.getDay() - this._weekStart) % 7,
|
|
||||||
x_fill: false, x_align: St.Align.END });
|
|
||||||
|
|
||||||
iter.setTime(iter.getTime() + MSECS_IN_DAY);
|
|
||||||
if (iter.getDay() == this._weekStart) {
|
|
||||||
// We stop on the first "first day of the week" after the month we are displaying
|
|
||||||
if (iter.getMonth() > this.date.getMonth() || iter.getYear() > this.date.getYear())
|
|
||||||
break;
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
281
js/ui/chrome.js
@ -5,28 +5,13 @@ const Lang = imports.lang;
|
|||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Params = imports.misc.params;
|
|
||||||
|
|
||||||
// This manages the shell "chrome"; the UI that's visible in the
|
// This manages the shell "chrome"; the UI that's visible in the
|
||||||
// normal mode (ie, outside the Overview), that surrounds the main
|
// normal mode (ie, outside the Overview), that surrounds the main
|
||||||
// workspace content.
|
// workspace content.
|
||||||
|
|
||||||
const Visibility = {
|
|
||||||
FULL: 1,
|
|
||||||
FULLSCREEN: 2,
|
|
||||||
OVERVIEW: 3
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultParams = {
|
|
||||||
visibleInOverview: false,
|
|
||||||
visibleInFullscreen: false,
|
|
||||||
affectsStruts: true,
|
|
||||||
affectsInputRegion: true
|
|
||||||
};
|
|
||||||
|
|
||||||
function Chrome() {
|
function Chrome() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -34,13 +19,12 @@ function Chrome() {
|
|||||||
Chrome.prototype = {
|
Chrome.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
// The group itself has zero size so it doesn't interfere with DND
|
// The group itself has zero size so it doesn't interfere with DND
|
||||||
this.actor = new Shell.GenericContainer({ width: 0, height: 0 });
|
this.actor = new Clutter.Group({ width: 0, height: 0 });
|
||||||
Main.uiGroup.add_actor(this.actor);
|
global.stage.add_actor(this.actor);
|
||||||
this.actor.connect('allocate', Lang.bind(this, this._allocated));
|
this.nonOverviewActor = new Clutter.Group();
|
||||||
|
this.actor.add_actor(this.nonOverviewActor);
|
||||||
|
|
||||||
this._inFullscreen = false;
|
this._obscuredByFullscreen = false;
|
||||||
this._inOverview = false;
|
|
||||||
this.visibility = Visibility.FULL;
|
|
||||||
|
|
||||||
this._trackedActors = [];
|
this._trackedActors = [];
|
||||||
|
|
||||||
@ -59,12 +43,6 @@ Chrome.prototype = {
|
|||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
_allocated: function(actor, box, flags) {
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
for (let i = 0; i < children.length; i++)
|
|
||||||
children[i].allocate_preferred_size(flags);
|
|
||||||
},
|
|
||||||
|
|
||||||
_verifyAncestry: function(actor, ancestor) {
|
_verifyAncestry: function(actor, ancestor) {
|
||||||
while (actor) {
|
while (actor) {
|
||||||
if (actor == ancestor)
|
if (actor == ancestor)
|
||||||
@ -76,7 +54,7 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
// addActor:
|
// addActor:
|
||||||
// @actor: an actor to add to the chrome layer
|
// @actor: an actor to add to the chrome layer
|
||||||
// @params: (optional) additional params
|
// @shapeActor: optional "shape actor".
|
||||||
//
|
//
|
||||||
// Adds @actor to the chrome layer and extends the input region
|
// Adds @actor to the chrome layer and extends the input region
|
||||||
// and window manager struts to include it. (Window manager struts
|
// and window manager struts to include it. (Window manager struts
|
||||||
@ -86,60 +64,59 @@ Chrome.prototype = {
|
|||||||
// in its visibility will affect the input region, but NOT the
|
// in its visibility will affect the input region, but NOT the
|
||||||
// struts.
|
// struts.
|
||||||
//
|
//
|
||||||
// If %visibleInOverview is %true in @params, @actor will remain
|
// If @shapeActor is provided, it will be used instead of @actor
|
||||||
// visible when the overview is brought up. Otherwise it will
|
// for the input region/strut shape. (This lets you have things like
|
||||||
// automatically be hidden. Likewise, if %visibleInFullscreen is
|
// drop shadows in @actor that don't affect the struts.) It must
|
||||||
// %true, the actor will be visible even when a fullscreen window
|
// be a child of @actor. Alternatively, you can pass %null for
|
||||||
// should be covering it.
|
// @shapeActor to indicate that @actor should not affect the input
|
||||||
//
|
// region or struts at all.
|
||||||
// If %affectsStruts or %affectsInputRegion is %false, the actor
|
addActor: function(actor, shapeActor) {
|
||||||
// will not have the indicated effect.
|
if (shapeActor === undefined)
|
||||||
addActor: function(actor, params) {
|
shapeActor = actor;
|
||||||
this.actor.add_actor(actor);
|
else if (shapeActor && !this._verifyAncestry(shapeActor, actor))
|
||||||
this._trackActor(actor, params);
|
throw new Error('shapeActor is not a descendent of actor');
|
||||||
|
|
||||||
|
this.nonOverviewActor.add_actor(actor);
|
||||||
|
|
||||||
|
if (shapeActor)
|
||||||
|
this._trackActor(shapeActor, true, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
// trackActor:
|
// setVisibleInOverview:
|
||||||
// @actor: a descendant of the chrome to begin tracking
|
// @actor: an actor in the chrome layer
|
||||||
// @params: parameters describing how to track @actor
|
// @visible: Overview visibility
|
||||||
//
|
//
|
||||||
// Tells the chrome to track @actor, which must be a descendant
|
// By default, actors in the chrome layer are automatically hidden
|
||||||
// of an actor added via addActor(). This can be used to extend the
|
// when the Overview is shown. This can be used to override that
|
||||||
// struts or input region to cover specific children.
|
// behavior
|
||||||
//
|
setVisibleInOverview: function(actor, visible) {
|
||||||
// @params can have any of the same values as in addActor(), though
|
if (!this._verifyAncestry(actor, this.actor))
|
||||||
// some possibilities don't make sense (eg, trying to have a
|
|
||||||
// %visibleInOverview child of a non-%visibleInOverview parent).
|
|
||||||
// By default, @actor has the same params as its chrome ancestor.
|
|
||||||
trackActor: function(actor, params) {
|
|
||||||
let ancestor = actor.get_parent();
|
|
||||||
let index = this._findActor(ancestor);
|
|
||||||
while (ancestor && index == -1) {
|
|
||||||
ancestor = ancestor.get_parent();
|
|
||||||
index = this._findActor(ancestor);
|
|
||||||
}
|
|
||||||
if (!ancestor)
|
|
||||||
throw new Error('actor is not a descendent of the chrome layer');
|
throw new Error('actor is not a descendent of the chrome layer');
|
||||||
|
|
||||||
let ancestorData = this._trackedActors[index];
|
if (visible)
|
||||||
if (!params)
|
actor.reparent(this.actor);
|
||||||
params = {};
|
else
|
||||||
// We can't use Params.parse here because we want to drop
|
actor.reparent(this.nonOverviewActor);
|
||||||
// the extra values like ancestorData.actor
|
|
||||||
for (let prop in defaultParams) {
|
|
||||||
if (!params[prop])
|
|
||||||
params[prop] = ancestorData[prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
this._trackActor(actor, params);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// untrackActor:
|
// addInputRegionActor:
|
||||||
// @actor: an actor previously tracked via trackActor()
|
// @actor: an actor to add to the stage input region
|
||||||
//
|
//
|
||||||
// Undoes the effect of trackActor()
|
// Adds @actor to the stage input region, as with addActor(), but
|
||||||
untrackActor: function(actor) {
|
// for actors that are already descendants of the chrome layer.
|
||||||
this._untrackActor(actor);
|
addInputRegionActor: function(actor) {
|
||||||
|
if (!this._verifyAncestry(actor, this.actor))
|
||||||
|
throw new Error('actor is not a descendent of the chrome layer');
|
||||||
|
|
||||||
|
this._trackActor(actor, true, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// removeInputRegionActor:
|
||||||
|
// @actor: an actor previously added to the stage input region
|
||||||
|
//
|
||||||
|
// Undoes the effect of addInputRegionActor()
|
||||||
|
removeInputRegionActor: function(actor) {
|
||||||
|
this._untrackActor(actor, true, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
// removeActor:
|
// removeActor:
|
||||||
@ -147,8 +124,11 @@ Chrome.prototype = {
|
|||||||
//
|
//
|
||||||
// Removes @actor from the chrome layer
|
// Removes @actor from the chrome layer
|
||||||
removeActor: function(actor) {
|
removeActor: function(actor) {
|
||||||
this.actor.remove_actor(actor);
|
if (actor.get_parent() == this.nonOverviewActor)
|
||||||
this._untrackActor(actor);
|
this.nonOverviewActor.remove_actor(actor);
|
||||||
|
else
|
||||||
|
this.actor.remove_actor(actor);
|
||||||
|
this._untrackActor(actor, true, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
_findActor: function(actor) {
|
_findActor: function(actor) {
|
||||||
@ -160,79 +140,92 @@ Chrome.prototype = {
|
|||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
_trackActor: function(actor, params) {
|
_trackActor: function(actor, inputRegion, strut) {
|
||||||
if (this._findActor(actor) != -1)
|
let actorData;
|
||||||
throw new Error('trying to re-track existing chrome actor');
|
let i = this._findActor(actor);
|
||||||
|
|
||||||
|
if (i != -1) {
|
||||||
|
actorData = this._trackedActors[i];
|
||||||
|
if (inputRegion)
|
||||||
|
actorData.inputRegion++;
|
||||||
|
if (strut)
|
||||||
|
actorData.strut++;
|
||||||
|
if (!inputRegion && !strut)
|
||||||
|
actorData.children++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actorData = { actor: actor,
|
||||||
|
inputRegion: inputRegion ? 1 : 0,
|
||||||
|
strut: strut ? 1 : 0,
|
||||||
|
children: 0 };
|
||||||
|
|
||||||
let actorData = Params.parse(params, defaultParams);
|
|
||||||
actorData.actor = actor;
|
|
||||||
actorData.visibleId = actor.connect('notify::visible',
|
actorData.visibleId = actor.connect('notify::visible',
|
||||||
Lang.bind(this, this._queueUpdateRegions));
|
Lang.bind(this, this._queueUpdateRegions));
|
||||||
actorData.allocationId = actor.connect('notify::allocation',
|
actorData.allocationId = actor.connect('notify::allocation',
|
||||||
Lang.bind(this, this._queueUpdateRegions));
|
Lang.bind(this, this._queueUpdateRegions));
|
||||||
actorData.parentSetId = actor.connect('parent-set',
|
actorData.parentSetId = actor.connect('parent-set',
|
||||||
Lang.bind(this, this._actorReparented));
|
Lang.bind(this, this._actorReparented));
|
||||||
// Note that destroying actor will unset its parent, so we don't
|
|
||||||
// need to connect to 'destroy' too.
|
|
||||||
|
|
||||||
this._trackedActors.push(actorData);
|
this._trackedActors.push(actorData);
|
||||||
this._queueUpdateRegions();
|
|
||||||
|
actor = actor.get_parent();
|
||||||
|
if (actor != this.actor && actor != this.nonOverviewActor)
|
||||||
|
this._trackActor(actor, false, false);
|
||||||
|
|
||||||
|
if (inputRegion || strut)
|
||||||
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
_untrackActor: function(actor) {
|
_untrackActor: function(actor, inputRegion, strut) {
|
||||||
let i = this._findActor(actor);
|
let i = this._findActor(actor);
|
||||||
|
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
return;
|
return;
|
||||||
let actorData = this._trackedActors[i];
|
let actorData = this._trackedActors[i];
|
||||||
|
|
||||||
this._trackedActors.splice(i, 1);
|
if (inputRegion)
|
||||||
actor.disconnect(actorData.visibleId);
|
actorData.inputRegion--;
|
||||||
actor.disconnect(actorData.allocationId);
|
if (strut)
|
||||||
actor.disconnect(actorData.parentSetId);
|
actorData.strut--;
|
||||||
|
if (!inputRegion && !strut)
|
||||||
|
actorData.children--;
|
||||||
|
|
||||||
this._queueUpdateRegions();
|
if (actorData.inputRegion <= 0 && actorData.strut <= 0 && actorData.children <= 0) {
|
||||||
|
this._trackedActors.splice(i, 1);
|
||||||
|
actor.disconnect(actorData.visibleId);
|
||||||
|
actor.disconnect(actorData.allocationId);
|
||||||
|
actor.disconnect(actorData.parentSetId);
|
||||||
|
|
||||||
|
actor = actor.get_parent();
|
||||||
|
if (actor && actor != this.actor && actor != this.nonOverviewActor)
|
||||||
|
this._untrackActor(actor, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputRegion || strut)
|
||||||
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
_actorReparented: function(actor, oldParent) {
|
_actorReparented: function(actor, oldParent) {
|
||||||
if (!this._verifyAncestry(actor, this.actor))
|
if (this._verifyAncestry(actor, this.actor)) {
|
||||||
this._untrackActor(actor);
|
let newParent = actor.get_parent();
|
||||||
},
|
if (newParent != this.actor && newParent != this.nonOverviewActor)
|
||||||
|
this._trackActor(newParent, false, false);
|
||||||
_updateVisibility: function() {
|
|
||||||
for (let i = 0; i < this._trackedActors.length; i++) {
|
|
||||||
let actorData = this._trackedActors[i];
|
|
||||||
if (this._inOverview && !actorData.visibleInOverview)
|
|
||||||
this.actor.set_skip_paint(actorData.actor, true);
|
|
||||||
else if (this._inFullscreen && !actorData.visibleInFullscreen)
|
|
||||||
this.actor.set_skip_paint(actorData.actor, true);
|
|
||||||
else
|
|
||||||
this.actor.set_skip_paint(actorData.actor, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
let newVisibility;
|
|
||||||
if (this._inOverview)
|
|
||||||
newVisibility = Visibility.OVERVIEW;
|
|
||||||
else if (this._inFullscreen)
|
|
||||||
newVisibility = Visibility.FULLSCREEN;
|
|
||||||
else
|
|
||||||
newVisibility = Visibility.FULL;
|
|
||||||
|
|
||||||
if (newVisibility != this.visibility) {
|
|
||||||
this.visibility = newVisibility;
|
|
||||||
this.emit('visibility-changed', this.visibility);
|
|
||||||
}
|
}
|
||||||
|
if (oldParent != this.actor && oldParent != this.nonOverviewActor)
|
||||||
|
this._untrackActor(oldParent, false, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
_overviewShowing: function() {
|
_overviewShowing: function() {
|
||||||
this._inOverview = true;
|
this.actor.show();
|
||||||
this._updateVisibility();
|
this.nonOverviewActor.hide();
|
||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
_overviewHidden: function() {
|
_overviewHidden: function() {
|
||||||
this._inOverview = false;
|
if (this._obscuredByFullscreen)
|
||||||
this._updateVisibility();
|
this.actor.hide();
|
||||||
|
this.nonOverviewActor.show();
|
||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -244,12 +237,11 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
_windowsRestacked: function() {
|
_windowsRestacked: function() {
|
||||||
let windows = global.get_windows();
|
let windows = global.get_windows();
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
|
|
||||||
// The chrome layer should be visible unless there is a window
|
// The chrome layer should be visible unless there is a window
|
||||||
// with layer FULLSCREEN, or a window with layer
|
// with layer FULLSCREEN, or a window with layer
|
||||||
// OVERRIDE_REDIRECT that covers the whole screen.
|
// OVERRIDE_REDIRECT that covers the whole screen.
|
||||||
// ('override_redirect' is not actually a layer above all
|
// ("override_redirect" is not actually a layer above all
|
||||||
// other windows, but this seems to be how mutter treats it
|
// other windows, but this seems to be how mutter treats it
|
||||||
// currently...) If we wanted to be extra clever, we could
|
// currently...) If we wanted to be extra clever, we could
|
||||||
// figure out when an OVERRIDE_REDIRECT window was trying to
|
// figure out when an OVERRIDE_REDIRECT window was trying to
|
||||||
@ -258,40 +250,28 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
// @windows is sorted bottom to top.
|
// @windows is sorted bottom to top.
|
||||||
|
|
||||||
let wasInFullscreen = this._inFullscreen;
|
this._obscuredByFullscreen = false;
|
||||||
this._inFullscreen = false;
|
|
||||||
for (let i = windows.length - 1; i > -1; i--) {
|
for (let i = windows.length - 1; i > -1; i--) {
|
||||||
let layer = windows[i].get_meta_window().get_layer();
|
let layer = windows[i].get_meta_window().get_layer();
|
||||||
|
|
||||||
// There are 3 cases we check here for:
|
|
||||||
// 1.) Monitor sized window
|
|
||||||
// 2.) Window with a position somewhere on the primary screen having the _NET_WM_FULLSCREEN flag set
|
|
||||||
// 3.) Window that is partly off screen (tries to hide its decorations) which might have negative coords
|
|
||||||
// We check for 1.) and 2.) by checking if the upper right corner is on the primary monitor, but avoid the case
|
|
||||||
// where it overlaps with the secondary screen (like window.x + window.width == primary.x + primary.width)
|
|
||||||
// For 3.) we just ignore negative values as they don't really make sense
|
|
||||||
|
|
||||||
if (layer == Meta.StackLayer.FULLSCREEN) {
|
|
||||||
if (Math.max(windows[i].x, 0) >= primary.x && Math.max(windows[i].x, 0) < primary.x + primary.width &&
|
|
||||||
Math.max(windows[i].y, 0) >= primary.y && Math.max(windows[i].y, 0) < primary.y + primary.height) {
|
|
||||||
this._inFullscreen = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
|
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
|
||||||
if (windows[i].x <= primary.x &&
|
if (windows[i].x <= 0 &&
|
||||||
windows[i].x + windows[i].width >= primary.x + primary.width &&
|
windows[i].x + windows[i].width >= global.screen_width &&
|
||||||
windows[i].y <= primary.y &&
|
windows[i].y <= 0 &&
|
||||||
windows[i].y + windows[i].height >= primary.y + primary.height) {
|
windows[i].y + windows[i].height >= global.screen_height) {
|
||||||
this._inFullscreen = true;
|
this._obscuredByFullscreen = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (layer == Meta.StackLayer.FULLSCREEN) {
|
||||||
|
this._obscuredByFullscreen = true;
|
||||||
|
break;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._inFullscreen != wasInFullscreen) {
|
let shouldBeVisible = !this._obscuredByFullscreen || Main.overview.visible;
|
||||||
this._updateVisibility();
|
if (this.actor.visible != shouldBeVisible) {
|
||||||
|
this.actor.visible = shouldBeVisible;
|
||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -303,7 +283,7 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
for (i = 0; i < this._trackedActors.length; i++) {
|
for (i = 0; i < this._trackedActors.length; i++) {
|
||||||
let actorData = this._trackedActors[i];
|
let actorData = this._trackedActors[i];
|
||||||
if (!actorData.affectsInputRegion && !actorData.affectsStruts)
|
if (!actorData.inputRegion && !actorData.strut)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
let [x, y] = actorData.actor.get_transformed_position();
|
let [x, y] = actorData.actor.get_transformed_position();
|
||||||
@ -314,12 +294,10 @@ Chrome.prototype = {
|
|||||||
h = Math.round(h);
|
h = Math.round(h);
|
||||||
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h});
|
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h});
|
||||||
|
|
||||||
if (actorData.affectsInputRegion &&
|
if (actorData.inputRegion && actorData.actor.get_paint_visibility())
|
||||||
actorData.actor.get_paint_visibility() &&
|
|
||||||
!this.actor.get_skip_paint(actorData.actor))
|
|
||||||
rects.push(rect);
|
rects.push(rect);
|
||||||
|
|
||||||
if (!actorData.affectsStruts)
|
if (!actorData.strut)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Metacity wants to know what side of the screen the
|
// Metacity wants to know what side of the screen the
|
||||||
@ -371,4 +349,3 @@ Chrome.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(Chrome.prototype);
|
|
||||||
|
1201
js/ui/dash.js
138
js/ui/dnd.js
@ -1,18 +1,11 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
const St = imports.gi.St;
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
|
|
||||||
// Time to scale down to maxDragActorSize
|
|
||||||
const SCALE_ANIMATION_TIME = 0.25;
|
|
||||||
// Time to animate to original position on cancel
|
|
||||||
const SNAP_BACK_ANIMATION_TIME = 0.25;
|
const SNAP_BACK_ANIMATION_TIME = 0.25;
|
||||||
|
|
||||||
let eventHandlerActor = null;
|
let eventHandlerActor = null;
|
||||||
@ -23,7 +16,7 @@ function _getEventHandlerActor() {
|
|||||||
eventHandlerActor = new Clutter.Rectangle();
|
eventHandlerActor = new Clutter.Rectangle();
|
||||||
eventHandlerActor.width = 0;
|
eventHandlerActor.width = 0;
|
||||||
eventHandlerActor.height = 0;
|
eventHandlerActor.height = 0;
|
||||||
Main.uiGroup.add_actor(eventHandlerActor);
|
global.stage.add_actor(eventHandlerActor);
|
||||||
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
|
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
|
||||||
// when you've grabbed the pointer.
|
// when you've grabbed the pointer.
|
||||||
eventHandlerActor.connect('event',
|
eventHandlerActor.connect('event',
|
||||||
@ -34,49 +27,31 @@ function _getEventHandlerActor() {
|
|||||||
return eventHandlerActor;
|
return eventHandlerActor;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _Draggable(actor, params) {
|
function _Draggable(actor, manualMode) {
|
||||||
this._init(actor, params);
|
this._init(actor, manualMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Draggable.prototype = {
|
_Draggable.prototype = {
|
||||||
_init : function(actor, params) {
|
_init : function(actor, manualMode) {
|
||||||
params = Params.parse(params, { manualMode: false,
|
|
||||||
dragActorMaxSize: undefined,
|
|
||||||
dragActorOpacity: undefined });
|
|
||||||
|
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
if (!params.manualMode)
|
if (!manualMode)
|
||||||
this.actor.connect('button-press-event',
|
this.actor.connect('button-press-event',
|
||||||
Lang.bind(this, this._onButtonPress));
|
Lang.bind(this, this._onButtonPress));
|
||||||
|
|
||||||
this.actor.connect('destroy', Lang.bind(this, function() {
|
|
||||||
this.disconnectAll();
|
|
||||||
}));
|
|
||||||
this._onEventId = null;
|
this._onEventId = null;
|
||||||
|
|
||||||
this._dragActorMaxSize = params.dragActorMaxSize;
|
|
||||||
this._dragActorOpacity = params.dragActorOpacity;
|
|
||||||
|
|
||||||
this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
|
this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
|
||||||
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
||||||
this._snapBackInProgress = false; // The drag has been cancelled and the item is in the process of snapping back.
|
this._snapBackInProgress = false; // The drag has been cancelled and the item is in the process of snapping back.
|
||||||
},
|
},
|
||||||
|
|
||||||
_onButtonPress : function (actor, event) {
|
_onButtonPress : function (actor, event) {
|
||||||
if (event.get_button() != 1)
|
// FIXME: we should make sure it's button 1, but we can't currently
|
||||||
return false;
|
// check that from JavaScript
|
||||||
|
|
||||||
if (Tweener.getTweenCount(actor))
|
if (Tweener.getTweenCount(actor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._buttonDown = true;
|
this._buttonDown = true;
|
||||||
// special case St.Clickable: grabbing the pointer would mess up the
|
this._grabActor();
|
||||||
// internal state, so we start the drag manually on hover change
|
|
||||||
if (this.actor instanceof St.Clickable)
|
|
||||||
this.actor.connect('notify::hover',
|
|
||||||
Lang.bind(this, this._onClickableHoverChanged));
|
|
||||||
else
|
|
||||||
this._grabActor();
|
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
this._dragStartX = stageX;
|
this._dragStartX = stageX;
|
||||||
@ -85,15 +60,6 @@ _Draggable.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onClickableHoverChanged: function(button) {
|
|
||||||
if (button.hover || !button.held)
|
|
||||||
return;
|
|
||||||
|
|
||||||
button.fake_release();
|
|
||||||
this.startDrag(this._dragStartX, this._dragStartY,
|
|
||||||
global.get_current_time());
|
|
||||||
},
|
|
||||||
|
|
||||||
_grabActor: function() {
|
_grabActor: function() {
|
||||||
Clutter.grab_pointer(this.actor);
|
Clutter.grab_pointer(this.actor);
|
||||||
this._onEventId = this.actor.connect('event',
|
this._onEventId = this.actor.connect('event',
|
||||||
@ -174,8 +140,8 @@ _Draggable.prototype = {
|
|||||||
this._ungrabActor();
|
this._ungrabActor();
|
||||||
this._grabEvents();
|
this._grabEvents();
|
||||||
|
|
||||||
this._dragX = this._dragStartX = stageX;
|
this._dragStartX = stageX;
|
||||||
this._dragY = this._dragStartY = stageY;
|
this._dragStartY = stageY;
|
||||||
|
|
||||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||||
@ -188,9 +154,10 @@ _Draggable.prototype = {
|
|||||||
// the dragActor over it. Otherwise, center it
|
// the dragActor over it. Otherwise, center it
|
||||||
// around the pointer
|
// around the pointer
|
||||||
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
||||||
|
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
|
||||||
let x, y;
|
let x, y;
|
||||||
if (stageX > sourceX && stageX <= sourceX + this._dragActor.width &&
|
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
|
||||||
stageY > sourceY && stageY <= sourceY + this._dragActor.height) {
|
stageY > sourceY && stageY <= sourceY + sourceHeight) {
|
||||||
x = sourceX;
|
x = sourceX;
|
||||||
y = sourceY;
|
y = sourceY;
|
||||||
} else {
|
} else {
|
||||||
@ -226,45 +193,6 @@ _Draggable.prototype = {
|
|||||||
|
|
||||||
this._dragActor.reparent(this.actor.get_stage());
|
this._dragActor.reparent(this.actor.get_stage());
|
||||||
this._dragActor.raise_top();
|
this._dragActor.raise_top();
|
||||||
|
|
||||||
this._dragOrigOpacity = this._dragActor.opacity;
|
|
||||||
if (this._dragActorOpacity != undefined)
|
|
||||||
this._dragActor.opacity = this._dragActorOpacity;
|
|
||||||
|
|
||||||
this._snapBackX = this._dragStartX + this._dragOffsetX;
|
|
||||||
this._snapBackY = this._dragStartY + this._dragOffsetY;
|
|
||||||
this._snapBackScale = this._dragActor.scale_x;
|
|
||||||
|
|
||||||
if (this._dragActorMaxSize != undefined) {
|
|
||||||
let [scaledWidth, scaledHeight] = this._dragActor.get_transformed_size();
|
|
||||||
let currentSize = Math.max(scaledWidth, scaledHeight);
|
|
||||||
if (currentSize > this._dragActorMaxSize) {
|
|
||||||
let scale = this._dragActorMaxSize / currentSize;
|
|
||||||
let origScale = this._dragActor.scale_x;
|
|
||||||
let origDragOffsetX = this._dragOffsetX;
|
|
||||||
let origDragOffsetY = this._dragOffsetY;
|
|
||||||
|
|
||||||
// The position of the actor changes as we scale
|
|
||||||
// around the drag position, but we can't just tween
|
|
||||||
// to the final position because that tween would
|
|
||||||
// fight with updates as the user continues dragging
|
|
||||||
// the mouse; instead we do the position computations in
|
|
||||||
// an onUpdate() function.
|
|
||||||
Tweener.addTween(this._dragActor,
|
|
||||||
{ scale_x: scale * origScale,
|
|
||||||
scale_y: scale * origScale,
|
|
||||||
time: SCALE_ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onUpdate: function() {
|
|
||||||
let currentScale = this._dragActor.scale_x / origScale;
|
|
||||||
this._dragOffsetX = currentScale * origDragOffsetX;
|
|
||||||
this._dragOffsetY = currentScale * origDragOffsetY;
|
|
||||||
this._dragActor.set_position(this._dragX + this._dragOffsetX,
|
|
||||||
this._dragY + this._dragOffsetY);
|
|
||||||
},
|
|
||||||
onUpdateScope: this });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_maybeStartDrag: function(event) {
|
_maybeStartDrag: function(event) {
|
||||||
@ -283,8 +211,6 @@ _Draggable.prototype = {
|
|||||||
|
|
||||||
_updateDragPosition : function (event) {
|
_updateDragPosition : function (event) {
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
this._dragX = stageX;
|
|
||||||
this._dragY = stageY;
|
|
||||||
|
|
||||||
// If we are dragging, update the position
|
// If we are dragging, update the position
|
||||||
if (this._dragActor) {
|
if (this._dragActor) {
|
||||||
@ -294,7 +220,8 @@ _Draggable.prototype = {
|
|||||||
// we have to temporarily hide this._dragActor.
|
// we have to temporarily hide this._dragActor.
|
||||||
this._dragActor.hide();
|
this._dragActor.hide();
|
||||||
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
||||||
stageX, stageY);
|
stageX + this._dragOffsetX,
|
||||||
|
stageY + this._dragOffsetY);
|
||||||
this._dragActor.show();
|
this._dragActor.show();
|
||||||
while (target) {
|
while (target) {
|
||||||
if (target._delegate && target._delegate.handleDragOver) {
|
if (target._delegate && target._delegate.handleDragOver) {
|
||||||
@ -303,8 +230,8 @@ _Draggable.prototype = {
|
|||||||
// We can check the return value of the function and break the loop if it's true if we don't want
|
// We can check the return value of the function and break the loop if it's true if we don't want
|
||||||
// to continue checking the parents.
|
// to continue checking the parents.
|
||||||
target._delegate.handleDragOver(this.actor._delegate, this._dragActor,
|
target._delegate.handleDragOver(this.actor._delegate, this._dragActor,
|
||||||
(stageX - targX) / target.scale_x,
|
(stageX + this._dragOffsetX - targX) / target.scale_x,
|
||||||
(stageY - targY) / target.scale_y,
|
(stageY + this._dragOffsetY - targY) / target.scale_y,
|
||||||
event.get_time());
|
event.get_time());
|
||||||
}
|
}
|
||||||
target = target.get_parent();
|
target = target.get_parent();
|
||||||
@ -353,8 +280,8 @@ _Draggable.prototype = {
|
|||||||
// Snap back to the actor source if the source is still around, snap back
|
// Snap back to the actor source if the source is still around, snap back
|
||||||
// to the original location if the actor itself was being dragged or the
|
// to the original location if the actor itself was being dragged or the
|
||||||
// source is no longer around.
|
// source is no longer around.
|
||||||
let snapBackX = this._snapBackX;
|
let snapBackX = this._dragStartX + this._dragOffsetX;
|
||||||
let snapBackY = this._snapBackY;
|
let snapBackY = this._dragStartY + this._dragOffsetY;
|
||||||
if (this._dragActorSource && this._dragActorSource.visible) {
|
if (this._dragActorSource && this._dragActorSource.visible) {
|
||||||
[snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
|
[snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
|
||||||
}
|
}
|
||||||
@ -364,11 +291,8 @@ _Draggable.prototype = {
|
|||||||
Tweener.addTween(this._dragActor,
|
Tweener.addTween(this._dragActor,
|
||||||
{ x: snapBackX,
|
{ x: snapBackX,
|
||||||
y: snapBackY,
|
y: snapBackY,
|
||||||
scale_x: this._snapBackScale,
|
|
||||||
scale_y: this._snapBackScale,
|
|
||||||
opacity: this._dragOrigOpacity,
|
|
||||||
time: SNAP_BACK_ANIMATION_TIME,
|
time: SNAP_BACK_ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad',
|
transition: "easeOutQuad",
|
||||||
onComplete: this._onSnapBackComplete,
|
onComplete: this._onSnapBackComplete,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [this._dragActor, eventTime]
|
onCompleteParams: [this._dragActor, eventTime]
|
||||||
@ -402,24 +326,10 @@ Signals.addSignalMethods(_Draggable.prototype);
|
|||||||
/**
|
/**
|
||||||
* makeDraggable:
|
* makeDraggable:
|
||||||
* @actor: Source actor
|
* @actor: Source actor
|
||||||
* @params: (optional) Additional parameters
|
* @manualMode: If given, do not automatically start drag and drop on click
|
||||||
*
|
*
|
||||||
* Create an object which controls drag and drop for the given actor.
|
* Create an object which controls drag and drop for the given actor.
|
||||||
*
|
|
||||||
* If %manualMode is %true in @params, do not automatically start
|
|
||||||
* drag and drop on click
|
|
||||||
*
|
|
||||||
* If %dragActorMaxSize is present in @params, the drag actor will
|
|
||||||
* be scaled down to be no larger than that size in pixels.
|
|
||||||
*
|
|
||||||
* If %dragActorOpacity is present in @params, the drag actor will
|
|
||||||
* will be set to have that opacity during the drag.
|
|
||||||
*
|
|
||||||
* Note that when the drag actor is the source actor and the drop
|
|
||||||
* succeeds, the actor scale and opacity aren't reset; if the drop
|
|
||||||
* target wants to reuse the actor, it's up to the drop target to
|
|
||||||
* reset these values.
|
|
||||||
*/
|
*/
|
||||||
function makeDraggable(actor, params) {
|
function makeDraggable(actor, manualMode) {
|
||||||
return new _Draggable(actor, params);
|
return new _Draggable(actor, manualMode);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
@ -7,18 +8,13 @@ const Lang = imports.lang;
|
|||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const St = imports.gi.St;
|
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const DocInfo = imports.misc.docInfo;
|
const DocInfo = imports.misc.docInfo;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
const GenericDisplay = imports.ui.genericDisplay;
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Search = imports.ui.search;
|
|
||||||
|
|
||||||
const MAX_DASH_DOCS = 50;
|
|
||||||
const DASH_DOCS_ICON_SIZE = 16;
|
const DASH_DOCS_ICON_SIZE = 16;
|
||||||
|
|
||||||
const DEFAULT_SPACING = 4;
|
const DEFAULT_SPACING = 4;
|
||||||
@ -41,7 +37,7 @@ DocDisplayItem.prototype = {
|
|||||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
|
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
|
||||||
this._docInfo = docInfo;
|
this._docInfo = docInfo;
|
||||||
|
|
||||||
this._setItemInfo(docInfo.name, '');
|
this._setItemInfo(docInfo.name, "");
|
||||||
|
|
||||||
this._timeoutTime = -1;
|
this._timeoutTime = -1;
|
||||||
this._resetTimeDisplay(currentSecs);
|
this._resetTimeDisplay(currentSecs);
|
||||||
@ -80,12 +76,12 @@ DocDisplayItem.prototype = {
|
|||||||
// Creates and returns a large preview icon, but only if this._docInfo is an image file
|
// Creates and returns a large preview icon, but only if this._docInfo is an image file
|
||||||
// and we were able to generate a pixbuf from it successfully.
|
// and we were able to generate a pixbuf from it successfully.
|
||||||
_createLargePreviewIcon : function() {
|
_createLargePreviewIcon : function() {
|
||||||
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf('image/') != 0)
|
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf("image/") != 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return St.TextureCache.get_default().load_uri_sync(St.TextureCachePolicy.NONE,
|
return Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.NONE,
|
||||||
this._docInfo.uri, -1, -1);
|
this._docInfo.uri, -1, -1);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// An exception will be raised when the image format isn't know
|
// An exception will be raised when the image format isn't know
|
||||||
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
|
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
|
||||||
@ -115,15 +111,15 @@ DocDisplayItem.prototype = {
|
|||||||
/* This class represents a display containing a collection of document items.
|
/* This class represents a display containing a collection of document items.
|
||||||
* The documents are sorted by how recently they were last visited.
|
* The documents are sorted by how recently they were last visited.
|
||||||
*/
|
*/
|
||||||
function DocDisplay(flags) {
|
function DocDisplay() {
|
||||||
this._init(flags);
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
DocDisplay.prototype = {
|
DocDisplay.prototype = {
|
||||||
__proto__: GenericDisplay.GenericDisplay.prototype,
|
__proto__: GenericDisplay.GenericDisplay.prototype,
|
||||||
|
|
||||||
_init : function(flags) {
|
_init : function() {
|
||||||
GenericDisplay.GenericDisplay.prototype._init.call(this, flags);
|
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||||
// We keep a single timeout callback for updating last visited times
|
// We keep a single timeout callback for updating last visited times
|
||||||
// for all the items in the display. This avoids creating individual
|
// for all the items in the display. This avoids creating individual
|
||||||
// callbacks for each item in the display. So proper time updates
|
// callbacks for each item in the display. So proper time updates
|
||||||
@ -140,7 +136,7 @@ DocDisplay.prototype = {
|
|||||||
// but redisplaying right away is cool when we use Zephyr.
|
// but redisplaying right away is cool when we use Zephyr.
|
||||||
// Also, we might be displaying remote documents, like Google Docs, in the future
|
// Also, we might be displaying remote documents, like Google Docs, in the future
|
||||||
// which might be edited by someone else.
|
// which might be edited by someone else.
|
||||||
this._redisplay(GenericDisplay.RedisplayFlags.NONE);
|
this._redisplay(false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.connect('destroy', Lang.bind(this, function (o) {
|
this.connect('destroy', Lang.bind(this, function (o) {
|
||||||
@ -155,8 +151,7 @@ DocDisplay.prototype = {
|
|||||||
_refreshCache : function() {
|
_refreshCache : function() {
|
||||||
if (!this._docsStale)
|
if (!this._docsStale)
|
||||||
return true;
|
return true;
|
||||||
this._allItems = {};
|
this._allItems = this._docManager.getItems();
|
||||||
Lang.copyProperties(this._docManager.getInfosByUri(), this._allItems);
|
|
||||||
this._docsStale = false;
|
this._docsStale = false;
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
@ -181,8 +176,13 @@ DocDisplay.prototype = {
|
|||||||
this._matchedItemKeys = [];
|
this._matchedItemKeys = [];
|
||||||
let docIdsToRemove = [];
|
let docIdsToRemove = [];
|
||||||
for (docId in this._allItems) {
|
for (docId in this._allItems) {
|
||||||
this._matchedItems[docId] = 1;
|
// this._allItems[docId].exists() checks if the resource still exists
|
||||||
this._matchedItemKeys.push(docId);
|
if (this._allItems[docId].exists()) {
|
||||||
|
this._matchedItems[docId] = 1;
|
||||||
|
this._matchedItemKeys.push(docId);
|
||||||
|
} else {
|
||||||
|
docIdsToRemove.push(docId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (docId in docIdsToRemove) {
|
for (docId in docIdsToRemove) {
|
||||||
@ -266,31 +266,26 @@ function DashDocDisplayItem(docInfo) {
|
|||||||
DashDocDisplayItem.prototype = {
|
DashDocDisplayItem.prototype = {
|
||||||
_init: function(docInfo) {
|
_init: function(docInfo) {
|
||||||
this._info = docInfo;
|
this._info = docInfo;
|
||||||
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
spacing: DEFAULT_SPACING,
|
||||||
this.actor = new St.Clickable({ style_class: 'recent-docs-item',
|
reactive: true });
|
||||||
reactive: true,
|
this.actor.connect('button-release-event', Lang.bind(this, function () {
|
||||||
x_align: St.Align.START });
|
|
||||||
|
|
||||||
let box = new St.BoxLayout({ style_class: 'recent-docs-item-box' });
|
|
||||||
this.actor.set_child(box);
|
|
||||||
|
|
||||||
box.add(this._icon);
|
|
||||||
|
|
||||||
let text = new St.Label({ text: docInfo.name });
|
|
||||||
box.add(text);
|
|
||||||
|
|
||||||
this.actor.connect('clicked', Lang.bind(this, function () {
|
|
||||||
docInfo.launch();
|
docInfo.launch();
|
||||||
Main.overview.hide();
|
Main.overview.hide();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.actor._delegate = this;
|
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
|
||||||
let draggable = DND.makeDraggable(this.actor);
|
let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
},
|
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
|
||||||
|
this.actor.append(iconBox, Big.BoxPackFlags.NONE);
|
||||||
|
let name = new Clutter.Text({ font_name: "Sans 14px",
|
||||||
|
color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
text: docInfo.name });
|
||||||
|
this.actor.append(name, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
getUri: function() {
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
return this._info.uri;
|
this.actor._delegate = this;
|
||||||
},
|
},
|
||||||
|
|
||||||
getDragActorSource: function() {
|
getDragActorSource: function() {
|
||||||
@ -322,14 +317,12 @@ DashDocDisplay.prototype = {
|
|||||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
|
|
||||||
|
|
||||||
this._actorsByUri = {};
|
|
||||||
|
|
||||||
this._docManager = DocInfo.getDocManager();
|
this._docManager = DocInfo.getDocManager();
|
||||||
this._docManager.connect('changed', Lang.bind(this, this._onDocsChanged));
|
this._docManager.connect('changed', Lang.bind(this, function(mgr) {
|
||||||
this._pendingDocsChange = true;
|
this._redisplay();
|
||||||
this._checkDocExistence = false;
|
}));
|
||||||
|
this._redisplay();
|
||||||
},
|
},
|
||||||
|
|
||||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||||
@ -358,119 +351,90 @@ DashDocDisplay.prototype = {
|
|||||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||||
let children = actor.get_children();
|
let children = actor.get_children();
|
||||||
|
|
||||||
// The width of an item is our allocated width, minus spacing, divided in half.
|
// Two columns, where we go vertically down first. So just take
|
||||||
this._itemWidth = Math.floor((forWidth - DEFAULT_SPACING) / 2);
|
// the height of half of the children as our preferred height.
|
||||||
|
|
||||||
let maxNatural = 0;
|
let firstColumnChildren = children.length / 2;
|
||||||
for (let i = 0; i < children.length; i++) {
|
|
||||||
|
alloc.min_size = 0;
|
||||||
|
for (let i = 0; i < firstColumnChildren; i++) {
|
||||||
let child = children[i];
|
let child = children[i];
|
||||||
let [minSize, naturalSize] = child.get_preferred_height(this._itemWidth);
|
let [minSize, naturalSize] = child.get_preferred_height(forWidth);
|
||||||
maxNatural = Math.max(maxNatural, naturalSize);
|
alloc.natural_size += naturalSize;
|
||||||
|
|
||||||
|
if (i > 0 && i < children.length - 1) {
|
||||||
|
alloc.min_size += DEFAULT_SPACING;
|
||||||
|
alloc.natural_size += DEFAULT_SPACING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._itemHeight = maxNatural;
|
|
||||||
|
|
||||||
let firstColumnChildren = Math.ceil(children.length / 2);
|
|
||||||
alloc.natural_size = (firstColumnChildren * maxNatural +
|
|
||||||
(firstColumnChildren - 1) * DEFAULT_SPACING);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_allocate: function(actor, box, flags) {
|
_allocate: function(actor, box, flags) {
|
||||||
let width = box.x2 - box.x1;
|
let width = box.x2 - box.x1;
|
||||||
let height = box.y2 - box.y1;
|
let height = box.y2 - box.y1;
|
||||||
|
|
||||||
// Make sure this._itemWidth/Height have been computed, even
|
|
||||||
// if the parent actor didn't check our size before allocating.
|
|
||||||
// (Not clear if that is required or not as a Clutter
|
|
||||||
// invariant; this is safe and cheap because of caching.)
|
|
||||||
actor.get_preferred_height(width);
|
|
||||||
|
|
||||||
let children = actor.get_children();
|
let children = actor.get_children();
|
||||||
|
|
||||||
let x = 0;
|
// The width of an item is our allocated width, minus spacing, divided in half.
|
||||||
let y = 0;
|
let itemWidth = Math.floor((width - DEFAULT_SPACING) / 2);
|
||||||
|
let x = box.x1;
|
||||||
|
let y = box.y1;
|
||||||
let columnIndex = 0;
|
let columnIndex = 0;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
// Loop over the children, going vertically down first. When we run
|
// Loop over the children, going vertically down first. When we run
|
||||||
// out of vertical space (our y variable is bigger than box.y2), switch
|
// out of vertical space (our y variable is bigger than box.y2), switch
|
||||||
// to the second column.
|
// to the second column.
|
||||||
while (i < children.length) {
|
for (; i < children.length; i++) {
|
||||||
let child = children[i];
|
let child = children[i];
|
||||||
|
|
||||||
if (y + this._itemHeight > box.y2) {
|
let [minSize, naturalSize] = child.get_preferred_height(-1);
|
||||||
// Is this the second column, or we're in
|
|
||||||
// the first column and can't even fit one
|
if (y + naturalSize > box.y2) {
|
||||||
// item? In that case, break.
|
// Is this the second column? Ok, break.
|
||||||
if (columnIndex == 1 || i == 0) {
|
if (columnIndex == 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Set x to the halfway point.
|
// Set x to the halfway point.
|
||||||
columnIndex += 1;
|
columnIndex += 1;
|
||||||
x = x + this._itemWidth + DEFAULT_SPACING;
|
x = x + itemWidth + DEFAULT_SPACING;
|
||||||
// And y is back to the top.
|
// And y is back to the top.
|
||||||
y = 0;
|
y = box.y1;
|
||||||
// Retry this same item, now that we're in the second column.
|
|
||||||
// By looping back to the top here, we re-test the size
|
|
||||||
// again for the second column.
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let childBox = new Clutter.ActorBox();
|
let childBox = new Clutter.ActorBox();
|
||||||
childBox.x1 = x;
|
childBox.x1 = x;
|
||||||
childBox.y1 = y;
|
childBox.y1 = y;
|
||||||
childBox.x2 = childBox.x1 + this._itemWidth;
|
childBox.x2 = childBox.x1 + itemWidth;
|
||||||
childBox.y2 = y + this._itemHeight;
|
childBox.y2 = y + naturalSize;
|
||||||
|
|
||||||
y = childBox.y2 + DEFAULT_SPACING;
|
y = childBox.y2 + DEFAULT_SPACING;
|
||||||
|
|
||||||
|
child.show();
|
||||||
child.allocate(childBox, flags);
|
child.allocate(childBox, flags);
|
||||||
this.actor.set_skip_paint(child, false);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._checkDocExistence) {
|
// Everything else didn't fit, just hide it.
|
||||||
// Now we know how many docs we are displaying, queue a check to see if any of them
|
for (; i < children.length; i++) {
|
||||||
// have been deleted. If they are deleted, then we'll get a 'changed' signal; since
|
children[i].hide();
|
||||||
// we'll now be displaying items we weren't previously, we'll check again to see
|
|
||||||
// if they were deleted, and so forth and so on.
|
|
||||||
// TODO: We should change this to ask for as many as we can fit in the given space:
|
|
||||||
// https://bugzilla.gnome.org/show_bug.cgi?id=603522#c23
|
|
||||||
this._docManager.queueExistenceCheck(i);
|
|
||||||
this._checkDocExistence = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < children.length; i++)
|
|
||||||
this.actor.set_skip_paint(children[i], true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onDocsChanged: function() {
|
|
||||||
this._checkDocExistence = true;
|
|
||||||
Main.queueDeferredWork(this._workId);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_redisplay: function() {
|
_redisplay: function() {
|
||||||
// Should be kept alive by the _actorsByUri
|
|
||||||
this.actor.remove_all();
|
this.actor.remove_all();
|
||||||
let docs = this._docManager.getTimestampOrderedInfos();
|
|
||||||
for (let i = 0; i < docs.length && i < MAX_DASH_DOCS; i++) {
|
let docs = this._docManager.getItems();
|
||||||
let doc = docs[i];
|
let docUrls = [];
|
||||||
let display = this._actorsByUri[doc.uri];
|
for (let url in docs) {
|
||||||
if (display) {
|
docUrls.push(url);
|
||||||
this.actor.add_actor(display.actor);
|
|
||||||
} else {
|
|
||||||
let display = new DashDocDisplayItem(doc);
|
|
||||||
this.actor.add_actor(display.actor);
|
|
||||||
this._actorsByUri[doc.uri] = display;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Any unparented actors must have been deleted
|
docUrls.sort(function (urlA, urlB) { return docs[urlB].timestamp - docs[urlA].timestamp; });
|
||||||
for (let uri in this._actorsByUri) {
|
let textureCache = Shell.TextureCache.get_default();
|
||||||
let display = this._actorsByUri[uri];
|
|
||||||
if (display.actor.get_parent() == null) {
|
for (let i = 0; i < docUrls.length; i++) {
|
||||||
display.actor.destroy();
|
let url = docUrls[i];
|
||||||
delete this._actorsByUri[uri];
|
let docInfo = docs[url];
|
||||||
}
|
let display = new DashDocDisplayItem(docInfo);
|
||||||
|
this.actor.add_actor(display.actor);
|
||||||
}
|
}
|
||||||
this.emit('changed');
|
this.emit('changed');
|
||||||
}
|
}
|
||||||
@ -478,41 +442,3 @@ DashDocDisplay.prototype = {
|
|||||||
|
|
||||||
Signals.addSignalMethods(DashDocDisplay.prototype);
|
Signals.addSignalMethods(DashDocDisplay.prototype);
|
||||||
|
|
||||||
function DocSearchProvider() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
DocSearchProvider.prototype = {
|
|
||||||
__proto__: Search.SearchProvider.prototype,
|
|
||||||
|
|
||||||
_init: function(name) {
|
|
||||||
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
|
|
||||||
this._docManager = DocInfo.getDocManager();
|
|
||||||
},
|
|
||||||
|
|
||||||
getResultMeta: function(resultId) {
|
|
||||||
let docInfo = this._docManager.lookupByUri(resultId);
|
|
||||||
if (!docInfo)
|
|
||||||
return null;
|
|
||||||
return { 'id': resultId,
|
|
||||||
'name': docInfo.name,
|
|
||||||
'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)};
|
|
||||||
},
|
|
||||||
|
|
||||||
activateResult: function(id) {
|
|
||||||
let docInfo = this._docManager.lookupByUri(id);
|
|
||||||
docInfo.launch();
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialResultSet: function(terms) {
|
|
||||||
return this._docManager.initialSearch(terms);
|
|
||||||
},
|
|
||||||
|
|
||||||
getSubsearchResultSet: function(previousResults, terms) {
|
|
||||||
return this._docManager.subsearch(previousResults, terms);
|
|
||||||
},
|
|
||||||
|
|
||||||
expandSearch: function(terms) {
|
|
||||||
log('TODO expand docs search');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Gettext_gtk20 = imports.gettext.domain('gtk20');
|
|
||||||
|
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
const Format = imports.misc.format;
|
|
||||||
|
|
||||||
// "monkey patch" in some varargs ClutterContainer methods; we need
|
// "monkey patch" in some varargs ClutterContainer methods; we need
|
||||||
// to do this per-container class since there is no representation
|
// to do this per-container class since there is no representation
|
||||||
// of interfaces in Javascript
|
// of interfaces in Javascript
|
||||||
@ -29,57 +25,9 @@ function _patchContainerClass(containerClass) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace @method with something that throws an error instead
|
_patchContainerClass(St.BoxLayout);
|
||||||
function _blockMethod(method, replacement, reason) {
|
_patchContainerClass(St.Table);
|
||||||
let match = method.match(/^(.+)\.([^.]+)$/);
|
|
||||||
if (!match)
|
|
||||||
throw new Error('Bad method name "' + method + '"');
|
|
||||||
let proto = 'imports.gi.' + match[1] + '.prototype';
|
|
||||||
let property = match[2];
|
|
||||||
|
|
||||||
if (!global.set_property_mutable(proto, property, true))
|
|
||||||
throw new Error('Bad method name "' + method + '"');
|
|
||||||
|
|
||||||
// eval() is evil in general, but we know it's safe here since
|
|
||||||
// set_property_mutable() would have failed if proto was
|
|
||||||
// malformed.
|
|
||||||
let node = eval(proto);
|
|
||||||
|
|
||||||
let msg = 'Do not use "' + method + '".';
|
|
||||||
if (replacement)
|
|
||||||
msg += ' Use "' + replacement + '" instead.';
|
|
||||||
if (reason)
|
|
||||||
msg += ' (' + reason + ')';
|
|
||||||
|
|
||||||
node[property] = function() {
|
|
||||||
throw new Error(msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
global.set_property_mutable(proto, property, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
Tweener.init();
|
Tweener.init();
|
||||||
String.prototype.format = Format.format;
|
|
||||||
|
|
||||||
// Set the default direction for St widgets (this needs to be done before any use of St)
|
|
||||||
if (Gettext_gtk20.gettext('default:LTR') == 'default:RTL') {
|
|
||||||
St.Widget.set_default_direction(St.TextDirection.RTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
_patchContainerClass(St.BoxLayout);
|
|
||||||
_patchContainerClass(St.Table);
|
|
||||||
|
|
||||||
_blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
|
|
||||||
'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
|
|
||||||
_blockMethod('Gdk.Display.get_pointer', 'global.get_pointer',
|
|
||||||
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
|
|
||||||
_blockMethod('Gdk.Window.get_pointer', 'global.get_pointer',
|
|
||||||
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
|
|
||||||
|
|
||||||
// Now close the back door to prevent extensions from trying to
|
|
||||||
// abuse it. We can't actually delete it since
|
|
||||||
// Shell.Global.prototype itself is read-only.
|
|
||||||
global.set_property_mutable('imports.gi.Shell.Global.prototype', 'set_property_mutable', true);
|
|
||||||
Shell.Global.prototype.set_property_mutable = undefined;
|
|
||||||
}
|
}
|
||||||
|
@ -1,157 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
|
|
||||||
const ExtensionState = {
|
|
||||||
ENABLED: 1,
|
|
||||||
DISABLED: 2,
|
|
||||||
ERROR: 3,
|
|
||||||
OUT_OF_DATE: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
const ExtensionType = {
|
|
||||||
SYSTEM: 1,
|
|
||||||
PER_USER: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// Maps uuid -> metadata object
|
|
||||||
const extensionMeta = {};
|
|
||||||
// Maps uuid -> importer object (extension directory tree)
|
|
||||||
const extensions = {};
|
|
||||||
// Array of uuids
|
|
||||||
var disabledExtensions;
|
|
||||||
// GFile for user extensions
|
|
||||||
var userExtensionsDir = null;
|
|
||||||
|
|
||||||
function loadExtension(dir, enabled, type) {
|
|
||||||
let info;
|
|
||||||
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
|
|
||||||
|
|
||||||
let metadataFile = dir.get_child('metadata.json');
|
|
||||||
if (!metadataFile.query_exists(null)) {
|
|
||||||
global.logError(baseErrorString + 'Missing metadata.json');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let [success, metadataContents, len, etag] = metadataFile.load_contents(null);
|
|
||||||
let meta;
|
|
||||||
try {
|
|
||||||
meta = JSON.parse(metadataContents);
|
|
||||||
} catch (e) {
|
|
||||||
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let requiredProperties = ['uuid', 'name', 'description'];
|
|
||||||
for (let i = 0; i < requiredProperties; i++) {
|
|
||||||
let prop = requiredProperties[i];
|
|
||||||
if (!meta[prop]) {
|
|
||||||
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Encourage people to add this
|
|
||||||
if (!meta['url']) {
|
|
||||||
global.log(baseErrorString + 'Warning: Missing "url" property in metadata.json');
|
|
||||||
}
|
|
||||||
|
|
||||||
let base = dir.get_basename();
|
|
||||||
if (base != meta.uuid) {
|
|
||||||
global.logError(baseErrorString + 'uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + base + '"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
extensionMeta[meta.uuid] = meta;
|
|
||||||
extensionMeta[meta.uuid].type = type;
|
|
||||||
extensionMeta[meta.uuid].path = dir.get_path();
|
|
||||||
if (!enabled) {
|
|
||||||
extensionMeta[meta.uuid].state = ExtensionState.DISABLED;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default to error, we set success as the last step
|
|
||||||
extensionMeta[meta.uuid].state = ExtensionState.ERROR;
|
|
||||||
|
|
||||||
let extensionJs = dir.get_child('extension.js');
|
|
||||||
if (!extensionJs.query_exists(null)) {
|
|
||||||
global.logError(baseErrorString + 'Missing extension.js');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let stylesheetPath = null;
|
|
||||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
|
||||||
let theme = themeContext.get_theme();
|
|
||||||
let stylesheetFile = dir.get_child('stylesheet.css');
|
|
||||||
if (stylesheetFile.query_exists(null)) {
|
|
||||||
try {
|
|
||||||
theme.load_stylesheet(stylesheetFile.get_path());
|
|
||||||
} catch (e) {
|
|
||||||
global.logError(baseErrorString + 'Stylesheet parse error: ' + e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let extensionModule;
|
|
||||||
try {
|
|
||||||
global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
|
|
||||||
extensionModule = extensions[meta.uuid].extension;
|
|
||||||
} catch (e) {
|
|
||||||
if (stylesheetPath != null)
|
|
||||||
theme.unload_stylesheet(stylesheetPath);
|
|
||||||
global.logError(baseErrorString + e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!extensionModule.main) {
|
|
||||||
global.logError(baseErrorString + 'missing \'main\' function');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
extensionModule.main();
|
|
||||||
} catch (e) {
|
|
||||||
if (stylesheetPath != null)
|
|
||||||
theme.unload_stylesheet(stylesheetPath);
|
|
||||||
global.logError(baseErrorString + 'Failed to evaluate main function:' + e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
extensionMeta[meta.uuid].state = ExtensionState.ENABLED;
|
|
||||||
global.log('Loaded extension ' + meta.uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
|
|
||||||
userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
|
|
||||||
try {
|
|
||||||
userExtensionsDir.make_directory_with_parents(null);
|
|
||||||
} catch (e) {
|
|
||||||
global.logError('' + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
disabledExtensions = Shell.GConf.get_default().get_string_list('disabled_extensions');
|
|
||||||
}
|
|
||||||
|
|
||||||
function _loadExtensionsIn(dir, type) {
|
|
||||||
let fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
|
|
||||||
let file, info;
|
|
||||||
while ((info = fileEnum.next_file(null)) != null) {
|
|
||||||
let fileType = info.get_file_type();
|
|
||||||
if (fileType != Gio.FileType.DIRECTORY)
|
|
||||||
continue;
|
|
||||||
let name = info.get_name();
|
|
||||||
let enabled = disabledExtensions.indexOf(name) < 0;
|
|
||||||
let child = dir.get_child(name);
|
|
||||||
loadExtension(child, enabled, type);
|
|
||||||
}
|
|
||||||
fileEnum.close(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadExtensions() {
|
|
||||||
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
|
|
||||||
let systemDataDirs = GLib.get_system_data_dirs();
|
|
||||||
for (let i = 0; i < systemDataDirs.length; i++) {
|
|
||||||
let dirPath = systemDataDirs[i] + '/gnome-shell/extensions';
|
|
||||||
let dir = Gio.file_new_for_path(dirPath);
|
|
||||||
if (dir.query_exists(null))
|
|
||||||
_loadExtensionsIn(dir, ExtensionType.SYSTEM);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Gdk = imports.gi.Gdk;
|
const Gdk = imports.gi.Gdk;
|
||||||
@ -10,19 +11,47 @@ const Meta = imports.gi.Meta;
|
|||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
|
const Button = imports.ui.button;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
|
const Link = imports.ui.link;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const RedisplayFlags = { NONE: 0,
|
const RedisplayFlags = { NONE: 0,
|
||||||
|
RESET_CONTROLS: 1 << 0,
|
||||||
FULL: 1 << 1,
|
FULL: 1 << 1,
|
||||||
SUBSEARCH: 1 << 2,
|
SUBSEARCH: 1 << 2 };
|
||||||
IMMEDIATE: 1 << 3 };
|
|
||||||
|
|
||||||
// Used by subclasses
|
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
|
||||||
|
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
|
||||||
|
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
|
||||||
|
ITEM_DISPLAY_DESCRIPTION_COLOR.from_pixel(0xffffffbb);
|
||||||
|
const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
|
ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000);
|
||||||
|
const ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
|
ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR.from_pixel(0x4f6fadaa);
|
||||||
|
const DISPLAY_CONTROL_SELECTED_COLOR = new Clutter.Color();
|
||||||
|
DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff);
|
||||||
|
const PREVIEW_BOX_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
|
PREVIEW_BOX_BACKGROUND_COLOR.from_pixel(0xADADADf0);
|
||||||
|
|
||||||
|
const DEFAULT_PADDING = 4;
|
||||||
|
|
||||||
|
const ITEM_DISPLAY_HEIGHT = 50;
|
||||||
const ITEM_DISPLAY_ICON_SIZE = 48;
|
const ITEM_DISPLAY_ICON_SIZE = 48;
|
||||||
|
const ITEM_DISPLAY_PADDING = 1;
|
||||||
|
const ITEM_DISPLAY_PADDING_RIGHT = 2;
|
||||||
|
const DEFAULT_COLUMN_GAP = 6;
|
||||||
|
|
||||||
const PREVIEW_ICON_SIZE = 96;
|
const PREVIEW_ICON_SIZE = 96;
|
||||||
|
const PREVIEW_BOX_PADDING = 6;
|
||||||
|
const PREVIEW_BOX_SPACING = DEFAULT_PADDING;
|
||||||
|
const PREVIEW_BOX_CORNER_RADIUS = 10;
|
||||||
|
// how far relative to the full item width the preview box should be placed
|
||||||
|
const PREVIEW_PLACING = 3/4;
|
||||||
|
const PREVIEW_DETAILS_MIN_WIDTH = PREVIEW_ICON_SIZE * 2;
|
||||||
|
|
||||||
|
const INFORMATION_BUTTON_SIZE = 16;
|
||||||
|
|
||||||
/* This is a virtual class that represents a single display item containing
|
/* This is a virtual class that represents a single display item containing
|
||||||
* a name, a description, and an icon. It allows selecting an item and represents
|
* a name, a description, and an icon. It allows selecting an item and represents
|
||||||
@ -34,8 +63,12 @@ function GenericDisplayItem() {
|
|||||||
|
|
||||||
GenericDisplayItem.prototype = {
|
GenericDisplayItem.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.actor = new St.BoxLayout({ style_class: 'generic-display-item',
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
reactive: true });
|
spacing: ITEM_DISPLAY_PADDING,
|
||||||
|
reactive: true,
|
||||||
|
background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
|
||||||
|
corner_radius: 4,
|
||||||
|
height: ITEM_DISPLAY_HEIGHT });
|
||||||
|
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.actor.connect('button-release-event',
|
this.actor.connect('button-release-event',
|
||||||
@ -47,13 +80,47 @@ GenericDisplayItem.prototype = {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
let draggable = DND.makeDraggable(this.actor);
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
|
draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||||
|
|
||||||
this._iconBin = new St.Bin();
|
this._infoContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
this.actor.add(this._iconBin);
|
spacing: DEFAULT_PADDING });
|
||||||
|
this.actor.append(this._infoContent, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._infoText = new St.BoxLayout({ style_class: 'generic-display-item-text',
|
this._iconBox = new Big.Box();
|
||||||
vertical: true });
|
this._infoContent.append(this._iconBox, Big.BoxPackFlags.NONE);
|
||||||
this.actor.add(this._infoText, { expand: true, y_fill: false });
|
|
||||||
|
this._infoText = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
spacing: DEFAULT_PADDING });
|
||||||
|
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
||||||
|
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
|
infoIconUri,
|
||||||
|
INFORMATION_BUTTON_SIZE,
|
||||||
|
INFORMATION_BUTTON_SIZE);
|
||||||
|
this._informationButton = new Button.IconButton(this.actor, INFORMATION_BUTTON_SIZE, infoIcon);
|
||||||
|
let buttonBox = new Big.Box({ width: INFORMATION_BUTTON_SIZE + 2 * DEFAULT_PADDING,
|
||||||
|
height: INFORMATION_BUTTON_SIZE,
|
||||||
|
padding_left: DEFAULT_PADDING, padding_right: DEFAULT_PADDING,
|
||||||
|
y_align: Big.BoxAlignment.CENTER });
|
||||||
|
buttonBox.append(this._informationButton.actor, Big.BoxPackFlags.NONE);
|
||||||
|
this.actor.append(buttonBox, Big.BoxPackFlags.END);
|
||||||
|
|
||||||
|
// Connecting to the button-press-event for the information button ensures that the actor,
|
||||||
|
// which is a draggable actor, does not get the button-press-event and doesn't initiate
|
||||||
|
// the dragging, which then prevents us from getting the button-release-event for the button.
|
||||||
|
this._informationButton.actor.connect('button-press-event',
|
||||||
|
Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
this._informationButton.actor.connect('button-release-event',
|
||||||
|
Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
// Selects the item by highlighting it and displaying its details
|
||||||
|
this.emit('show-details');
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
|
||||||
this._name = null;
|
this._name = null;
|
||||||
this._description = null;
|
this._description = null;
|
||||||
@ -85,13 +152,24 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
//// Public methods ////
|
//// Public methods ////
|
||||||
|
|
||||||
|
// Shows the information button when the item was drawn under the mouse pointer.
|
||||||
|
onDrawnUnderPointer: function() {
|
||||||
|
this._informationButton.show();
|
||||||
|
},
|
||||||
|
|
||||||
// Highlights the item by setting a different background color than the default
|
// Highlights the item by setting a different background color than the default
|
||||||
// if isSelected is true, removes the highlighting otherwise.
|
// if isSelected is true, removes the highlighting otherwise.
|
||||||
markSelected: function(isSelected) {
|
markSelected: function(isSelected) {
|
||||||
if (isSelected)
|
let color;
|
||||||
this.actor.add_style_pseudo_class('selected');
|
if (isSelected) {
|
||||||
else
|
color = ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR;
|
||||||
this.actor.remove_style_pseudo_class('selected');
|
this._informationButton.forceShow(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
color = ITEM_DISPLAY_BACKGROUND_COLOR;
|
||||||
|
this._informationButton.forceShow(false);
|
||||||
|
}
|
||||||
|
this.actor.background_color = color;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -100,36 +178,44 @@ GenericDisplayItem.prototype = {
|
|||||||
*/
|
*/
|
||||||
createDetailsActor: function() {
|
createDetailsActor: function() {
|
||||||
|
|
||||||
let details = new St.BoxLayout({ style_class: 'generic-display-container',
|
let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
vertical: true });
|
spacing: PREVIEW_BOX_SPACING });
|
||||||
|
|
||||||
let mainDetails = new St.BoxLayout({ style_class: 'generic-display-container' });
|
let mainDetails = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
spacing: PREVIEW_BOX_SPACING });
|
||||||
|
|
||||||
// Inner box with name and description
|
// Inner box with name and description
|
||||||
let textDetails = new St.BoxLayout({ style_class: 'generic-display-details',
|
let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
vertical: true });
|
spacing: PREVIEW_BOX_SPACING });
|
||||||
let detailsName = new St.Label({ style_class: 'generic-display-details-name',
|
let detailsName = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
||||||
text: this._name.text });
|
font_name: "Sans bold 14px",
|
||||||
textDetails.add(detailsName);
|
line_wrap: true,
|
||||||
|
text: this._name.text });
|
||||||
|
textDetails.append(detailsName, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
let detailsDescription = new St.Label({ text: this._description.text });
|
let detailsDescription = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
||||||
textDetails.add(detailsDescription);
|
font_name: "Sans 14px",
|
||||||
|
line_wrap: true,
|
||||||
|
text: this._description.text });
|
||||||
|
textDetails.append(detailsDescription, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this._detailsDescriptions.push(detailsDescription);
|
this._detailsDescriptions.push(detailsDescription);
|
||||||
|
|
||||||
mainDetails.add(textDetails, { expand: true });
|
mainDetails.append(textDetails, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
let previewIcon = this._createPreviewIcon();
|
let previewIcon = this._createPreviewIcon();
|
||||||
let largePreviewIcon = this._createLargePreviewIcon();
|
let largePreviewIcon = this._createLargePreviewIcon();
|
||||||
|
|
||||||
if (previewIcon != null && largePreviewIcon == null) {
|
if (previewIcon != null && largePreviewIcon == null) {
|
||||||
mainDetails.insert_actor(previewIcon, 0);
|
mainDetails.prepend(previewIcon, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
details.add(mainDetails);
|
details.append(mainDetails, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
if (largePreviewIcon != null) {
|
if (largePreviewIcon != null) {
|
||||||
details.add(largePreviewIcon);
|
let largePreview = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
|
largePreview.append(largePreviewIcon, Big.BoxPackFlags.NONE);
|
||||||
|
details.append(largePreview, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return details;
|
return details;
|
||||||
@ -137,14 +223,14 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
// Destroys the item.
|
// Destroys the item.
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Pure virtual public methods ////
|
//// Pure virtual public methods ////
|
||||||
|
|
||||||
// Performes an action associated with launching this item, such as opening a file or an application.
|
// Performes an action associated with launching this item, such as opening a file or an application.
|
||||||
launch: function() {
|
launch: function() {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Protected methods ////
|
//// Protected methods ////
|
||||||
@ -174,15 +260,20 @@ GenericDisplayItem.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._icon = this._createIcon();
|
this._icon = this._createIcon();
|
||||||
this._iconBin.set_child(this._icon);
|
this._iconBox.append(this._icon, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this._name = new St.Label({ style_class: 'generic-display-item-name',
|
this._name = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
||||||
text: nameText });
|
font_name: "Sans 14px",
|
||||||
this._infoText.add(this._name);
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
text: nameText });
|
||||||
|
this._infoText.append(this._name, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._description = new St.Label({ style_class: 'generic-display-item-description',
|
this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR,
|
||||||
text: descriptionText ? descriptionText : '' });
|
font_name: "Sans 12px",
|
||||||
this._infoText.add(this._description);
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
text: descriptionText ? descriptionText : ""
|
||||||
|
});
|
||||||
|
this._infoText.append(this._description, Big.BoxPackFlags.EXPAND);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sets the description text for the item, including the description text
|
// Sets the description text for the item, including the description text
|
||||||
@ -208,51 +299,48 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
// Returns an icon for the item.
|
// Returns an icon for the item.
|
||||||
_createIcon: function() {
|
_createIcon: function() {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns a preview icon for the item.
|
// Returns a preview icon for the item.
|
||||||
_createPreviewIcon: function() {
|
_createPreviewIcon: function() {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
}
|
},
|
||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
|
|
||||||
|
// Hides the information button once the item starts being dragged.
|
||||||
|
_onDragBegin : function (draggable, time) {
|
||||||
|
// For some reason, we are not getting leave-event signal when we are dragging an item,
|
||||||
|
// so we should remove the link manually.
|
||||||
|
this._informationButton.actor.hide();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(GenericDisplayItem.prototype);
|
Signals.addSignalMethods(GenericDisplayItem.prototype);
|
||||||
|
|
||||||
const GenericDisplayFlags = {
|
|
||||||
DISABLE_VSCROLLING: 1 << 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* This is a virtual class that represents a display containing a collection of items
|
/* This is a virtual class that represents a display containing a collection of items
|
||||||
* that can be filtered with a search string.
|
* that can be filtered with a search string.
|
||||||
*/
|
*/
|
||||||
function GenericDisplay(flags) {
|
function GenericDisplay() {
|
||||||
this._init(flags);
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericDisplay.prototype = {
|
GenericDisplay.prototype = {
|
||||||
_init : function(flags) {
|
_init : function() {
|
||||||
let disableVScrolling = (flags & GenericDisplayFlags.DISABLE_VSCROLLING) != 0;
|
|
||||||
this._search = '';
|
this._search = '';
|
||||||
this._expanded = false;
|
this._expanded = false;
|
||||||
|
|
||||||
if (disableVScrolling) {
|
this._maxItemsPerPage = null;
|
||||||
this.actor = this._list = new Shell.OverflowList({ spacing: 6,
|
this._list = new Shell.OverflowList({ spacing: 6.0,
|
||||||
item_height: 50 });
|
item_height: ITEM_DISPLAY_HEIGHT });
|
||||||
} else {
|
|
||||||
this.actor = new St.ScrollView({ x_fill: true,
|
|
||||||
y_fill: false,
|
|
||||||
vshadows: true });
|
|
||||||
this._list = new St.BoxLayout({ style_class: 'generic-display-container',
|
|
||||||
vertical: true });
|
|
||||||
this.actor.add_actor(this._list);
|
|
||||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._pendingRedisplay = RedisplayFlags.NONE;
|
this._list.connect('notify::n-pages', Lang.bind(this, function () {
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify));
|
this._updateDisplayControl(true);
|
||||||
|
}));
|
||||||
|
this._list.connect('notify::page', Lang.bind(this, function () {
|
||||||
|
this._updateDisplayControl(false);
|
||||||
|
}));
|
||||||
|
|
||||||
// map<itemId, Object> where Object represents the item info
|
// map<itemId, Object> where Object represents the item info
|
||||||
this._allItems = {};
|
this._allItems = {};
|
||||||
@ -264,6 +352,13 @@ GenericDisplay.prototype = {
|
|||||||
this._displayedItems = {};
|
this._displayedItems = {};
|
||||||
this._openDetailIndex = -1;
|
this._openDetailIndex = -1;
|
||||||
this._selectedIndex = -1;
|
this._selectedIndex = -1;
|
||||||
|
// These two are public - .actor is the normal "actor subclass" property,
|
||||||
|
// but we also expose a .displayControl actor which is separate.
|
||||||
|
// See also getNavigationArea.
|
||||||
|
this.actor = this._list;
|
||||||
|
this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
|
||||||
|
spacing: 12,
|
||||||
|
orientation: Big.BoxOrientation.HORIZONTAL});
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Public methods ////
|
//// Public methods ////
|
||||||
@ -271,18 +366,12 @@ GenericDisplay.prototype = {
|
|||||||
// Sets the search string and displays the matching items.
|
// Sets the search string and displays the matching items.
|
||||||
setSearch: function(text) {
|
setSearch: function(text) {
|
||||||
let lowertext = text.toLowerCase();
|
let lowertext = text.toLowerCase();
|
||||||
if (lowertext == this._search) {
|
if (lowertext == this._search)
|
||||||
return;
|
return;
|
||||||
}
|
let flags = RedisplayFlags.RESET_CONTROLS;
|
||||||
let flags = RedisplayFlags.IMMEDIATE;
|
|
||||||
if (this._search != '') {
|
if (this._search != '') {
|
||||||
// Because we combine search terms with OR, we have to be sure that no new term
|
if (lowertext.indexOf(this._search) == 0)
|
||||||
// was introduced before deciding that the new search results will be a subset of
|
|
||||||
// the existing search results.
|
|
||||||
if (lowertext.indexOf(this._search) == 0 &&
|
|
||||||
lowertext.split(/\s+/).length == this._search.split(/\s+/).length) {
|
|
||||||
flags |= RedisplayFlags.SUBSEARCH;
|
flags |= RedisplayFlags.SUBSEARCH;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this._search = lowertext;
|
this._search = lowertext;
|
||||||
this._redisplay(flags);
|
this._redisplay(flags);
|
||||||
@ -302,7 +391,7 @@ GenericDisplay.prototype = {
|
|||||||
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
|
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
|
||||||
// around to the bottom.
|
// around to the bottom.
|
||||||
selectUp: function() {
|
selectUp: function() {
|
||||||
let count = this._getVisibleCount();
|
let count = this._list.displayedCount;
|
||||||
let selectedUp = true;
|
let selectedUp = true;
|
||||||
let prev = this._selectedIndex - 1;
|
let prev = this._selectedIndex - 1;
|
||||||
if (this._selectedIndex <= 0) {
|
if (this._selectedIndex <= 0) {
|
||||||
@ -317,7 +406,7 @@ GenericDisplay.prototype = {
|
|||||||
// to the top one. Returns true if the selection actually moved down, false if it wrapped
|
// to the top one. Returns true if the selection actually moved down, false if it wrapped
|
||||||
// around to the top.
|
// around to the top.
|
||||||
selectDown: function() {
|
selectDown: function() {
|
||||||
let count = this._getVisibleCount();
|
let count = this._list.displayedCount;
|
||||||
let selectedDown = true;
|
let selectedDown = true;
|
||||||
let next = this._selectedIndex + 1;
|
let next = this._selectedIndex + 1;
|
||||||
if (this._selectedIndex == count - 1) {
|
if (this._selectedIndex == count - 1) {
|
||||||
@ -336,7 +425,7 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// Selects the last item among the displayed items.
|
// Selects the last item among the displayed items.
|
||||||
selectLastItem: function() {
|
selectLastItem: function() {
|
||||||
let count = this._getVisibleCount();
|
let count = this._list.displayedCount;
|
||||||
if (this.hasItems())
|
if (this.hasItems())
|
||||||
this._selectIndex(count - 1);
|
this._selectIndex(count - 1);
|
||||||
},
|
},
|
||||||
@ -356,7 +445,7 @@ GenericDisplay.prototype = {
|
|||||||
// TODO: figure out why this._list.displayedCount is returning a
|
// TODO: figure out why this._list.displayedCount is returning a
|
||||||
// positive number when this._mathedItems.length is 0
|
// positive number when this._mathedItems.length is 0
|
||||||
// This can be triggered if a search string is entered for which there are no matches.
|
// This can be triggered if a search string is entered for which there are no matches.
|
||||||
// log('this._mathedItems.length: ' + this._matchedItems.length + ' this._list.displayedCount ' + this._list.displayedCount);
|
// log("this._mathedItems.length: " + this._matchedItems.length + " this._list.displayedCount " + this._list.displayedCount);
|
||||||
return this._matchedItemKeys.length > 0;
|
return this._matchedItemKeys.length > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -373,8 +462,6 @@ GenericDisplay.prototype = {
|
|||||||
resetState: function() {
|
resetState: function() {
|
||||||
this._filterReset();
|
this._filterReset();
|
||||||
this._openDetailIndex = -1;
|
this._openDetailIndex = -1;
|
||||||
if (!(this.actor instanceof Shell.OverflowList))
|
|
||||||
this.actor.get_vscroll_bar().get_adjustment().value = 0;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns an actor which acts as a sidebar; this is used for
|
// Returns an actor which acts as a sidebar; this is used for
|
||||||
@ -388,21 +475,29 @@ GenericDisplay.prototype = {
|
|||||||
return item.createDetailsActor();
|
return item.createDetailsActor();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Displays the page specified by the pageNumber argument.
|
||||||
|
displayPage: function(pageNumber) {
|
||||||
|
// Cleanup from the previous selection, but don't unset this._selectedIndex
|
||||||
|
if (this.hasSelected()) {
|
||||||
|
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
||||||
|
}
|
||||||
|
this._list.page = pageNumber;
|
||||||
|
},
|
||||||
|
|
||||||
//// Protected methods ////
|
//// Protected methods ////
|
||||||
|
|
||||||
_recreateDisplayItems: function() {
|
_redisplayFull: function() {
|
||||||
this._removeAllDisplayItems();
|
this._removeAllDisplayItems();
|
||||||
this._setDefaultList();
|
|
||||||
for (let itemId in this._allItems) {
|
for (let itemId in this._allItems) {
|
||||||
this._addDisplayItem(itemId);
|
this._addDisplayItem(itemId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Creates a display item based on the information associated with itemId
|
// Creates a display item based on the information associated with itemId
|
||||||
// and adds it to the list of displayed items, but does not yet display it.
|
// and adds it to the displayed items.
|
||||||
_addDisplayItem : function(itemId) {
|
_addDisplayItem : function(itemId) {
|
||||||
if (this._displayedItems.hasOwnProperty(itemId)) {
|
if (this._displayedItems.hasOwnProperty(itemId)) {
|
||||||
log('Tried adding a display item for ' + itemId + ', but an item with this item id is already among displayed items.');
|
log("Tried adding a display item for " + itemId + ", but an item with this item id is already among displayed items.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,14 +508,14 @@ GenericDisplay.prototype = {
|
|||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
// update the selection
|
// update the selection
|
||||||
this._selectIndex(this._list.get_children().indexOf(displayItem.actor));
|
this._selectIndex(this._list.get_actor_index(displayItem.actor));
|
||||||
this.activateSelected();
|
this.activateSelected();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
displayItem.connect('show-details',
|
displayItem.connect('show-details',
|
||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
let index = this._list.get_children().indexOf(displayItem.actor);
|
let index = this._list.get_actor_index(displayItem.actor);
|
||||||
/* Close the details pane if already open */
|
/* Close the details pane if already open */
|
||||||
if (index == this._openDetailIndex) {
|
if (index == this._openDetailIndex) {
|
||||||
this._openDetailIndex = -1;
|
this._openDetailIndex = -1;
|
||||||
@ -430,15 +525,15 @@ GenericDisplay.prototype = {
|
|||||||
this.emit('show-details', index);
|
this.emit('show-details', index);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
this._list.add_actor(displayItem.actor);
|
||||||
this._displayedItems[itemId] = displayItem;
|
this._displayedItems[itemId] = displayItem;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Removes an item identifed by the itemId from the displayed items.
|
// Removes an item identifed by the itemId from the displayed items.
|
||||||
_removeDisplayItem: function(itemId) {
|
_removeDisplayItem: function(itemId) {
|
||||||
let children = this._list.get_children();
|
let count = this._list.displayedCount;
|
||||||
let count = children.length;
|
|
||||||
let displayItem = this._displayedItems[itemId];
|
let displayItem = this._displayedItems[itemId];
|
||||||
let displayItemIndex = children.indexOf(displayItem.actor);
|
let displayItemIndex = this._list.get_actor_index(displayItem.actor);
|
||||||
|
|
||||||
if (this.hasSelected() && count == 1) {
|
if (this.hasSelected() && count == 1) {
|
||||||
this.unsetSelected();
|
this.unsetSelected();
|
||||||
@ -461,7 +556,7 @@ GenericDisplay.prototype = {
|
|||||||
// Return true if there's an active search or other constraint
|
// Return true if there's an active search or other constraint
|
||||||
// on the list
|
// on the list
|
||||||
_filterActive: function() {
|
_filterActive: function() {
|
||||||
return this._search != '';
|
return this._search != "";
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called when we are resetting state
|
// Called when we are resetting state
|
||||||
@ -533,83 +628,94 @@ GenericDisplay.prototype = {
|
|||||||
/*
|
/*
|
||||||
* Updates the displayed items, applying the search string if one exists.
|
* Updates the displayed items, applying the search string if one exists.
|
||||||
* @flags: Flags controlling redisplay behavior as follows:
|
* @flags: Flags controlling redisplay behavior as follows:
|
||||||
|
* RESET_CONTROLS - indicates if the page selection should be reset when displaying the matching results.
|
||||||
|
* We reset the page selection when the change in results was initiated by the user by
|
||||||
|
* entering a different search criteria or by viewing the results list in a different
|
||||||
|
* size mode, but we keep the page selection the same if the results got updated on
|
||||||
|
* their own while the user was browsing through the result pages.
|
||||||
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
|
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
|
||||||
* one, which implies we only need to re-search through previous results.
|
* one, which implies we only need to re-search through previous results.
|
||||||
* FULL - Indicates that we need recreate all displayed items.
|
|
||||||
* IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful
|
|
||||||
* if you want to get the number of matched items and show/hide a section based on
|
|
||||||
* that number.
|
|
||||||
*/
|
*/
|
||||||
_redisplay: function(flags) {
|
_redisplay: function(flags) {
|
||||||
let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0;
|
let resetPage = (flags & RedisplayFlags.RESET_CONTROLS) > 0;
|
||||||
if (!immediate && !this.actor.mapped) {
|
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) > 0;
|
||||||
this._pendingRedisplay |= flags;
|
let fullReload = (flags & RedisplayFlags.FULL) > 0;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0;
|
|
||||||
let fullReload = (flags & RedisplayFlags.FULL) != 0;
|
|
||||||
|
|
||||||
let hadSelected = this.hasSelected();
|
let hadSelected = this.hasSelected();
|
||||||
this.unsetSelected();
|
|
||||||
|
|
||||||
if (!this._initialLoadComplete)
|
if (!this._initialLoadComplete || !this._refreshCache())
|
||||||
fullReload = true;
|
fullReload = true;
|
||||||
|
|
||||||
if (!this._refreshCache())
|
|
||||||
fullReload = true;
|
|
||||||
|
|
||||||
if (fullReload) {
|
if (fullReload) {
|
||||||
this._recreateDisplayItems();
|
|
||||||
this._initialLoadComplete = true;
|
this._initialLoadComplete = true;
|
||||||
}
|
this._redisplayFull();
|
||||||
|
} if (isSubSearch) {
|
||||||
if (isSubSearch) {
|
|
||||||
this._redisplaySubSearch();
|
this._redisplaySubSearch();
|
||||||
} else {
|
} else {
|
||||||
this._redisplayReordering();
|
this._redisplayReordering();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resetPage)
|
||||||
|
this._list.page = 0;
|
||||||
|
|
||||||
if (hadSelected) {
|
if (hadSelected) {
|
||||||
this._selectedIndex = -1;
|
this._selectedIndex = -1;
|
||||||
this.selectFirstItem();
|
this.selectFirstItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mainloop.idle_add(Lang.bind(this, this._checkInformationIcon),
|
||||||
|
Meta.PRIORITY_BEFORE_REDRAW);
|
||||||
|
|
||||||
this.emit('redisplayed');
|
this.emit('redisplayed');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Check if the pointer is over one of the items and display the information button if it is.
|
||||||
|
// We want to do this between finishing our changes to the display and the point where
|
||||||
|
// the display is redrawn.
|
||||||
|
_checkInformationIcon: function() {
|
||||||
|
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
||||||
|
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
||||||
|
x, y);
|
||||||
|
if (actor != null) {
|
||||||
|
let item = this._findDisplayedByActor(actor);
|
||||||
|
if (item != null) {
|
||||||
|
item.onDrawnUnderPointer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
//// Pure virtual protected methods ////
|
//// Pure virtual protected methods ////
|
||||||
|
|
||||||
// Performs the steps needed to have the latest information about the items.
|
// Performs the steps needed to have the latest information about the items.
|
||||||
// Implementation should return %true if we are up to date, and %false
|
// Implementation should return %true if we are up to date, and %false
|
||||||
// if a full reload occurred.
|
// if a full reload occurred.
|
||||||
_refreshCache: function() {
|
_refreshCache: function() {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sets the list of the displayed items based on the default sorting order.
|
// Sets the list of the displayed items based on the default sorting order.
|
||||||
// The default sorting order is specific to each implementing class.
|
// The default sorting order is specific to each implementing class.
|
||||||
_setDefaultList: function() {
|
_setDefaultList: function() {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Compares items associated with the item ids based on the order in which the
|
// Compares items associated with the item ids based on the order in which the
|
||||||
// items should be displayed.
|
// items should be displayed.
|
||||||
// Intended to be used as a compareFunction for array.sort().
|
// Intended to be used as a compareFunction for array.sort().
|
||||||
// Returns an integer value indicating the result of the comparison.
|
// Returns an integer value indicating the result of the comparison.
|
||||||
_compareItems: function(itemIdA, itemIdB) {
|
_compareItems: function(itemIdA, itemIdB) {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Checks if the item info can be a match for the search string.
|
// Checks if the item info can be a match for the search string.
|
||||||
// Returns a boolean flag indicating if that's the case.
|
// Returns a boolean flag indicating if that's the case.
|
||||||
_isInfoMatching: function(itemInfo, search) {
|
_isInfoMatching: function(itemInfo, search) {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Creates a display item based on itemInfo.
|
// Creates a display item based on itemInfo.
|
||||||
_createDisplayItem: function(itemInfo) {
|
_createDisplayItem: function(itemInfo) {
|
||||||
throw new Error('Not implemented');
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
@ -650,14 +756,59 @@ GenericDisplay.prototype = {
|
|||||||
return matchScores;
|
return matchScores;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Updates the display control to reflect the matched items set and the page selected.
|
||||||
|
*
|
||||||
|
* resetDisplayControl - indicates if the display control should be re-created because
|
||||||
|
* the results or the space allocated for them changed. If it's false,
|
||||||
|
* the existing display control is used and only the page links are
|
||||||
|
* updated to reflect the current page selection.
|
||||||
|
*/
|
||||||
|
_updateDisplayControl: function(resetDisplayControl) {
|
||||||
|
if (resetDisplayControl) {
|
||||||
|
this.displayControl.remove_all();
|
||||||
|
let nPages = this._list.n_pages;
|
||||||
|
// Don't show the page indicator if there is only one page.
|
||||||
|
if (nPages == 1)
|
||||||
|
return;
|
||||||
|
let pageNumber = this._list.page;
|
||||||
|
for (let i = 0; i < nPages; i++) {
|
||||||
|
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
|
||||||
|
font_name: "Sans Bold 16px",
|
||||||
|
text: (i+1) + "",
|
||||||
|
reactive: (i == pageNumber) ? false : true});
|
||||||
|
this.displayControl.append(pageControl.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
// we use pageNumberLocalScope to get the page number right in the callback function
|
||||||
|
let pageNumberLocalScope = i;
|
||||||
|
pageControl.connect('clicked',
|
||||||
|
Lang.bind(this,
|
||||||
|
function(o, event) {
|
||||||
|
this.displayPage(pageNumberLocalScope);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let pageControlActors = this.displayControl.get_children();
|
||||||
|
for (let i = 0; i < pageControlActors.length; i++) {
|
||||||
|
let pageControlActor = pageControlActors[i];
|
||||||
|
if (i == this._list.page) {
|
||||||
|
pageControlActor.color = DISPLAY_CONTROL_SELECTED_COLOR;
|
||||||
|
pageControlActor.reactive = false;
|
||||||
|
} else {
|
||||||
|
pageControlActor.color = ITEM_DISPLAY_DESCRIPTION_COLOR;
|
||||||
|
pageControlActor.reactive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.hasSelected()) {
|
||||||
|
this.selectFirstItem();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Returns a display item based on its index in the ordering of the
|
// Returns a display item based on its index in the ordering of the
|
||||||
// display children.
|
// display children.
|
||||||
_findDisplayedByIndex: function(index) {
|
_findDisplayedByIndex: function(index) {
|
||||||
let actor;
|
let actor = this._list.get_displayed_actor(index);
|
||||||
if (this.actor instanceof Shell.OverflowList)
|
|
||||||
actor = this.actor.get_displayed_actor(index);
|
|
||||||
else
|
|
||||||
actor = this._list.get_children()[index];
|
|
||||||
return this._findDisplayedByActor(actor);
|
return this._findDisplayedByActor(actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -683,26 +834,12 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
this._selectedIndex = index;
|
this._selectedIndex = index;
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return;
|
return
|
||||||
|
|
||||||
// Mark the new item as selected and create its details pane
|
// Mark the new item as selected and create its details pane
|
||||||
let item = this._findDisplayedByIndex(index);
|
let item = this._findDisplayedByIndex(index);
|
||||||
item.markSelected(true);
|
item.markSelected(true);
|
||||||
this.emit('selected');
|
this.emit('selected');
|
||||||
},
|
|
||||||
|
|
||||||
_getVisibleCount: function() {
|
|
||||||
if (this.actor instanceof Shell.OverflowList)
|
|
||||||
return this._list.displayed_count;
|
|
||||||
return this._list.get_n_children();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMappedNotify: function () {
|
|
||||||
let mapped = this.actor.mapped;
|
|
||||||
if (mapped && this._pendingRedisplay > RedisplayFlags.NONE)
|
|
||||||
this._redisplay(this._pendingRedisplay);
|
|
||||||
|
|
||||||
this._pendingRedisplay = RedisplayFlags.NONE;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const St = imports.gi.St;
|
const Main = imports.ui.main;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
const SHADE_COLOR = new Clutter.Color();
|
||||||
|
SHADE_COLOR.from_pixel(0x00000044);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lightbox:
|
* Lightbox:
|
||||||
* @container: parent Clutter.Container
|
* @container: parent Clutter.Container
|
||||||
* @inhibitEvents: whether to inhibit events for @container
|
|
||||||
* @width: (optional) shade actor width
|
* @width: (optional) shade actor width
|
||||||
* @height: (optional) shade actor height
|
* @height: (optional) shade actor height
|
||||||
*
|
*
|
||||||
@ -26,23 +29,24 @@ const St = imports.gi.St;
|
|||||||
* @container and will track any changes in its size. You can override
|
* @container and will track any changes in its size. You can override
|
||||||
* this by passing an explicit width and height
|
* this by passing an explicit width and height
|
||||||
*/
|
*/
|
||||||
function Lightbox(container, inhibitEvents, width, height) {
|
function Lightbox(container, width, height) {
|
||||||
this._init(container, inhibitEvents, width, height);
|
this._init(container, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lightbox.prototype = {
|
Lightbox.prototype = {
|
||||||
_init : function(container, inhibitEvents, width, height) {
|
_init : function(container, width, height) {
|
||||||
this._container = container;
|
this._container = container;
|
||||||
this._children = container.get_children();
|
this._children = container.get_children();
|
||||||
this.actor = new St.Bin({ x: 0,
|
this.actor = new Clutter.Rectangle({ color: SHADE_COLOR,
|
||||||
y: 0,
|
x: 0,
|
||||||
style_class: 'lightbox',
|
y: 0,
|
||||||
reactive: inhibitEvents });
|
border_width: 0,
|
||||||
|
reactive: true });
|
||||||
|
|
||||||
container.add_actor(this.actor);
|
container.add_actor(this.actor);
|
||||||
this.actor.raise_top();
|
this.actor.raise_top();
|
||||||
|
|
||||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
this._destroySignalId = this.actor.connect('destroy', Lang.bind(this, this.destroy));
|
||||||
|
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
this.actor.width = width;
|
this.actor.width = width;
|
||||||
@ -61,13 +65,8 @@ Lightbox.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_allocationChanged : function(container, box, flags) {
|
_allocationChanged : function(container, box, flags) {
|
||||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
this.actor.width = this._container.width;
|
||||||
this.actor.width = this.width;
|
this.actor.height = this._container.height;
|
||||||
this.actor.height = this.height;
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
this.width = this._container.width;
|
|
||||||
this.height = this._container.height;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_actorAdded : function(container, newChild) {
|
_actorAdded : function(container, newChild) {
|
||||||
@ -135,24 +134,18 @@ Lightbox.prototype = {
|
|||||||
/**
|
/**
|
||||||
* destroy:
|
* destroy:
|
||||||
*
|
*
|
||||||
* Destroys the lightbox.
|
* Destroys the lightbox. This is called automatically if the
|
||||||
|
* lightbox's container is destroyed.
|
||||||
*/
|
*/
|
||||||
destroy : function() {
|
destroy : function() {
|
||||||
this.actor.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* _onDestroy:
|
|
||||||
*
|
|
||||||
* This is called when the lightbox' actor is destroyed, either
|
|
||||||
* by destroying its container or by explicitly calling this.destroy().
|
|
||||||
*/
|
|
||||||
_onDestroy: function() {
|
|
||||||
if (this._allocationChangedSignalId != 0)
|
if (this._allocationChangedSignalId != 0)
|
||||||
this._container.disconnect(this._allocationChangedSignalId);
|
this._container.disconnect(this._allocationChangedSignalId);
|
||||||
this._container.disconnect(this._actorAddedSignalId);
|
this._container.disconnect(this._actorAddedSignalId);
|
||||||
this._container.disconnect(this._actorRemovedSignalId);
|
this._container.disconnect(this._actorRemovedSignalId);
|
||||||
|
|
||||||
|
this.actor.disconnect(this._destroySignalId);
|
||||||
|
|
||||||
this.highlight(null);
|
this.highlight(null);
|
||||||
|
this.actor.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3,22 +3,78 @@
|
|||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
|
// Link is a clickable link. Right now it just handles properly capturing
|
||||||
|
// press and release events and short-circuiting the button handling in
|
||||||
|
// ClutterText, but more features like different colors for hover/pressed states
|
||||||
|
// or a different mouse cursor could be implemented.
|
||||||
|
//
|
||||||
|
// The properties passed in are forwarded to the Clutter.Text() constructor,
|
||||||
|
// so can include, 'text', 'font_name', etc.
|
||||||
function Link(props) {
|
function Link(props) {
|
||||||
this._init(props);
|
this._init(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
Link.prototype = {
|
Link.prototype = {
|
||||||
_init : function(props) {
|
_init : function(props) {
|
||||||
let realProps = { reactive: true,
|
let realProps = { reactive: true };
|
||||||
track_hover: true,
|
|
||||||
style_class: 'shell-link' };
|
|
||||||
// The user can pass in reactive: false to override the above and get
|
// The user can pass in reactive: false to override the above and get
|
||||||
// a non-reactive link (a link to the current page, perhaps)
|
// a non-reactive link (a link to the current page, perhaps)
|
||||||
Lang.copyProperties(props, realProps);
|
Lang.copyProperties(props, realProps);
|
||||||
|
|
||||||
this.actor = new St.Button(realProps);
|
this.actor = new Clutter.Text(realProps);
|
||||||
|
this.actor._delegate = this;
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||||
|
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||||
|
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
|
||||||
|
this.actor.connect('leave-event', Lang.bind(this, this._onLeave));
|
||||||
|
|
||||||
|
this._buttonDown = false;
|
||||||
|
this._havePointer = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update the text of the link
|
||||||
|
setText : function(text) {
|
||||||
|
this.actor.text = text;
|
||||||
|
},
|
||||||
|
|
||||||
|
// We want to react on buttonDown, but if we override button-release-event for
|
||||||
|
// ClutterText, but not button-press-event, we get a stuck grab. Tracking
|
||||||
|
// buttonDown and doing the grab isn't really necessary, but doing it makes
|
||||||
|
// the behavior perfectly correct if the user clicks on one actor, drags
|
||||||
|
// to another and releases - that should not trigger either actor.
|
||||||
|
_onButtonPress : function(actor, event) {
|
||||||
|
this._buttonDown = true;
|
||||||
|
this._havePointer = true; // Hack to work around poor enter/leave tracking in Clutter
|
||||||
|
Clutter.grab_pointer(actor);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onButtonRelease : function(actor, event) {
|
||||||
|
if (this._buttonDown) {
|
||||||
|
this._buttonDown = false;
|
||||||
|
Clutter.ungrab_pointer(actor);
|
||||||
|
|
||||||
|
if (this._havePointer)
|
||||||
|
this.emit('clicked');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onEnter : function(actor, event) {
|
||||||
|
if (event.get_source() == actor)
|
||||||
|
this._havePointer = true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onLeave : function(actor, event) {
|
||||||
|
if (event.get_source() == actor)
|
||||||
|
this._havePointer = false;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
@ -9,31 +9,27 @@ const Shell = imports.gi.Shell;
|
|||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const ExtensionSystem = imports.ui.extensionSystem;
|
|
||||||
const Link = imports.ui.link;
|
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
/* Imports...feel free to add here as needed */
|
/* Imports...feel free to add here as needed */
|
||||||
var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
|
var commandHeader = "const Clutter = imports.gi.Clutter; " +
|
||||||
'const GLib = imports.gi.GLib; ' +
|
"const GLib = imports.gi.GLib; " +
|
||||||
'const Gtk = imports.gi.Gtk; ' +
|
"const Gtk = imports.gi.Gtk; " +
|
||||||
'const Mainloop = imports.mainloop; ' +
|
"const Mainloop = imports.mainloop; " +
|
||||||
'const Meta = imports.gi.Meta; ' +
|
"const Meta = imports.gi.Meta; " +
|
||||||
'const Shell = imports.gi.Shell; ' +
|
"const Shell = imports.gi.Shell; " +
|
||||||
'const Main = imports.ui.main; ' +
|
"const Main = imports.ui.main; " +
|
||||||
'const Lang = imports.lang; ' +
|
"const Lang = imports.lang; " +
|
||||||
'const Tweener = imports.ui.tweener; ' +
|
"const Tweener = imports.ui.tweener; " +
|
||||||
/* Utility functions...we should probably be able to use these
|
/* Utility functions...we should probably be able to use these
|
||||||
* in the shell core code too. */
|
* in the shell core code too. */
|
||||||
'const stage = global.stage; ' +
|
"const stage = global.stage; " +
|
||||||
'const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; ' +
|
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
|
||||||
/* Special lookingGlass functions */
|
/* Special lookingGlass functions */
|
||||||
'const it = Main.lookingGlass.getIt(); ' +
|
"const it = Main.lookingGlass.getIt(); " +
|
||||||
'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
|
"const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ";
|
||||||
|
|
||||||
function Notebook() {
|
function Notebook() {
|
||||||
this._init();
|
this._init();
|
||||||
@ -43,41 +39,33 @@ Notebook.prototype = {
|
|||||||
_init: function() {
|
_init: function() {
|
||||||
this.actor = new St.BoxLayout({ vertical: true });
|
this.actor = new St.BoxLayout({ vertical: true });
|
||||||
|
|
||||||
this.tabControls = new St.BoxLayout({ style_class: 'labels' });
|
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
spacing: 4, padding: 2 });
|
||||||
|
|
||||||
this._selectedIndex = -1;
|
this._selectedIndex = -1;
|
||||||
this._tabs = [];
|
this._tabs = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
appendPage: function(name, child) {
|
appendPage: function(name, child) {
|
||||||
let labelBox = new St.BoxLayout({ style_class: 'notebook-tab',
|
let labelOuterBox = new Big.Box({ padding: 2 });
|
||||||
reactive: true,
|
let labelBox = new St.BoxLayout({ reactive: true });
|
||||||
track_hover: true });
|
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
|
||||||
let label = new St.Button({ label: name });
|
let label = new St.Label({ text: name });
|
||||||
label.connect('clicked', Lang.bind(this, function () {
|
labelBox.connect('button-press-event', Lang.bind(this, function () {
|
||||||
this.selectChild(child);
|
this.selectChild(child);
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
labelBox.add(label, { expand: true });
|
labelBox.add(label, { expand: true });
|
||||||
this.tabControls.add(labelBox);
|
this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
let scrollview = new St.ScrollView({ x_fill: true, y_fill: true });
|
let scrollview = new St.ScrollView({ x_fill: true, y_fill: true });
|
||||||
scrollview.get_hscroll_bar().hide();
|
scrollview.get_hscroll_bar().hide();
|
||||||
scrollview.add_actor(child);
|
scrollview.add_actor(child);
|
||||||
|
|
||||||
let tabData = { child: child,
|
this._tabs.push([child, labelBox, scrollview]);
|
||||||
labelBox: labelBox,
|
|
||||||
label: label,
|
|
||||||
scrollView: scrollview,
|
|
||||||
_scrollToBottom: false };
|
|
||||||
this._tabs.push(tabData);
|
|
||||||
scrollview.hide();
|
scrollview.hide();
|
||||||
this.actor.add(scrollview, { expand: true });
|
this.actor.add(scrollview, { expand: true });
|
||||||
|
|
||||||
let vAdjust = scrollview.vscroll.adjustment;
|
|
||||||
vAdjust.connect('changed', Lang.bind(this, function () { this._onAdjustScopeChanged(tabData); }));
|
|
||||||
vAdjust.connect('notify::value', Lang.bind(this, function() { this._onAdjustValueChanged(tabData); }));
|
|
||||||
|
|
||||||
if (this._selectedIndex == -1)
|
if (this._selectedIndex == -1)
|
||||||
this.selectIndex(0);
|
this.selectIndex(0);
|
||||||
},
|
},
|
||||||
@ -85,9 +73,10 @@ Notebook.prototype = {
|
|||||||
_unselect: function() {
|
_unselect: function() {
|
||||||
if (this._selectedIndex < 0)
|
if (this._selectedIndex < 0)
|
||||||
return;
|
return;
|
||||||
let tabData = this._tabs[this._selectedIndex];
|
let [child, labelBox, scrollview] = this._tabs[this._selectedIndex];
|
||||||
tabData.labelBox.remove_style_pseudo_class('selected');
|
labelBox.padding = 2;
|
||||||
tabData.scrollView.hide();
|
labelBox.border = 0;
|
||||||
|
scrollview.hide();
|
||||||
this._selectedIndex = -1;
|
this._selectedIndex = -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -99,11 +88,12 @@ Notebook.prototype = {
|
|||||||
this.emit('selection', null);
|
this.emit('selection', null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tabData = this._tabs[index];
|
let [child, labelBox, scrollview] = this._tabs[index];
|
||||||
tabData.labelBox.add_style_pseudo_class('selected');
|
labelBox.padding = 1;
|
||||||
tabData.scrollView.show();
|
labelBox.border = 1;
|
||||||
|
scrollview.show();
|
||||||
this._selectedIndex = index;
|
this._selectedIndex = index;
|
||||||
this.emit('selection', tabData.child);
|
this.emit('selection', child);
|
||||||
},
|
},
|
||||||
|
|
||||||
selectChild: function(child) {
|
selectChild: function(child) {
|
||||||
@ -111,70 +101,17 @@ Notebook.prototype = {
|
|||||||
this.selectIndex(-1);
|
this.selectIndex(-1);
|
||||||
else {
|
else {
|
||||||
for (let i = 0; i < this._tabs.length; i++) {
|
for (let i = 0; i < this._tabs.length; i++) {
|
||||||
let tabData = this._tabs[i];
|
let [tabChild, labelBox, scrollview] = this._tabs[i];
|
||||||
if (tabData.child == child) {
|
if (tabChild == child) {
|
||||||
this.selectIndex(i);
|
this.selectIndex(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
scrollToBottom: function(index) {
|
|
||||||
let tabData = this._tabs[index];
|
|
||||||
tabData._scrollToBottom = true;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_onAdjustValueChanged: function (tabData) {
|
|
||||||
let vAdjust = tabData.scrollView.vscroll.adjustment;
|
|
||||||
if (vAdjust.value < (vAdjust.upper - vAdjust.lower - 0.5))
|
|
||||||
tabData._scrolltoBottom = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onAdjustScopeChanged: function (tabData) {
|
|
||||||
if (!tabData._scrollToBottom)
|
|
||||||
return;
|
|
||||||
let vAdjust = tabData.scrollView.vscroll.adjustment;
|
|
||||||
vAdjust.value = vAdjust.upper - vAdjust.page_size;
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Signals.addSignalMethods(Notebook.prototype);
|
Signals.addSignalMethods(Notebook.prototype);
|
||||||
|
|
||||||
function objectToString(o) {
|
|
||||||
if (typeof(o) == typeof(objectToString)) {
|
|
||||||
// special case this since the default is way, way too verbose
|
|
||||||
return "<js function>";
|
|
||||||
} else {
|
|
||||||
return "" + o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ObjLink(o, title) {
|
|
||||||
this._init(o, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjLink.prototype = {
|
|
||||||
__proto__: Link.Link,
|
|
||||||
|
|
||||||
_init: function(o, title) {
|
|
||||||
let text;
|
|
||||||
if (title)
|
|
||||||
text = title;
|
|
||||||
else
|
|
||||||
text = objectToString(o);
|
|
||||||
text = GLib.markup_escape_text(text, -1);
|
|
||||||
this._obj = o;
|
|
||||||
Link.Link.prototype._init.call(this, { label: text });
|
|
||||||
this.actor.get_child().single_line_mode = true;
|
|
||||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClicked: function (link) {
|
|
||||||
Main.lookingGlass.inspectObject(this._obj, this.actor);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Result(command, o, index) {
|
function Result(command, o, index) {
|
||||||
this._init(command, o, index);
|
this._init(command, o, index);
|
||||||
}
|
}
|
||||||
@ -184,175 +121,108 @@ Result.prototype = {
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
this.o = o;
|
this.o = o;
|
||||||
|
|
||||||
this.actor = new St.BoxLayout({ vertical: true });
|
this.actor = new Big.Box();
|
||||||
|
|
||||||
let cmdTxt = new St.Label({ text: command });
|
let cmdTxt = new St.Label({ text: command });
|
||||||
cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
cmdTxt.ellipsize = Pango.EllipsizeMode.END;
|
||||||
this.actor.add(cmdTxt);
|
|
||||||
let box = new St.BoxLayout({});
|
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
|
||||||
this.actor.add(box);
|
let resultTxt = new St.Label({ text: "r(" + index + ") = " + o });
|
||||||
let resultTxt = new St.Label({ text: 'r(' + index + ') = ' });
|
resultTxt.ellipsize = Pango.EllipsizeMode.END;
|
||||||
resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
|
||||||
box.add(resultTxt);
|
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
|
||||||
let objLink = new ObjLink(o);
|
let line = new Clutter.Rectangle({ name: "Separator",
|
||||||
box.add(objLink.actor);
|
height: 1 });
|
||||||
let line = new Clutter.Rectangle({ name: 'Separator' });
|
let padBin = new St.Bin({ name: "Separator", x_fill: true, y_fill: true });
|
||||||
let padBin = new St.Bin({ name: 'Separator', x_fill: true, y_fill: true });
|
|
||||||
padBin.add_actor(line);
|
padBin.add_actor(line);
|
||||||
this.actor.add(padBin);
|
this.actor.append(padBin, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function WindowList() {
|
function ActorHierarchy() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowList.prototype = {
|
ActorHierarchy.prototype = {
|
||||||
_init : function () {
|
_init : function () {
|
||||||
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
|
this._previousTarget = null;
|
||||||
let display = global.screen.get_display();
|
this._target = null;
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
|
||||||
this._updateId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._updateWindowList));
|
|
||||||
display.connect('window-created', Lang.bind(this, this._updateWindowList));
|
|
||||||
tracker.connect('tracked-windows-changed', Lang.bind(this, this._updateWindowList));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateWindowList: function() {
|
|
||||||
this.actor.get_children().forEach(function (actor) { actor.destroy(); });
|
|
||||||
let windows = global.get_windows();
|
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
|
||||||
for (let i = 0; i < windows.length; i++) {
|
|
||||||
let metaWindow = windows[i].metaWindow;
|
|
||||||
metaWindow.connect('unmanaged', Lang.bind(this, this._updateWindowList));
|
|
||||||
let box = new St.BoxLayout({ vertical: true });
|
|
||||||
this.actor.add(box);
|
|
||||||
let windowLink = new ObjLink(metaWindow, metaWindow.title);
|
|
||||||
box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false });
|
|
||||||
let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
|
|
||||||
box.add(propsBox);
|
|
||||||
propsBox.add(new St.Label({ text: 'wmclass: ' + metaWindow.get_wm_class() }));
|
|
||||||
let app = tracker.get_window_app(metaWindow);
|
|
||||||
if (app != null && !app.is_transient()) {
|
|
||||||
let icon = app.create_icon_texture(22);
|
|
||||||
let propBox = new St.BoxLayout({ style: 'spacing: 6px; ' });
|
|
||||||
propsBox.add(propBox);
|
|
||||||
propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false });
|
|
||||||
let appLink = new ObjLink(app, app.get_id());
|
|
||||||
propBox.add(appLink.actor, { y_fill: false });
|
|
||||||
propBox.add(icon, { y_fill: false });
|
|
||||||
} else {
|
|
||||||
propsBox.add(new St.Label({ text: '<untracked>' }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(WindowList.prototype);
|
|
||||||
|
|
||||||
function ObjInspector() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjInspector.prototype = {
|
|
||||||
_init : function () {
|
|
||||||
this._obj = null;
|
|
||||||
this._previousObj = null;
|
|
||||||
|
|
||||||
this._parentList = [];
|
this._parentList = [];
|
||||||
|
|
||||||
this.actor = new St.ScrollView({ x_fill: true, y_fill: true });
|
this.actor = new St.BoxLayout({ name: "ActorHierarchy", vertical: true });
|
||||||
this.actor.get_hscroll_bar().hide();
|
|
||||||
this._container = new St.BoxLayout({ name: 'LookingGlassPropertyInspector',
|
|
||||||
style_class: 'lg-dialog',
|
|
||||||
vertical: true });
|
|
||||||
this.actor.add_actor(this._container);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
selectObject: function(obj, skipPrevious) {
|
setTarget: function(actor) {
|
||||||
if (!skipPrevious)
|
this._previousTarget = this._target;
|
||||||
this._previousObj = this._obj;
|
this.target = actor;
|
||||||
else
|
|
||||||
this._previousObj = null;
|
|
||||||
this._obj = obj;
|
|
||||||
|
|
||||||
this._container.get_children().forEach(function (child) { child.destroy(); });
|
this.actor.get_children().forEach(function (child) { child.destroy(); });
|
||||||
|
|
||||||
let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' });
|
if (!(actor instanceof Clutter.Actor))
|
||||||
this._container.add_actor(hbox);
|
|
||||||
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof(obj),
|
|
||||||
objectToString(obj)) });
|
|
||||||
label.single_line_mode = true;
|
|
||||||
hbox.add(label, { expand: true, y_fill: false });
|
|
||||||
let button = new St.Button({ label: 'Insert', style_class: 'lg-obj-inspector-button' });
|
|
||||||
button.connect('clicked', Lang.bind(this, this._onInsert));
|
|
||||||
hbox.add(button);
|
|
||||||
|
|
||||||
if (this._previousObj != null) {
|
|
||||||
button = new St.Button({ label: 'Back', style_class: 'lg-obj-inspector-button' });
|
|
||||||
button.connect('clicked', Lang.bind(this, this._onBack));
|
|
||||||
hbox.add(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
button = new St.Button({ style_class: 'window-close' });
|
|
||||||
button.connect('clicked', Lang.bind(this, this.close));
|
|
||||||
hbox.add(button);
|
|
||||||
if (typeof(obj) == typeof({})) {
|
|
||||||
for (let propName in obj) {
|
|
||||||
let valueStr;
|
|
||||||
let link;
|
|
||||||
try {
|
|
||||||
let prop = obj[propName];
|
|
||||||
link = new ObjLink(prop).actor;
|
|
||||||
} catch (e) {
|
|
||||||
link = new St.Label({ text: '<error>' });
|
|
||||||
}
|
|
||||||
let hbox = new St.BoxLayout();
|
|
||||||
let propText = propName + ": " + valueStr;
|
|
||||||
hbox.add(new St.Label({ text: propName + ': ' }));
|
|
||||||
hbox.add(link);
|
|
||||||
this._container.add_actor(hbox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
open: function(sourceActor) {
|
|
||||||
if (this._open)
|
|
||||||
return;
|
return;
|
||||||
this._previousObj = null;
|
|
||||||
this._open = true;
|
|
||||||
this.actor.show();
|
|
||||||
if (sourceActor) {
|
|
||||||
this.actor.set_scale(0, 0);
|
|
||||||
let [sourceX, sourceY] = sourceActor.get_transformed_position();
|
|
||||||
let [sourceWidth, sourceHeight] = sourceActor.get_transformed_size();
|
|
||||||
this.actor.move_anchor_point(Math.floor(sourceX + sourceWidth / 2),
|
|
||||||
Math.floor(sourceY + sourceHeight / 2));
|
|
||||||
Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
|
|
||||||
transition: "easeOutQuad",
|
|
||||||
time: 0.2 });
|
|
||||||
} else {
|
|
||||||
this.actor.set_scale(1, 1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function() {
|
if (this.target == null)
|
||||||
if (!this._open)
|
|
||||||
return;
|
return;
|
||||||
this._open = false;
|
|
||||||
this.actor.hide();
|
this._parentList = [];
|
||||||
this._previousObj = null;
|
let parent = actor;
|
||||||
this._obj = null;
|
while ((parent = parent.get_parent()) != null) {
|
||||||
|
this._parentList.push(parent);
|
||||||
|
|
||||||
|
let link = new St.Label({ reactive: true,
|
||||||
|
text: "" + parent });
|
||||||
|
this.actor.add_actor(link);
|
||||||
|
let parentTarget = parent;
|
||||||
|
link.connect('button-press-event', Lang.bind(this, function () {
|
||||||
|
this._selectByActor(parentTarget);
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.emit('selection', actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onInsert: function() {
|
_selectByActor: function(actor) {
|
||||||
let obj = this._obj;
|
let idx = this._parentList.indexOf(actor);
|
||||||
this.close();
|
let children = this.actor.get_children();
|
||||||
Main.lookingGlass.insertObject(obj);
|
let link = children[idx];
|
||||||
},
|
this.emit('selection', actor);
|
||||||
|
|
||||||
_onBack: function() {
|
|
||||||
this.selectObject(this._previousObj, true);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
Signals.addSignalMethods(ActorHierarchy.prototype);
|
||||||
|
|
||||||
|
function PropertyInspector() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyInspector.prototype = {
|
||||||
|
_init : function () {
|
||||||
|
this._target = null;
|
||||||
|
|
||||||
|
this._parentList = [];
|
||||||
|
|
||||||
|
this.actor = new St.BoxLayout({ name: "PropertyInspector", vertical: true });
|
||||||
|
},
|
||||||
|
|
||||||
|
setTarget: function(actor) {
|
||||||
|
this.target = actor;
|
||||||
|
|
||||||
|
this.actor.get_children().forEach(function (child) { child.destroy(); });
|
||||||
|
|
||||||
|
for (let propName in actor) {
|
||||||
|
let valueStr;
|
||||||
|
try {
|
||||||
|
valueStr = "" + actor[propName];
|
||||||
|
} catch (e) {
|
||||||
|
valueStr = '<error>';
|
||||||
|
}
|
||||||
|
let propText = propName + ": " + valueStr;
|
||||||
|
let propDisplay = new St.Label({ reactive: true,
|
||||||
|
text: propText });
|
||||||
|
this.actor.add_actor(propDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Inspector() {
|
function Inspector() {
|
||||||
this._init();
|
this._init();
|
||||||
@ -361,15 +231,14 @@ function Inspector() {
|
|||||||
Inspector.prototype = {
|
Inspector.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
let width = 150;
|
let width = 150;
|
||||||
let primary = global.get_primary_monitor();
|
let eventHandler = new St.BoxLayout({ name: "LookingGlassDialog",
|
||||||
let eventHandler = new St.BoxLayout({ name: 'LookingGlassDialog',
|
|
||||||
vertical: false,
|
vertical: false,
|
||||||
y: primary.y + Math.floor(primary.height / 2),
|
y: Math.floor(global.stage.height/2),
|
||||||
reactive: true });
|
reactive: true });
|
||||||
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
|
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
|
||||||
eventHandler.x = primary.x + Math.floor((primary.width - eventHandler.width) / 2);
|
eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2);
|
||||||
}));
|
}));
|
||||||
Main.uiGroup.add_actor(eventHandler);
|
global.stage.add_actor(eventHandler);
|
||||||
let displayText = new St.Label();
|
let displayText = new St.Label();
|
||||||
eventHandler.add(displayText, { expand: true });
|
eventHandler.add(displayText, { expand: true });
|
||||||
|
|
||||||
@ -398,14 +267,7 @@ Inspector.prototype = {
|
|||||||
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
||||||
stageX,
|
stageX,
|
||||||
stageY);
|
stageY);
|
||||||
let id, style_class;
|
displayText.text = '<inspect x: ' + stageX + ' y: ' + stageY + '> ' + target;
|
||||||
if (target instanceof St.Widget) {
|
|
||||||
id = target.get_theme_node().get_element_id();
|
|
||||||
style_class = target.get_theme_node().get_element_class();
|
|
||||||
}
|
|
||||||
let position = '<inspect x: ' + stageX + ' y: ' + stageY + '>';
|
|
||||||
let style = '<style id: ' + id + ' class: ' + style_class + '>';
|
|
||||||
displayText.text = position + ' ' + style + ' ' + target;
|
|
||||||
if (borderPaintTarget != null)
|
if (borderPaintTarget != null)
|
||||||
borderPaintTarget.disconnect(borderPaintId);
|
borderPaintTarget.disconnect(borderPaintId);
|
||||||
borderPaintTarget = target;
|
borderPaintTarget = target;
|
||||||
@ -414,139 +276,10 @@ Inspector.prototype = {
|
|||||||
}));
|
}));
|
||||||
Clutter.grab_pointer(eventHandler);
|
Clutter.grab_pointer(eventHandler);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Signals.addSignalMethods(Inspector.prototype);
|
Signals.addSignalMethods(Inspector.prototype);
|
||||||
|
|
||||||
function ErrorLog() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorLog.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.BoxLayout();
|
|
||||||
this.text = new St.Label();
|
|
||||||
this.actor.add(this.text);
|
|
||||||
this.text.clutter_text.line_wrap = true;
|
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this, this._renderText));
|
|
||||||
},
|
|
||||||
|
|
||||||
_formatTime: function(d){
|
|
||||||
function pad(n) { return n < 10 ? '0' + n : n; }
|
|
||||||
return d.getUTCFullYear()+'-'
|
|
||||||
+ pad(d.getUTCMonth()+1)+'-'
|
|
||||||
+ pad(d.getUTCDate())+'T'
|
|
||||||
+ pad(d.getUTCHours())+':'
|
|
||||||
+ pad(d.getUTCMinutes())+':'
|
|
||||||
+ pad(d.getUTCSeconds())+'Z';
|
|
||||||
},
|
|
||||||
|
|
||||||
_renderText: function() {
|
|
||||||
if (!this.actor.mapped)
|
|
||||||
return;
|
|
||||||
let text = this.text.text;
|
|
||||||
let stack = Main._getAndClearErrorStack();
|
|
||||||
for (let i = 0; i < stack.length; i++) {
|
|
||||||
let logItem = stack[i];
|
|
||||||
text += logItem.category + ' t=' + this._formatTime(new Date(logItem.timestamp)) + ' ' + logItem.message + '\n';
|
|
||||||
}
|
|
||||||
this.text.text = text;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Extensions() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Extensions.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.BoxLayout({ vertical: true,
|
|
||||||
name: 'lookingGlassExtensions' });
|
|
||||||
this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
|
|
||||||
text: _("No extensions installed") });
|
|
||||||
this._extensionsList = new St.BoxLayout({ vertical: true,
|
|
||||||
style_class: 'lg-extensions-list' });
|
|
||||||
this.actor.add(this._extensionsList);
|
|
||||||
this._loadExtensionList();
|
|
||||||
},
|
|
||||||
|
|
||||||
_loadExtensionList: function() {
|
|
||||||
let extensions = ExtensionSystem.extensionMeta;
|
|
||||||
let totalExtensions = 0;
|
|
||||||
for (let uuid in extensions) {
|
|
||||||
let extensionDisplay = this._createExtensionDisplay(extensions[uuid]);
|
|
||||||
this._extensionsList.add(extensionDisplay);
|
|
||||||
totalExtensions++;
|
|
||||||
}
|
|
||||||
if (totalExtensions == 0) {
|
|
||||||
this._extensionsList.add(this._noExtensions);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onViewSource: function (actor) {
|
|
||||||
let meta = actor._extensionMeta;
|
|
||||||
let file = Gio.file_new_for_path(meta.path);
|
|
||||||
let uri = file.get_uri();
|
|
||||||
Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context());
|
|
||||||
Main.lookingGlass.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onWebPage: function (actor) {
|
|
||||||
let meta = actor._extensionMeta;
|
|
||||||
Gio.app_info_launch_default_for_uri(meta.url, global.create_app_launch_context());
|
|
||||||
Main.lookingGlass.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
_stateToString: function(extensionState) {
|
|
||||||
switch (extensionState) {
|
|
||||||
case ExtensionSystem.ExtensionState.ENABLED:
|
|
||||||
return _("Enabled");
|
|
||||||
case ExtensionSystem.ExtensionState.DISABLED:
|
|
||||||
return _("Disabled");
|
|
||||||
case ExtensionSystem.ExtensionState.ERROR:
|
|
||||||
return _("Error");
|
|
||||||
case ExtensionSystem.ExtensionState.OUT_OF_DATE:
|
|
||||||
return _("Out of date");
|
|
||||||
}
|
|
||||||
return 'Unknown'; // Not translated, shouldn't appear
|
|
||||||
},
|
|
||||||
|
|
||||||
_createExtensionDisplay: function(meta) {
|
|
||||||
let box = new St.BoxLayout({ style_class: 'lg-extension', vertical: true });
|
|
||||||
let name = new St.Label({ style_class: 'lg-extension-name',
|
|
||||||
text: meta.name });
|
|
||||||
box.add(name, { expand: true });
|
|
||||||
let description = new St.Label({ style_class: 'lg-extension-description',
|
|
||||||
text: meta.description });
|
|
||||||
box.add(description, { expand: true });
|
|
||||||
|
|
||||||
let metaBox = new St.BoxLayout();
|
|
||||||
box.add(metaBox);
|
|
||||||
let stateString = this._stateToString(meta.state);
|
|
||||||
let state = new St.Label({ style_class: 'lg-extension-state',
|
|
||||||
text: this._stateToString(meta.state) });
|
|
||||||
|
|
||||||
let actionsContainer = new St.Bin({ x_align: St.Align.END });
|
|
||||||
metaBox.add(actionsContainer);
|
|
||||||
let actionsBox = new St.BoxLayout({ style_class: 'lg-extension-actions' });
|
|
||||||
actionsContainer.set_child(actionsBox);
|
|
||||||
|
|
||||||
let viewsource = new Link.Link({ label: _("View Source") });
|
|
||||||
viewsource.actor._extensionMeta = meta;
|
|
||||||
viewsource.actor.connect('clicked', Lang.bind(this, this._onViewSource));
|
|
||||||
actionsBox.add(viewsource.actor);
|
|
||||||
|
|
||||||
if (meta.url) {
|
|
||||||
let webpage = new Link.Link({ label: _("Web Page") });
|
|
||||||
webpage.actor._extensionMeta = meta;
|
|
||||||
webpage.actor.connect('clicked', Lang.bind(this, this._onWebPage));
|
|
||||||
actionsBox.add(webpage.actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function LookingGlass() {
|
function LookingGlass() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -554,15 +287,11 @@ function LookingGlass() {
|
|||||||
LookingGlass.prototype = {
|
LookingGlass.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this._idleHistorySaveId = 0;
|
this._idleHistorySaveId = 0;
|
||||||
let historyPath = global.userdatadir + '/lookingglass-history.txt';
|
let historyPath = global.configdir + "/lookingglass-history.txt";
|
||||||
this._historyFile = Gio.file_new_for_path(historyPath);
|
this._historyFile = Gio.file_new_for_path(historyPath);
|
||||||
this._savedText = null;
|
this._savedText = null;
|
||||||
this._historyNavIndex = -1;
|
this._historyNavIndex = -1;
|
||||||
this._history = [];
|
this._history = [];
|
||||||
this._borderPaintTarget = null;
|
|
||||||
this._borderPaintId = 0;
|
|
||||||
this._borderDestroyId = 0;
|
|
||||||
|
|
||||||
this._readHistory();
|
this._readHistory();
|
||||||
|
|
||||||
this._open = false;
|
this._open = false;
|
||||||
@ -573,27 +302,22 @@ LookingGlass.prototype = {
|
|||||||
// Sort of magic, but...eh.
|
// Sort of magic, but...eh.
|
||||||
this._maxItems = 150;
|
this._maxItems = 150;
|
||||||
|
|
||||||
this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
|
this.actor = new St.BoxLayout({ name: "LookingGlassDialog",
|
||||||
style_class: 'lg-dialog',
|
|
||||||
vertical: true,
|
vertical: true,
|
||||||
visible: false });
|
visible: false });
|
||||||
|
|
||||||
let gconf = Shell.GConf.get_default();
|
let gconf = Shell.GConf.get_default();
|
||||||
gconf.watch_directory('/desktop/gnome/interface');
|
gconf.watch_directory("/desktop/gnome/interface");
|
||||||
gconf.connect('changed::/desktop/gnome/interface/monospace_font_name',
|
gconf.connect("changed::/desktop/gnome/interface/monospace_font_name",
|
||||||
Lang.bind(this, this._updateFont));
|
Lang.bind(this, this._updateFont));
|
||||||
this._updateFont();
|
this._updateFont();
|
||||||
|
|
||||||
Main.uiGroup.add_actor(this.actor);
|
global.stage.add_actor(this.actor);
|
||||||
|
|
||||||
this._objInspector = new ObjInspector();
|
let toolbar = new St.BoxLayout({ name: "Toolbar" });
|
||||||
Main.uiGroup.add_actor(this._objInspector.actor);
|
|
||||||
this._objInspector.actor.hide();
|
|
||||||
|
|
||||||
let toolbar = new St.BoxLayout({ name: 'Toolbar' });
|
|
||||||
this.actor.add_actor(toolbar);
|
this.actor.add_actor(toolbar);
|
||||||
let inspectIcon = St.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
|
let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
|
||||||
24);
|
24);
|
||||||
toolbar.add_actor(inspectIcon);
|
toolbar.add_actor(inspectIcon);
|
||||||
inspectIcon.reactive = true;
|
inspectIcon.reactive = true;
|
||||||
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
|
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
|
||||||
@ -601,6 +325,7 @@ LookingGlass.prototype = {
|
|||||||
inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
|
inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
|
||||||
this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
|
this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
|
||||||
target);
|
target);
|
||||||
|
this._hierarchy.setTarget(target);
|
||||||
}));
|
}));
|
||||||
inspector.connect('closed', Lang.bind(this, function() {
|
inspector.connect('closed', Lang.bind(this, function() {
|
||||||
this.actor.show();
|
this.actor.show();
|
||||||
@ -611,24 +336,24 @@ LookingGlass.prototype = {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
let notebook = new Notebook();
|
let notebook = new Notebook();
|
||||||
this._notebook = notebook;
|
|
||||||
this.actor.add(notebook.actor, { expand: true });
|
this.actor.add(notebook.actor, { expand: true });
|
||||||
|
|
||||||
let emptyBox = new St.Bin();
|
let emptyBox = new St.Bin();
|
||||||
toolbar.add(emptyBox, { expand: true });
|
toolbar.add(emptyBox, { expand: true });
|
||||||
toolbar.add_actor(notebook.tabControls);
|
toolbar.add_actor(notebook.tabControls);
|
||||||
|
|
||||||
this._evalBox = new St.BoxLayout({ name: 'EvalBox', vertical: true });
|
this._evalBox = new St.BoxLayout({ name: "EvalBox", vertical: true });
|
||||||
notebook.appendPage('Evaluator', this._evalBox);
|
notebook.appendPage('Evaluator', this._evalBox);
|
||||||
|
|
||||||
this._resultsArea = new St.BoxLayout({ name: 'ResultsArea', vertical: true });
|
this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
spacing: 4 });
|
||||||
this._evalBox.add(this._resultsArea, { expand: true });
|
this._evalBox.add(this._resultsArea, { expand: true });
|
||||||
|
|
||||||
let entryArea = new St.BoxLayout({ name: 'EntryArea' });
|
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
this._evalBox.add_actor(entryArea);
|
this._evalBox.add_actor(entryArea);
|
||||||
|
|
||||||
let label = new St.Label({ text: 'js>>> ' });
|
let label = new St.Label({ text: 'js>>> ' });
|
||||||
entryArea.add(label);
|
entryArea.append(label, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this._entry = new St.Entry();
|
this._entry = new St.Entry();
|
||||||
/* unmapping the edit box will un-focus it, undo that */
|
/* unmapping the edit box will un-focus it, undo that */
|
||||||
@ -636,20 +361,17 @@ LookingGlass.prototype = {
|
|||||||
if (child == this._evalBox)
|
if (child == this._evalBox)
|
||||||
global.stage.set_key_focus(this._entry);
|
global.stage.set_key_focus(this._entry);
|
||||||
}));
|
}));
|
||||||
entryArea.add(this._entry, { expand: true });
|
entryArea.append(this._entry, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._windowList = new WindowList();
|
this._hierarchy = new ActorHierarchy();
|
||||||
this._windowList.connect('selected', Lang.bind(this, function(list, window) {
|
notebook.appendPage('Hierarchy', this._hierarchy.actor);
|
||||||
|
|
||||||
|
this._propInspector = new PropertyInspector();
|
||||||
|
notebook.appendPage('Properties', this._propInspector.actor);
|
||||||
|
this._hierarchy.connect('selection', Lang.bind(this, function (h, actor) {
|
||||||
|
this._pushResult('<parent selection>', actor);
|
||||||
notebook.selectIndex(0);
|
notebook.selectIndex(0);
|
||||||
this._pushResult('<window selection>', window);
|
|
||||||
}));
|
}));
|
||||||
notebook.appendPage('Windows', this._windowList.actor);
|
|
||||||
|
|
||||||
this._errorLog = new ErrorLog();
|
|
||||||
notebook.appendPage('Errors', this._errorLog.actor);
|
|
||||||
|
|
||||||
this._extensions = new Extensions();
|
|
||||||
notebook.appendPage('Extensions', this._extensions.actor);
|
|
||||||
|
|
||||||
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
|
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
|
||||||
let text = o.get_text();
|
let text = o.get_text();
|
||||||
@ -657,7 +379,7 @@ LookingGlass.prototype = {
|
|||||||
// newline-separated.
|
// newline-separated.
|
||||||
text.replace('\n', ' ');
|
text.replace('\n', ' ');
|
||||||
// Strip leading and trailing whitespace
|
// Strip leading and trailing whitespace
|
||||||
text = text.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
||||||
if (text == '')
|
if (text == '')
|
||||||
return true;
|
return true;
|
||||||
this._evaluate(text);
|
this._evaluate(text);
|
||||||
@ -666,7 +388,10 @@ LookingGlass.prototype = {
|
|||||||
}));
|
}));
|
||||||
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
|
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||||
let symbol = e.get_key_symbol();
|
let symbol = e.get_key_symbol();
|
||||||
if (symbol == Clutter.Up) {
|
if (symbol == Clutter.Escape) {
|
||||||
|
this.close();
|
||||||
|
return true;
|
||||||
|
} else if (symbol == Clutter.Up) {
|
||||||
if (this._historyNavIndex >= this._history.length - 1)
|
if (this._historyNavIndex >= this._history.length - 1)
|
||||||
return true;
|
return true;
|
||||||
this._historyNavIndex++;
|
this._historyNavIndex++;
|
||||||
@ -693,7 +418,7 @@ LookingGlass.prototype = {
|
|||||||
|
|
||||||
_updateFont: function() {
|
_updateFont: function() {
|
||||||
let gconf = Shell.GConf.get_default();
|
let gconf = Shell.GConf.get_default();
|
||||||
let fontName = gconf.get_string('/desktop/gnome/interface/monospace_font_name');
|
let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name");
|
||||||
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
|
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
|
||||||
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
|
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
|
||||||
let fontDesc = Pango.Font.description_from_string(fontName);
|
let fontDesc = Pango.Font.description_from_string(fontName);
|
||||||
@ -731,19 +456,8 @@ LookingGlass.prototype = {
|
|||||||
let index = this._results.length + this._offset;
|
let index = this._results.length + this._offset;
|
||||||
let result = new Result('>>> ' + command, obj, index);
|
let result = new Result('>>> ' + command, obj, index);
|
||||||
this._results.push(result);
|
this._results.push(result);
|
||||||
this._resultsArea.add(result.actor);
|
this._resultsArea.append(result.actor, Big.BoxPackFlags.NONE);
|
||||||
if (this._borderPaintTarget != null) {
|
this._propInspector.setTarget(obj);
|
||||||
this._borderPaintTarget.disconnect(this._borderPaintId);
|
|
||||||
this._borderPaintTarget = null;
|
|
||||||
}
|
|
||||||
if (obj instanceof Clutter.Actor) {
|
|
||||||
this._borderPaintTarget = obj;
|
|
||||||
this._borderPaintId = Shell.add_hook_paint_red_border(obj);
|
|
||||||
this._borderDestroyId = obj.connect('destroy', Lang.bind(this, function () {
|
|
||||||
this._borderDestroyId = 0;
|
|
||||||
this._borderPaintTarget = null;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
let children = this._resultsArea.get_children();
|
let children = this._resultsArea.get_children();
|
||||||
if (children.length > this._maxItems) {
|
if (children.length > this._maxItems) {
|
||||||
this._results.shift();
|
this._results.shift();
|
||||||
@ -751,9 +465,6 @@ LookingGlass.prototype = {
|
|||||||
this._offset++;
|
this._offset++;
|
||||||
}
|
}
|
||||||
this._it = obj;
|
this._it = obj;
|
||||||
|
|
||||||
// Scroll to bottom
|
|
||||||
this._notebook.scrollToBottom(0);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_evaluate : function(command) {
|
_evaluate : function(command) {
|
||||||
@ -766,10 +477,11 @@ LookingGlass.prototype = {
|
|||||||
try {
|
try {
|
||||||
resultObj = eval(fullCmd);
|
resultObj = eval(fullCmd);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
resultObj = '<exception ' + e + '>';
|
resultObj = "<exception " + e + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
this._pushResult(command, resultObj);
|
this._pushResult(command, resultObj);
|
||||||
|
this._hierarchy.setTarget(null);
|
||||||
this._entry.text = '';
|
this._entry.text = '';
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -789,19 +501,16 @@ LookingGlass.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_resizeTo: function(actor) {
|
_resizeTo: function(actor) {
|
||||||
let primary = global.get_primary_monitor();
|
let stage = global.stage;
|
||||||
let myWidth = primary.width * 0.7;
|
let myWidth = stage.width * 0.7;
|
||||||
let myHeight = primary.height * 0.7;
|
let myHeight = stage.height * 0.7;
|
||||||
let [srcX, srcY] = actor.get_transformed_position();
|
let [srcX, srcY] = actor.get_transformed_position();
|
||||||
this.actor.x = srcX + (primary.width - myWidth) / 2;
|
this.actor.x = srcX + (stage.width-myWidth)/2;
|
||||||
this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners
|
this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners
|
||||||
this._targetY = this._hiddenY + myHeight;
|
this._targetY = this._hiddenY + myHeight;
|
||||||
this.actor.y = this._hiddenY;
|
this.actor.y = this._hiddenY;
|
||||||
this.actor.width = myWidth;
|
this.actor.width = myWidth;
|
||||||
this.actor.height = myHeight;
|
this.actor.height = myHeight;
|
||||||
this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
|
|
||||||
this._objInspector.actor.set_position(this.actor.x + Math.floor(myWidth * 0.1),
|
|
||||||
this._targetY + Math.floor(myHeight * 0.1));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
slaveTo: function(actor) {
|
slaveTo: function(actor) {
|
||||||
@ -812,29 +521,6 @@ LookingGlass.prototype = {
|
|||||||
this._resizeTo(actor);
|
this._resizeTo(actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
insertObject: function(obj) {
|
|
||||||
this._pushResult('<insert>', obj);
|
|
||||||
},
|
|
||||||
|
|
||||||
inspectObject: function(obj, sourceActor) {
|
|
||||||
this._objInspector.open(sourceActor);
|
|
||||||
this._objInspector.selectObject(obj);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Handle key events which are relevant for all tabs of the LookingGlass
|
|
||||||
_globalKeyPressEvent : function(actor, event) {
|
|
||||||
let symbol = event.get_key_symbol();
|
|
||||||
if (symbol == Clutter.Escape) {
|
|
||||||
if (this._objInspector.actor.visible) {
|
|
||||||
this._objInspector.close();
|
|
||||||
} else {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
open : function() {
|
open : function() {
|
||||||
if (this._open)
|
if (this._open)
|
||||||
return;
|
return;
|
||||||
@ -842,9 +528,6 @@ LookingGlass.prototype = {
|
|||||||
if (!Main.pushModal(this.actor))
|
if (!Main.pushModal(this.actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._keyPressEventId = global.stage.connect('key-press-event',
|
|
||||||
Lang.bind(this, this._globalKeyPressEvent));
|
|
||||||
|
|
||||||
this.actor.show();
|
this.actor.show();
|
||||||
this.actor.lower(Main.chrome.actor);
|
this.actor.lower(Main.chrome.actor);
|
||||||
this._open = true;
|
this._open = true;
|
||||||
@ -854,7 +537,7 @@ LookingGlass.prototype = {
|
|||||||
global.stage.set_key_focus(this._entry);
|
global.stage.set_key_focus(this._entry);
|
||||||
|
|
||||||
Tweener.addTween(this.actor, { time: 0.5,
|
Tweener.addTween(this.actor, { time: 0.5,
|
||||||
transition: 'easeOutQuad',
|
transition: "easeOutQuad",
|
||||||
y: this._targetY
|
y: this._targetY
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -863,25 +546,14 @@ LookingGlass.prototype = {
|
|||||||
if (!this._open)
|
if (!this._open)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._keyPressEventId)
|
|
||||||
global.stage.disconnect(this._keyPressEventId);
|
|
||||||
|
|
||||||
this._objInspector.actor.hide();
|
|
||||||
|
|
||||||
this._historyNavIndex = -1;
|
this._historyNavIndex = -1;
|
||||||
this._open = false;
|
this._open = false;
|
||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
|
|
||||||
if (this._borderPaintTarget != null) {
|
|
||||||
this._borderPaintTarget.disconnect(this._borderPaintId);
|
|
||||||
this._borderPaintTarget.disconnect(this._borderDestroyId);
|
|
||||||
this._borderPaintTarget = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Main.popModal(this.actor);
|
Main.popModal(this.actor);
|
||||||
|
|
||||||
Tweener.addTween(this.actor, { time: 0.5,
|
Tweener.addTween(this.actor, { time: 0.5,
|
||||||
transition: 'easeOutQuad',
|
transition: "easeOutQuad",
|
||||||
y: this._hiddenY,
|
y: this._hiddenY,
|
||||||
onComplete: Lang.bind(this, function () {
|
onComplete: Lang.bind(this, function () {
|
||||||
this.actor.hide();
|
this.actor.hide();
|
||||||
|
1479
js/ui/magnifier.js
@ -1,375 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
|
|
||||||
const MAG_SERVICE_PATH = '/org/gnome/Magnifier';
|
|
||||||
const ZOOM_SERVICE_NAME = 'org.gnome.Magnifier.ZoomRegion';
|
|
||||||
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 = {
|
|
||||||
name: MAG_SERVICE_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'setActive', inSignature: 'b', outSignature: '' },
|
|
||||||
{ name: 'isActive', inSignature: '', outSignature: 'b' },
|
|
||||||
{ name: 'showCursor', inSignature: '', outSignature: '' },
|
|
||||||
{ name: 'hideCursor', inSignature: '', outSignature: '' },
|
|
||||||
{ name: 'createZoomRegion', inSignature: 'ddaiai', outSignature: 'o' },
|
|
||||||
{ name: 'addZoomRegion', inSignature: 'o', outSignature: 'b' },
|
|
||||||
{ name: 'getZoomRegions', inSignature: '', outSignature: 'ao' },
|
|
||||||
{ name: 'clearAllZoomRegions', inSignature: '', outSignature: '' },
|
|
||||||
{ name: 'fullScreenCapable', inSignature: '', outSignature: 'b' },
|
|
||||||
|
|
||||||
{ name: 'setCrosswireSize', inSignature: 'i', outSignature: '' },
|
|
||||||
{ name: 'getCrosswireSize', inSignature: '', outSignature: 'i' },
|
|
||||||
{ name: 'setCrosswireLength', inSignature: 'i', outSignature: '' },
|
|
||||||
{ name: 'getCrosswireLength', inSignature: '', outSignature: 'i' },
|
|
||||||
{ name: 'setCrosswireClip', inSignature: 'b', outSignature: '' },
|
|
||||||
{ name: 'getCrosswireClip', inSignature: '', outSignature: 'b' },
|
|
||||||
{ name: 'setCrosswireColor', inSignature: 'u', outSignature: '' },
|
|
||||||
{ name: 'getCrosswireColor', inSignature: '', outSignature: 'u' }
|
|
||||||
],
|
|
||||||
signals: [],
|
|
||||||
properties: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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 = {
|
|
||||||
name: ZOOM_SERVICE_NAME,
|
|
||||||
methods: [
|
|
||||||
{ name: 'setMagFactor', inSignature: 'dd', outSignature: ''},
|
|
||||||
{ name: 'getMagFactor', inSignature: '', outSignature: 'dd' },
|
|
||||||
{ name: 'setRoi', inSignature: 'ai', outSignature: '' },
|
|
||||||
{ name: 'getRoi', inSignature: '', outSignature: 'ai' },
|
|
||||||
{ name: 'shiftContentsTo', inSignature: 'ii', outSignature: 'b' },
|
|
||||||
{ name: 'moveResize', inSignature: 'ai', outSignature: '' }
|
|
||||||
],
|
|
||||||
signals: [],
|
|
||||||
properties: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// For making unique ZoomRegion DBus proxy object paths of the form:
|
|
||||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',
|
|
||||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
|
|
||||||
let _zoomRegionInstanceCount = 0;
|
|
||||||
|
|
||||||
function ShellMagnifier() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellMagnifier.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this._zoomers = {};
|
|
||||||
DBus.session.exportObject(MAG_SERVICE_PATH, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setActive:
|
|
||||||
* @activate: Boolean to activate or de-activate the magnifier.
|
|
||||||
*/
|
|
||||||
setActive: function(activate) {
|
|
||||||
Main.magnifier.setActive(activate);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isActive:
|
|
||||||
* @return Whether the magnifier is active (boolean).
|
|
||||||
*/
|
|
||||||
isActive: function() {
|
|
||||||
return Main.magnifier.isActive();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* showCursor:
|
|
||||||
* Show the system mouse pointer.
|
|
||||||
*/
|
|
||||||
showCursor: function() {
|
|
||||||
Main.magnifier.showSystemCursor();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* hideCursor:
|
|
||||||
* Hide the system mouse pointer.
|
|
||||||
*/
|
|
||||||
hideCursor: function() {
|
|
||||||
Main.magnifier.hideSystemCursor();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* createZoomRegion:
|
|
||||||
* Create a new ZoomRegion and return its object path.
|
|
||||||
* @xMagFactor: The power to set horizontal magnification of the
|
|
||||||
* ZoomRegion. A value of 1.0 means no magnification. A
|
|
||||||
* value of 2.0 doubles the size.
|
|
||||||
* @yMagFactor: The power to set the vertical magnification of the
|
|
||||||
* ZoomRegion.
|
|
||||||
* @roi Array of integers defining the region of the
|
|
||||||
* screen/desktop to magnify. The array has the form
|
|
||||||
* [x, y, width, height].
|
|
||||||
* @viewPort Array of integers, [ x, y, width, height ] that defines
|
|
||||||
* the position of the ZoomRegion on screen.
|
|
||||||
* @return The newly created ZoomRegion.
|
|
||||||
*/
|
|
||||||
createZoomRegion: function(xMagFactor, yMagFactor, roi, viewPort) {
|
|
||||||
let ROI = { x: roi[0], y: roi[1], width: roi[2], height: roi[3] };
|
|
||||||
let viewBox = { x: viewPort[0], y: viewPort[1], width: viewPort[2], height: viewPort[3] };
|
|
||||||
let realZoomRegion = Main.magnifier.createZoomRegion(xMagFactor, yMagFactor, ROI, viewBox);
|
|
||||||
let objectPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
|
|
||||||
_zoomRegionInstanceCount++;
|
|
||||||
|
|
||||||
let zoomRegionProxy = new ShellMagnifierZoomRegion(objectPath, realZoomRegion);
|
|
||||||
let proxyAndZoomRegion = {};
|
|
||||||
proxyAndZoomRegion.proxy = zoomRegionProxy;
|
|
||||||
proxyAndZoomRegion.zoomRegion = realZoomRegion;
|
|
||||||
this._zoomers[objectPath] = proxyAndZoomRegion;
|
|
||||||
return objectPath;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* addZoomRegion:
|
|
||||||
* Append the given ZoomRegion to the magnifier's list of ZoomRegions.
|
|
||||||
* @zoomerObjectPath: The object path for the zoom region proxy.
|
|
||||||
*/
|
|
||||||
addZoomRegion: function(zoomerObjectPath) {
|
|
||||||
let proxyAndZoomRegion = this._zoomers[zoomerObjectPath];
|
|
||||||
if (proxyAndZoomRegion && proxyAndZoomRegion.zoomRegion) {
|
|
||||||
Main.magnifier.addZoomRegion(proxyAndZoomRegion.zoomRegion);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getZoomRegions:
|
|
||||||
* Return a list of ZoomRegion object paths for this Magnifier.
|
|
||||||
* @return: The Magnifier's zoom region list as an array of DBus object
|
|
||||||
* paths.
|
|
||||||
*/
|
|
||||||
getZoomRegions: function() {
|
|
||||||
// There may be more ZoomRegions in the magnifier itself than have
|
|
||||||
// been added through dbus. Make sure all of them are associated with
|
|
||||||
// an object path and proxy.
|
|
||||||
let zoomRegions = Main.magnifier.getZoomRegions();
|
|
||||||
let objectPaths = [];
|
|
||||||
let thoseZoomers = this._zoomers;
|
|
||||||
zoomRegions.forEach (function(aZoomRegion, index, array) {
|
|
||||||
let found = false;
|
|
||||||
for (let objectPath in thoseZoomers) {
|
|
||||||
let proxyAndZoomRegion = thoseZoomers[objectPath];
|
|
||||||
if (proxyAndZoomRegion.zoomRegion === aZoomRegion) {
|
|
||||||
objectPaths.push(objectPath);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
// Got a ZoomRegion with no DBus proxy, make one.
|
|
||||||
let newPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
|
|
||||||
_zoomRegionInstanceCount++;
|
|
||||||
let zoomRegionProxy = new ShellMagnifierZoomRegion(newPath, aZoomRegion);
|
|
||||||
let proxyAndZoomer = {};
|
|
||||||
proxyAndZoomer.proxy = zoomRegionProxy;
|
|
||||||
proxyAndZoomer.zoomRegion = aZoomRegion;
|
|
||||||
thoseZoomers[newPath] = proxyAndZoomer;
|
|
||||||
objectPaths.push(newPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return objectPaths;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clearAllZoomRegions:
|
|
||||||
* Remove all the zoom regions from this Magnfier's ZoomRegion list.
|
|
||||||
*/
|
|
||||||
clearAllZoomRegions: function() {
|
|
||||||
Main.magnifier.clearAllZoomRegions();
|
|
||||||
for (let objectPath in this._zoomers) {
|
|
||||||
let proxyAndZoomer = this._zoomers[objectPath];
|
|
||||||
proxyAndZoomer.proxy = null;
|
|
||||||
proxyAndZoomer.zoomRegion = null;
|
|
||||||
delete this._zoomers[objectPath];
|
|
||||||
DBus.session.unexportObject(proxyAndZoomer);
|
|
||||||
}
|
|
||||||
this._zoomers = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fullScreenCapable:
|
|
||||||
* Consult if the Magnifier can magnify in full-screen mode.
|
|
||||||
* @return Always return true.
|
|
||||||
*/
|
|
||||||
fullScreenCapable: function() {
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setCrosswireSize:
|
|
||||||
* Set the crosswire size of all ZoomRegions.
|
|
||||||
* @size: The thickness of each line in the cross wire.
|
|
||||||
*/
|
|
||||||
setCrosswireSize: function(size) {
|
|
||||||
Main.magnifier.setCrosshairsThickness(size);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getCrosswireSize:
|
|
||||||
* Get the crosswire size of all ZoomRegions.
|
|
||||||
* @return: The thickness of each line in the cross wire.
|
|
||||||
*/
|
|
||||||
getCrosswireSize: function() {
|
|
||||||
return Main.magnifier.getCrosshairsThickness();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setCrosswireLength:
|
|
||||||
* Set the crosswire length of all zoom-regions..
|
|
||||||
* @size: The length of each line in the cross wire.
|
|
||||||
*/
|
|
||||||
setCrosswireLength: function(length) {
|
|
||||||
Main.magnifier.setCrosshairsLength(length);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setCrosswireSize:
|
|
||||||
* Set the crosswire size of all zoom-regions.
|
|
||||||
* @size: The thickness of each line in the cross wire.
|
|
||||||
*/
|
|
||||||
getCrosswireLength: function() {
|
|
||||||
return Main.magnifier.getCrosshairsLength();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setCrosswireClip:
|
|
||||||
* Set if the crosswire will be clipped by the cursor image..
|
|
||||||
* @clip: Flag to indicate whether to clip the crosswire.
|
|
||||||
*/
|
|
||||||
setCrosswireClip: function(clip) {
|
|
||||||
Main.magnifier.setCrosshairsClip(clip);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getCrosswireClip:
|
|
||||||
* Get the crosswire clip value.
|
|
||||||
* @return: Whether the crosswire is clipped by the cursor image.
|
|
||||||
*/
|
|
||||||
getCrosswireClip: function() {
|
|
||||||
return Main.magnifier.getCrosshairsClip();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setCrosswireColor:
|
|
||||||
* Set the crosswire color of all ZoomRegions.
|
|
||||||
* @color: Unsigned int of the form rrggbbaa.
|
|
||||||
*/
|
|
||||||
setCrosswireColor: function(color) {
|
|
||||||
Main.magnifier.setCrosshairsColor('#' + color.toString(16));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getCrosswireClip:
|
|
||||||
* Get the crosswire color of all ZoomRegions.
|
|
||||||
* @return: The crosswire color as an unsigned int in the form rrggbbaa.
|
|
||||||
*/
|
|
||||||
getCrosswireColor: function() {
|
|
||||||
let colorString = Main.magnifier.getCrosshairsColor();
|
|
||||||
// Drop the leading '#'.
|
|
||||||
return parseInt(colorString.slice(1), 16);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ShellMagnifierZoomRegion:
|
|
||||||
* Object that implements the DBus ZoomRegion interface.
|
|
||||||
* @zoomerObjectPath: String that is the path to a DBus ZoomRegion.
|
|
||||||
* @zoomRegion: The actual zoom region associated with the object path.
|
|
||||||
*/
|
|
||||||
function ShellMagnifierZoomRegion(zoomerObjectPath, zoomRegion) {
|
|
||||||
this._init(zoomerObjectPath, zoomRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellMagnifierZoomRegion.prototype = {
|
|
||||||
_init: function(zoomerObjectPath, zoomRegion) {
|
|
||||||
this._zoomRegion = zoomRegion;
|
|
||||||
DBus.session.proxifyObject(this, ZOOM_SERVICE_NAME, zoomerObjectPath);
|
|
||||||
DBus.session.exportObject(zoomerObjectPath, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setMagFactor:
|
|
||||||
* @xMagFactor: The power to set the horizontal magnification factor to
|
|
||||||
* of the magnified view. A value of 1.0 means no
|
|
||||||
* magnification. A value of 2.0 doubles the size.
|
|
||||||
* @yMagFactor: The power to set the vertical magnification factor to
|
|
||||||
* of the magnified view.
|
|
||||||
*/
|
|
||||||
setMagFactor: function(xMagFactor, yMagFactor) {
|
|
||||||
this._zoomRegion.setMagFactor(xMagFactor, yMagFactor);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getMagFactor:
|
|
||||||
* @return an array, [xMagFactor, yMagFactor], containing the horizontal
|
|
||||||
* and vertical magnification powers. A value of 1.0 means no
|
|
||||||
* magnification. A value of 2.0 means the contents are doubled
|
|
||||||
* in size, and so on.
|
|
||||||
*/
|
|
||||||
getMagFactor: function() {
|
|
||||||
return this._zoomRegion.getMagFactor();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setRoi:
|
|
||||||
* Sets the "region of interest" that the ZoomRegion is magnifying.
|
|
||||||
* @roi Array, [x, y, width, height], defining the region of the screen to
|
|
||||||
* magnify. The values are in screen (unmagnified) coordinate
|
|
||||||
* space.
|
|
||||||
*/
|
|
||||||
setRoi: function(roi) {
|
|
||||||
let roiObject = { x: roi[0], y: roi[1], width: roi[2], height: roi[3] };
|
|
||||||
this._zoomRegion.setROI(roiObject);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getRoi:
|
|
||||||
* Retrieves the "region of interest" -- the rectangular bounds of that part
|
|
||||||
* of the desktop that the magnified view is showing (x, y, width, height).
|
|
||||||
* The bounds are given in non-magnified coordinates.
|
|
||||||
* @return an array, [x, y, width, height], representing the bounding
|
|
||||||
* rectangle of what is shown in the magnified view.
|
|
||||||
*/
|
|
||||||
getRoi: function() {
|
|
||||||
return this._zoomRegion.getROI();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the "region of interest" by centering the given screen coordinate
|
|
||||||
* within the zoom region.
|
|
||||||
* @x The x-coord of the point to place at the center of the zoom region.
|
|
||||||
* @y The y-coord.
|
|
||||||
* @return Whether the shift was successful (for GS-mag, this is always
|
|
||||||
* true).
|
|
||||||
*/
|
|
||||||
shiftContentsTo: function(x, y) {
|
|
||||||
this._zoomRegion.scrollContentsTo(x, y);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* moveResize
|
|
||||||
* Sets the position and size of the ZoomRegion on screen.
|
|
||||||
* @viewPort Array, [x, y, width, height], defining the position and size
|
|
||||||
* on screen to place the zoom region.
|
|
||||||
*/
|
|
||||||
moveResize: function(viewPort) {
|
|
||||||
let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2], height: viewPort[3] };
|
|
||||||
this._zoomRegion.setViewPort(viewRect);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.conformExport(ShellMagnifier.prototype, MagnifierIface);
|
|
||||||
DBus.conformExport(ShellMagnifierZoomRegion.prototype, ZoomRegionIface);
|
|
372
js/ui/main.js
@ -1,11 +1,5 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
imports.gi.versions.Clutter = '1.0';
|
|
||||||
imports.gi.versions.Gio = '2.0';
|
|
||||||
imports.gi.versions.Gdk = '2.0';
|
|
||||||
imports.gi.versions.GdkPixbuf = '2.0';
|
|
||||||
imports.gi.versions.Gtk = '2.0';
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const DBus = imports.dbus;
|
const DBus = imports.dbus;
|
||||||
const Gdk = imports.gi.Gdk;
|
const Gdk = imports.gi.Gdk;
|
||||||
@ -20,59 +14,36 @@ const St = imports.gi.St;
|
|||||||
|
|
||||||
const Chrome = imports.ui.chrome;
|
const Chrome = imports.ui.chrome;
|
||||||
const Environment = imports.ui.environment;
|
const Environment = imports.ui.environment;
|
||||||
const ExtensionSystem = imports.ui.extensionSystem;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const PlaceDisplay = imports.ui.placeDisplay;
|
|
||||||
const RunDialog = imports.ui.runDialog;
|
const RunDialog = imports.ui.runDialog;
|
||||||
const LookingGlass = imports.ui.lookingGlass;
|
const LookingGlass = imports.ui.lookingGlass;
|
||||||
const NotificationDaemon = imports.ui.notificationDaemon;
|
|
||||||
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
|
|
||||||
const Scripting = imports.ui.scripting;
|
|
||||||
const ShellDBus = imports.ui.shellDBus;
|
const ShellDBus = imports.ui.shellDBus;
|
||||||
const TelepathyClient = imports.ui.telepathyClient;
|
const Sidebar = imports.ui.sidebar;
|
||||||
const WindowManager = imports.ui.windowManager;
|
const WindowManager = imports.ui.windowManager;
|
||||||
const Magnifier = imports.ui.magnifier;
|
|
||||||
|
|
||||||
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
|
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
|
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
|
||||||
|
|
||||||
let chrome = null;
|
let chrome = null;
|
||||||
let panel = null;
|
let panel = null;
|
||||||
let placesManager = null;
|
let sidebar = null;
|
||||||
let overview = null;
|
let overview = null;
|
||||||
let runDialog = null;
|
let runDialog = null;
|
||||||
let lookingGlass = null;
|
let lookingGlass = null;
|
||||||
let wm = null;
|
let wm = null;
|
||||||
let messageTray = null;
|
|
||||||
let notificationDaemon = null;
|
|
||||||
let windowAttentionHandler = null;
|
|
||||||
let telepathyClient = null;
|
|
||||||
let recorder = null;
|
let recorder = null;
|
||||||
let shellDBusService = null;
|
let shellDBusService = null;
|
||||||
let modalCount = 0;
|
let modalCount = 0;
|
||||||
let modalActorFocusStack = [];
|
let modalActorFocusStack = [];
|
||||||
let uiGroup = null;
|
|
||||||
let magnifier = null;
|
|
||||||
let _errorLogStack = [];
|
|
||||||
let _startDate;
|
|
||||||
|
|
||||||
let background = null;
|
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
// Add a binding for 'global' in the global JS namespace; (gjs
|
// Add a binding for "global" in the global JS namespace; (gjs
|
||||||
// keeps the web browser convention of having that namespace be
|
// keeps the web browser convention of having that namespace be
|
||||||
// called 'window'.)
|
// called "window".)
|
||||||
window.global = Shell.Global.get();
|
window.global = Shell.Global.get();
|
||||||
|
|
||||||
// Now monkey patch utility functions into the global proxy;
|
Gio.DesktopAppInfo.set_desktop_env("GNOME");
|
||||||
// This is easier and faster than indirecting down into global
|
|
||||||
// if we want to call back up into JS.
|
|
||||||
global.logError = _logError;
|
|
||||||
global.log = _logDebug;
|
|
||||||
|
|
||||||
Gio.DesktopAppInfo.set_desktop_env('GNOME');
|
|
||||||
|
|
||||||
global.grab_dbus_service();
|
global.grab_dbus_service();
|
||||||
shellDBusService = new ShellDBus.GnomeShell();
|
shellDBusService = new ShellDBus.GnomeShell();
|
||||||
@ -84,54 +55,51 @@ function start() {
|
|||||||
|
|
||||||
Environment.init();
|
Environment.init();
|
||||||
|
|
||||||
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
|
// Ensure ShellAppMonitor is initialized; this will
|
||||||
// also initialize ShellAppSystem first. ShellAppSystem
|
// also initialize ShellAppSystem first. ShellAppSystem
|
||||||
// needs to load all the .desktop files, and ShellWindowTracker
|
// needs to load all the .desktop files, and ShellAppMonitor
|
||||||
// will use those to associate with windows. Right now
|
// will use those to associate with windows. Right now
|
||||||
// the Monitor doesn't listen for installed app changes
|
// the Monitor doesn't listen for installed app changes
|
||||||
// and recalculate application associations, so to avoid
|
// and recalculate application associations, so to avoid
|
||||||
// races for now we initialize it here. It's better to
|
// races for now we initialize it here. It's better to
|
||||||
// be predictable anyways.
|
// be predictable anyways.
|
||||||
Shell.WindowTracker.get_default();
|
Shell.AppMonitor.get_default();
|
||||||
Shell.AppUsage.get_default();
|
|
||||||
|
|
||||||
// The background color really only matters if there is no desktop
|
// The background color really only matters if there is no desktop
|
||||||
// window (say, nautilus) running. We set it mostly so things look good
|
// window (say, nautilus) running. We set it mostly so things look good
|
||||||
// when we are running inside Xephyr.
|
// when we are running inside Xephyr.
|
||||||
global.stage.color = DEFAULT_BACKGROUND_COLOR;
|
global.stage.color = DEFAULT_BACKGROUND_COLOR;
|
||||||
|
|
||||||
|
// Mutter currently hardcodes putting "Yessir. The compositor is running""
|
||||||
|
// in the Overview. Clear that out.
|
||||||
|
let children = global.overlay_group.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++)
|
||||||
|
children[i].destroy();
|
||||||
|
|
||||||
let themeContext = St.ThemeContext.get_for_stage (global.stage);
|
let themeContext = St.ThemeContext.get_for_stage (global.stage);
|
||||||
let stylesheetPath = global.datadir + '/theme/gnome-shell.css';
|
let stylesheetPath = global.datadir + "/theme/gnome-shell.css";
|
||||||
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
|
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
|
||||||
themeContext.set_theme (theme);
|
themeContext.set_theme (theme);
|
||||||
|
|
||||||
|
global.connect('panel-run-dialog', function(panel) {
|
||||||
|
// Make sure not more than one run dialog is shown.
|
||||||
|
getRunDialog().open();
|
||||||
|
});
|
||||||
let shellwm = global.window_manager;
|
let shellwm = global.window_manager;
|
||||||
shellwm.takeover_keybinding('panel_main_menu');
|
shellwm.takeover_keybinding("panel_main_menu");
|
||||||
shellwm.connect('keybinding::panel_main_menu', function () {
|
shellwm.connect("keybinding::panel_main_menu", function () {
|
||||||
overview.toggle();
|
overview.toggle();
|
||||||
});
|
});
|
||||||
shellwm.takeover_keybinding('panel_run_dialog');
|
shellwm.takeover_keybinding("panel_run_dialog");
|
||||||
shellwm.connect('keybinding::panel_run_dialog', function () {
|
shellwm.connect("keybinding::panel_run_dialog", function () {
|
||||||
getRunDialog().open();
|
getRunDialog().open();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set up stage hierarchy to group all UI actors under one container.
|
|
||||||
uiGroup = new Clutter.Group();
|
|
||||||
global.window_group.reparent(uiGroup);
|
|
||||||
global.overlay_group.reparent(uiGroup);
|
|
||||||
global.stage.add_actor(uiGroup);
|
|
||||||
|
|
||||||
placesManager = new PlaceDisplay.PlacesManager();
|
|
||||||
overview = new Overview.Overview();
|
overview = new Overview.Overview();
|
||||||
chrome = new Chrome.Chrome();
|
chrome = new Chrome.Chrome();
|
||||||
panel = new Panel.Panel();
|
panel = new Panel.Panel();
|
||||||
|
sidebar = new Sidebar.Sidebar();
|
||||||
wm = new WindowManager.WindowManager();
|
wm = new WindowManager.WindowManager();
|
||||||
messageTray = new MessageTray.MessageTray();
|
|
||||||
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
|
||||||
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
|
|
||||||
telepathyClient = new TelepathyClient.Client();
|
|
||||||
|
|
||||||
_startDate = new Date();
|
|
||||||
|
|
||||||
global.screen.connect('toggle-recording', function() {
|
global.screen.connect('toggle-recording', function() {
|
||||||
if (recorder == null) {
|
if (recorder == null) {
|
||||||
@ -141,110 +109,26 @@ function start() {
|
|||||||
if (recorder.is_recording()) {
|
if (recorder.is_recording()) {
|
||||||
recorder.pause();
|
recorder.pause();
|
||||||
} else {
|
} else {
|
||||||
//read the parameters from GConf always in case they have changed
|
|
||||||
let gconf = Shell.GConf.get_default();
|
|
||||||
recorder.set_framerate(gconf.get_int('recorder/framerate'));
|
|
||||||
recorder.set_filename('shell-%d%u-%c.' + gconf.get_string('recorder/file_extension'));
|
|
||||||
let pipeline = gconf.get_string('recorder/pipeline');
|
|
||||||
if (!pipeline.match(/^\s*$/))
|
|
||||||
recorder.set_pipeline(pipeline);
|
|
||||||
else
|
|
||||||
recorder.set_pipeline(null);
|
|
||||||
|
|
||||||
recorder.record();
|
recorder.record();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
background = global.create_root_pixmap_actor();
|
_relayout();
|
||||||
global.stage.add_actor(background);
|
|
||||||
background.lower_bottom();
|
|
||||||
|
|
||||||
global.connect('screen-size-changed', _relayout);
|
|
||||||
|
|
||||||
ExtensionSystem.init();
|
|
||||||
ExtensionSystem.loadExtensions();
|
|
||||||
|
|
||||||
panel.startupAnimation();
|
panel.startupAnimation();
|
||||||
|
|
||||||
let display = global.screen.get_display();
|
let display = global.screen.get_display();
|
||||||
display.connect('overlay-key', Lang.bind(overview, overview.toggle));
|
display.connect('overlay-key', Lang.bind(overview, overview.toggle));
|
||||||
|
global.connect('panel-main-menu', Lang.bind(overview, overview.toggle));
|
||||||
|
|
||||||
global.stage.connect('captured-event', _globalKeyPressHandler);
|
global.stage.connect('captured-event', _globalKeyPressHandler);
|
||||||
|
|
||||||
// Install magnifier.
|
|
||||||
magnifier = new Magnifier.Magnifier();
|
|
||||||
|
|
||||||
// Perform initial relayout here
|
|
||||||
_relayout();
|
|
||||||
|
|
||||||
_log('info', 'loaded at ' + _startDate);
|
|
||||||
log('GNOME Shell started at ' + _startDate);
|
|
||||||
|
|
||||||
Mainloop.idle_add(_removeUnusedWorkspaces);
|
Mainloop.idle_add(_removeUnusedWorkspaces);
|
||||||
|
|
||||||
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
|
|
||||||
if (perfModuleName) {
|
|
||||||
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
|
|
||||||
let module = eval('imports.perf.' + perfModuleName + ';');
|
|
||||||
Scripting.runPerfScript(module, perfOutput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* _log:
|
|
||||||
* @category: string message type ('info', 'error')
|
|
||||||
* @msg: A message string
|
|
||||||
* ...: Any further arguments are converted into JSON notation,
|
|
||||||
* and appended to the log message, separated by spaces.
|
|
||||||
*
|
|
||||||
* Log a message into the LookingGlass error
|
|
||||||
* stream. This is primarily intended for use by the
|
|
||||||
* extension system as well as debugging.
|
|
||||||
*/
|
|
||||||
function _log(category, msg) {
|
|
||||||
let text = msg;
|
|
||||||
if (arguments.length > 2) {
|
|
||||||
text += ': ';
|
|
||||||
for (let i = 2; i < arguments.length; i++) {
|
|
||||||
text += JSON.stringify(arguments[i]);
|
|
||||||
if (i < arguments.length - 1)
|
|
||||||
text += ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_errorLogStack.push({timestamp: new Date().getTime(),
|
|
||||||
category: category,
|
|
||||||
message: text });
|
|
||||||
}
|
|
||||||
|
|
||||||
function _logError(msg) {
|
|
||||||
return _log('error', msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _logDebug(msg) {
|
|
||||||
return _log('debug', msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by the error display in lookingGlass.js
|
|
||||||
function _getAndClearErrorStack() {
|
|
||||||
let errors = _errorLogStack;
|
|
||||||
_errorLogStack = [];
|
|
||||||
return errors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _relayout() {
|
function _relayout() {
|
||||||
let primary = global.get_primary_monitor();
|
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
|
||||||
panel.actor.set_position(primary.x, primary.y);
|
|
||||||
panel.actor.set_size(primary.width, Panel.PANEL_HEIGHT);
|
|
||||||
overview.relayout();
|
overview.relayout();
|
||||||
|
|
||||||
background.set_size(global.screen_width, global.screen_height);
|
|
||||||
|
|
||||||
// To avoid updating the position and size of the workspaces
|
|
||||||
// in the overview, we just hide the overview. The positions
|
|
||||||
// will be updated when it is next shown. We do the same for
|
|
||||||
// the calendar popdown.
|
|
||||||
overview.hide();
|
|
||||||
panel.hideCalendar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// metacity-clutter currently uses the same prefs as plain metacity,
|
// metacity-clutter currently uses the same prefs as plain metacity,
|
||||||
@ -297,8 +181,8 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
if (symbol == Clutter.Print) {
|
if (symbol == Clutter.Print) {
|
||||||
// We want to be able to take screenshots of the shell at all times
|
// We want to be able to take screenshots of the shell at all times
|
||||||
let gconf = Shell.GConf.get_default();
|
let gconf = Shell.GConf.get_default();
|
||||||
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
|
let command = gconf.get_string("/apps/metacity/keybinding_commands/command_screenshot");
|
||||||
if (command != null && command != '') {
|
if (command != null && command != "") {
|
||||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||||
let p = new Shell.Process({'args' : args});
|
let p = new Shell.Process({'args' : args});
|
||||||
p.run();
|
p.run();
|
||||||
@ -308,9 +192,6 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
}
|
}
|
||||||
} else if (type == Clutter.EventType.KEY_RELEASE) {
|
} else if (type == Clutter.EventType.KEY_RELEASE) {
|
||||||
let symbol = event.get_key_symbol();
|
let symbol = event.get_key_symbol();
|
||||||
let keyCode = event.get_key_code();
|
|
||||||
let modifierState = Shell.get_event_state(event);
|
|
||||||
// Check the overview key first, this isn't a Meta.KeyBindingAction yet
|
|
||||||
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
|
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
|
||||||
// The super key is the default for triggering the overview, and should
|
// The super key is the default for triggering the overview, and should
|
||||||
// get us out of the overview when we are already in it.
|
// get us out of the overview when we are already in it.
|
||||||
@ -318,25 +199,8 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
overview.hide();
|
overview.hide();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
|
||||||
|
getRunDialog().open();
|
||||||
// Whitelist some of the Metacity actions
|
|
||||||
let display = global.screen.get_display();
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
|
|
||||||
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
|
|
||||||
let action = display.get_keybinding_action(symbol, keyCode, modifierState);
|
|
||||||
switch (action) {
|
|
||||||
case Meta.KeyBindingAction.WORKSPACE_LEFT:
|
|
||||||
wm.actionMoveWorkspaceLeft();
|
|
||||||
return true;
|
|
||||||
case Meta.KeyBindingAction.WORKSPACE_RIGHT:
|
|
||||||
wm.actionMoveWorkspaceRight();
|
|
||||||
return true;
|
|
||||||
case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
|
|
||||||
case Meta.KeyBindingAction.COMMAND_2:
|
|
||||||
getRunDialog().open();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,8 +234,8 @@ function _findModal(actor) {
|
|||||||
*/
|
*/
|
||||||
function pushModal(actor) {
|
function pushModal(actor) {
|
||||||
if (modalCount == 0) {
|
if (modalCount == 0) {
|
||||||
if (!global.begin_modal(global.get_current_time())) {
|
if (!global.begin_modal(currentTime())) {
|
||||||
log('pushModal: invocation of begin_modal failed');
|
log("pushModal: invocation of begin_modal failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +287,7 @@ function popModal(actor) {
|
|||||||
if (modalCount > 0)
|
if (modalCount > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
global.end_modal(global.get_current_time());
|
global.end_modal(currentTime());
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,21 +306,58 @@ function getRunDialog() {
|
|||||||
return runDialog;
|
return runDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createAppLaunchContext() {
|
||||||
|
let context = new Gdk.AppLaunchContext();
|
||||||
|
context.set_timestamp(currentTime());
|
||||||
|
|
||||||
|
// Make sure that the app is opened on the current workspace even if
|
||||||
|
// the user switches before it starts
|
||||||
|
context.set_desktop(global.screen.get_active_workspace_index());
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* currentTime:
|
||||||
|
*
|
||||||
|
* Gets the current X server time from the current Clutter, Gdk, or X
|
||||||
|
* event. If called from outside an event handler, this may return
|
||||||
|
* %Clutter.CURRENT_TIME (aka 0), or it may return a slightly
|
||||||
|
* out-of-date timestamp.
|
||||||
|
*/
|
||||||
|
function currentTime() {
|
||||||
|
// meta_display_get_current_time() will return the correct time
|
||||||
|
// when handling an X or Gdk event, but will return CurrentTime
|
||||||
|
// from some Clutter event callbacks.
|
||||||
|
//
|
||||||
|
// clutter_get_current_event_time() will return the correct time
|
||||||
|
// from a Clutter event callback, but may return an out-of-date
|
||||||
|
// timestamp if called at other times.
|
||||||
|
//
|
||||||
|
// So we try meta_display_get_current_time() first, since we
|
||||||
|
// can recognize a "wrong" answer from that, and then fall back
|
||||||
|
// to clutter_get_current_event_time().
|
||||||
|
|
||||||
|
let time = global.screen.get_display().get_current_time();
|
||||||
|
if (time != Clutter.CURRENT_TIME)
|
||||||
|
return time;
|
||||||
|
|
||||||
|
return Clutter.get_current_event_time();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* activateWindow:
|
* activateWindow:
|
||||||
* @window: the Meta.Window to activate
|
* @window: the Meta.Window to activate
|
||||||
* @time: (optional) current event time
|
* @time: (optional) current event time
|
||||||
* @workspaceNum: (optional) window's workspace number
|
|
||||||
*
|
*
|
||||||
* Activates @window, switching to its workspace first if necessary,
|
* Activates @window, switching to its workspace first if necessary
|
||||||
* and switching out of the overview if it's currently active
|
|
||||||
*/
|
*/
|
||||||
function activateWindow(window, time, workspaceNum) {
|
function activateWindow(window, time) {
|
||||||
let activeWorkspaceNum = global.screen.get_active_workspace_index();
|
let activeWorkspaceNum = global.screen.get_active_workspace_index();
|
||||||
let windowWorkspaceNum = (workspaceNum !== undefined) ? workspaceNum : window.get_workspace().index();
|
let windowWorkspaceNum = window.get_workspace().index();
|
||||||
|
|
||||||
if (!time)
|
if (!time)
|
||||||
time = global.get_current_time();
|
time = currentTime();
|
||||||
|
|
||||||
if (windowWorkspaceNum != activeWorkspaceNum) {
|
if (windowWorkspaceNum != activeWorkspaceNum) {
|
||||||
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
|
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
|
||||||
@ -464,123 +365,4 @@ function activateWindow(window, time, workspaceNum) {
|
|||||||
} else {
|
} else {
|
||||||
window.activate(time);
|
window.activate(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
overview.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - replace this timeout with some system to guess when the user might
|
|
||||||
// be e.g. just reading the screen and not likely to interact.
|
|
||||||
const DEFERRED_TIMEOUT_SECONDS = 20;
|
|
||||||
var _deferredWorkData = {};
|
|
||||||
// Work scheduled for some point in the future
|
|
||||||
var _deferredWorkQueue = [];
|
|
||||||
// Work we need to process before the next redraw
|
|
||||||
var _beforeRedrawQueue = [];
|
|
||||||
// Counter to assign work ids
|
|
||||||
var _deferredWorkSequence = 0;
|
|
||||||
var _deferredTimeoutId = 0;
|
|
||||||
|
|
||||||
function _runDeferredWork(workId) {
|
|
||||||
if (!_deferredWorkData[workId])
|
|
||||||
return;
|
|
||||||
let index = _deferredWorkQueue.indexOf(workId);
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_deferredWorkQueue.splice(index, 1);
|
|
||||||
_deferredWorkData[workId].callback();
|
|
||||||
if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
|
|
||||||
Mainloop.source_remove(_deferredTimeoutId);
|
|
||||||
_deferredTimeoutId = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _runAllDeferredWork() {
|
|
||||||
while (_deferredWorkQueue.length > 0)
|
|
||||||
_runDeferredWork(_deferredWorkQueue[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _runBeforeRedrawQueue() {
|
|
||||||
for (let i = 0; i < _beforeRedrawQueue.length; i++) {
|
|
||||||
let workId = _beforeRedrawQueue[i];
|
|
||||||
_runDeferredWork(workId);
|
|
||||||
}
|
|
||||||
_beforeRedrawQueue = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function _queueBeforeRedraw(workId) {
|
|
||||||
_beforeRedrawQueue.push(workId);
|
|
||||||
if (_beforeRedrawQueue.length == 1) {
|
|
||||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function () {
|
|
||||||
_runBeforeRedrawQueue();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* initializeDeferredWork:
|
|
||||||
* @actor: A #ClutterActor
|
|
||||||
* @callback: Function to invoke to perform work
|
|
||||||
*
|
|
||||||
* This function sets up a callback to be invoked when either the
|
|
||||||
* given actor is mapped, or after some period of time when the machine
|
|
||||||
* is idle. This is useful if your actor isn't always visible on the
|
|
||||||
* screen (for example, all actors in the overview), and you don't want
|
|
||||||
* to consume resources updating if the actor isn't actually going to be
|
|
||||||
* displaying to the user.
|
|
||||||
*
|
|
||||||
* Note that queueDeferredWork is called by default immediately on
|
|
||||||
* initialization as well, under the assumption that new actors
|
|
||||||
* will need it.
|
|
||||||
*
|
|
||||||
* Returns: A string work identifer
|
|
||||||
*/
|
|
||||||
function initializeDeferredWork(actor, callback, props) {
|
|
||||||
// Turn into a string so we can use as an object property
|
|
||||||
let workId = '' + (++_deferredWorkSequence);
|
|
||||||
_deferredWorkData[workId] = { 'actor': actor,
|
|
||||||
'callback': callback };
|
|
||||||
actor.connect('notify::mapped', function () {
|
|
||||||
if (!(actor.mapped && _deferredWorkQueue.indexOf(workId) >= 0))
|
|
||||||
return;
|
|
||||||
_queueBeforeRedraw(workId);
|
|
||||||
});
|
|
||||||
actor.connect('destroy', function() {
|
|
||||||
let index = _deferredWorkQueue.indexOf(workId);
|
|
||||||
if (index >= 0)
|
|
||||||
_deferredWorkQueue.splice(index, 1);
|
|
||||||
delete _deferredWorkData[workId];
|
|
||||||
});
|
|
||||||
queueDeferredWork(workId);
|
|
||||||
return workId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* queueDeferredWork:
|
|
||||||
* @workId: work identifier
|
|
||||||
*
|
|
||||||
* Ensure that the work identified by @workId will be
|
|
||||||
* run on map or timeout. You should call this function
|
|
||||||
* for example when data being displayed by the actor has
|
|
||||||
* changed.
|
|
||||||
*/
|
|
||||||
function queueDeferredWork(workId) {
|
|
||||||
let data = _deferredWorkData[workId];
|
|
||||||
if (!data) {
|
|
||||||
global.logError('invalid work id ', workId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_deferredWorkQueue.indexOf(workId) < 0)
|
|
||||||
_deferredWorkQueue.push(workId);
|
|
||||||
if (data.actor.mapped) {
|
|
||||||
_queueBeforeRedraw(workId);
|
|
||||||
return;
|
|
||||||
} else if (_deferredTimeoutId == 0) {
|
|
||||||
_deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, function () {
|
|
||||||
_runAllDeferredWork();
|
|
||||||
_deferredTimeoutId = 0;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,987 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const ANIMATION_TIME = 0.2;
|
|
||||||
const NOTIFICATION_TIMEOUT = 4;
|
|
||||||
const SUMMARY_TIMEOUT = 1;
|
|
||||||
|
|
||||||
const HIDE_TIMEOUT = 0.2;
|
|
||||||
|
|
||||||
const ICON_SIZE = 24;
|
|
||||||
|
|
||||||
const State = {
|
|
||||||
HIDDEN: 0,
|
|
||||||
SHOWING: 1,
|
|
||||||
SHOWN: 2,
|
|
||||||
HIDING: 3
|
|
||||||
};
|
|
||||||
|
|
||||||
function _cleanMarkup(text) {
|
|
||||||
// Support &, ", ', < and >, escape all other
|
|
||||||
// occurrences of '&'.
|
|
||||||
let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&');
|
|
||||||
// Support <b>, <i>, and <u>, escape anything else
|
|
||||||
// so it displays as raw markup.
|
|
||||||
return _text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, '<$1');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notification:
|
|
||||||
// @id: the notification's id
|
|
||||||
// @source: the notification's Source
|
|
||||||
// @title: the title
|
|
||||||
// @banner: the banner text
|
|
||||||
// @bannerBody: whether or not to promote the banner to the body on overflow
|
|
||||||
//
|
|
||||||
// Creates a notification. In banner mode, it will show
|
|
||||||
// @source's icon, @title (in bold) and @banner, all on a single line
|
|
||||||
// (with @banner ellipsized if necessary).
|
|
||||||
//
|
|
||||||
// Additional notification details can be added, in which case the
|
|
||||||
// notification can be expanded by moving the pointer into it. In
|
|
||||||
// expanded mode, the banner text disappears, and there can be one or
|
|
||||||
// more rows of additional content. This content is put inside a
|
|
||||||
// scrollview, so if it gets too tall, the notification will scroll
|
|
||||||
// rather than continuing to grow. In addition to this main content
|
|
||||||
// area, there is also a single-row "action area", which is not
|
|
||||||
// scrolled and can contain a single actor. There are also convenience
|
|
||||||
// methods for creating a button box in the action area.
|
|
||||||
//
|
|
||||||
// If @bannerBody is %true, then @banner will also be used as the body
|
|
||||||
// of the notification (as with addBody()) when the banner is expanded.
|
|
||||||
// In this case, if @banner is too long to fit in the single-line mode,
|
|
||||||
// the notification will be made expandable automatically.
|
|
||||||
function Notification(id, source, title, banner, bannerBody) {
|
|
||||||
this._init(id, source, title, banner, bannerBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification.prototype = {
|
|
||||||
_init: function(id, source, title, banner, bannerBody) {
|
|
||||||
this.id = id;
|
|
||||||
this.source = source;
|
|
||||||
this._bannerBody = bannerBody;
|
|
||||||
this.urgent = false;
|
|
||||||
|
|
||||||
source.connect('clicked', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this.emit('dismissed');
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.actor = new St.Table({ name: 'notification',
|
|
||||||
reactive: true });
|
|
||||||
this.actor.connect('style-changed', Lang.bind(this, this._styleChanged));
|
|
||||||
this.update(title, banner, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
// update:
|
|
||||||
// @title: the new title
|
|
||||||
// @banner: the new banner
|
|
||||||
// @clear: whether or not to clear out body and action actors
|
|
||||||
//
|
|
||||||
// Updates the notification by regenerating its icon and updating
|
|
||||||
// the title/banner. If @clear is %true, it will also remove any
|
|
||||||
// additional actors/action buttons previously added.
|
|
||||||
update: function(title, banner, clear) {
|
|
||||||
if (this._icon)
|
|
||||||
this._icon.destroy();
|
|
||||||
if (this._bannerBox)
|
|
||||||
this._bannerBox.destroy();
|
|
||||||
if (this._scrollArea && (this._bannerBody || clear)) {
|
|
||||||
this._scrollArea.destroy();
|
|
||||||
this._scrollArea = null;
|
|
||||||
this._contentArea = null;
|
|
||||||
}
|
|
||||||
if (this._actionArea && clear) {
|
|
||||||
this._actionArea.destroy();
|
|
||||||
this._actionArea = null;
|
|
||||||
this._buttonBox = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._icon = this.source.createIcon(ICON_SIZE);
|
|
||||||
this._icon.reactive = true;
|
|
||||||
this.actor.add(this._icon, { row: 0,
|
|
||||||
col: 0,
|
|
||||||
x_expand: false,
|
|
||||||
y_expand: false,
|
|
||||||
y_fill: false });
|
|
||||||
|
|
||||||
this._icon.connect('button-release-event', Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
this.source.clicked();
|
|
||||||
}));
|
|
||||||
|
|
||||||
// The first line should have the title, followed by the
|
|
||||||
// banner text, but ellipsized if they won't both fit. We can't
|
|
||||||
// make St.Table or St.BoxLayout do this the way we want (don't
|
|
||||||
// show banner at all if title needs to be ellipsized), so we
|
|
||||||
// use Shell.GenericContainer.
|
|
||||||
this._bannerBox = new Shell.GenericContainer();
|
|
||||||
this._bannerBox.connect('get-preferred-width', Lang.bind(this, this._bannerBoxGetPreferredWidth));
|
|
||||||
this._bannerBox.connect('get-preferred-height', Lang.bind(this, this._bannerBoxGetPreferredHeight));
|
|
||||||
this._bannerBox.connect('allocate', Lang.bind(this, this._bannerBoxAllocate));
|
|
||||||
this.actor.add(this._bannerBox, { row: 0,
|
|
||||||
col: 1,
|
|
||||||
y_expand: false,
|
|
||||||
y_fill: false });
|
|
||||||
|
|
||||||
this._titleLabel = new St.Label();
|
|
||||||
title = title ? _cleanMarkup(title.replace(/\n/g, ' ')) : '';
|
|
||||||
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
|
|
||||||
this._bannerBox.add_actor(this._titleLabel);
|
|
||||||
|
|
||||||
if (this._bannerBody)
|
|
||||||
this._bannerBodyText = banner;
|
|
||||||
else
|
|
||||||
this._bannerBodyText = null;
|
|
||||||
|
|
||||||
this._bannerLabel = new St.Label();
|
|
||||||
banner = banner ? _cleanMarkup(banner.replace(/\n/g, ' ')) : '';
|
|
||||||
this._bannerLabel.clutter_text.set_markup(banner);
|
|
||||||
this._bannerBox.add_actor(this._bannerLabel);
|
|
||||||
|
|
||||||
// Add the bannerBody now if we know for sure we'll need it
|
|
||||||
if (this._bannerBodyText && this._bannerBodyText.indexOf('\n') > -1)
|
|
||||||
this._addBannerBody();
|
|
||||||
},
|
|
||||||
|
|
||||||
// addActor:
|
|
||||||
// @actor: actor to add to the body of the notification
|
|
||||||
//
|
|
||||||
// Appends @actor to the notification's body
|
|
||||||
addActor: function(actor) {
|
|
||||||
if (!this._scrollArea) {
|
|
||||||
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
|
|
||||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
|
||||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
|
||||||
vshadows: true });
|
|
||||||
this.actor.add(this._scrollArea, { row: 1,
|
|
||||||
col: 1 });
|
|
||||||
this._contentArea = new St.BoxLayout({ name: 'notification-body',
|
|
||||||
vertical: true });
|
|
||||||
this._scrollArea.add_actor(this._contentArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._contentArea.add(actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
// addBody:
|
|
||||||
// @text: the text
|
|
||||||
//
|
|
||||||
// Adds a multi-line label containing @text to the notification.
|
|
||||||
//
|
|
||||||
// Return value: the newly-added label
|
|
||||||
addBody: function(text) {
|
|
||||||
let body = new St.Label();
|
|
||||||
body.clutter_text.line_wrap = true;
|
|
||||||
body.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
|
||||||
body.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
||||||
|
|
||||||
text = text ? _cleanMarkup(text) : '';
|
|
||||||
body.clutter_text.set_markup(text);
|
|
||||||
|
|
||||||
this.addActor(body);
|
|
||||||
return body;
|
|
||||||
},
|
|
||||||
|
|
||||||
_addBannerBody: function() {
|
|
||||||
this.addBody(this._bannerBodyText);
|
|
||||||
this._bannerBodyText = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
// scrollTo:
|
|
||||||
// @side: St.Side.TOP or St.Side.BOTTOM
|
|
||||||
//
|
|
||||||
// Scrolls the content area (if scrollable) to the indicated edge
|
|
||||||
scrollTo: function(side) {
|
|
||||||
// Hack to force a relayout, since the caller probably
|
|
||||||
// just added or removed something to scrollArea, and
|
|
||||||
// the adjustment needs to reflect that.
|
|
||||||
global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, 0, 0);
|
|
||||||
|
|
||||||
let adjustment = this._scrollArea.vscroll.adjustment;
|
|
||||||
if (side == St.Side.TOP)
|
|
||||||
adjustment.value = adjustment.lower;
|
|
||||||
else if (side == St.Side.BOTTOM)
|
|
||||||
adjustment.value = adjustment.upper;
|
|
||||||
},
|
|
||||||
|
|
||||||
// setActionArea:
|
|
||||||
// @actor: the actor
|
|
||||||
// @props: (option) St.Table child properties
|
|
||||||
//
|
|
||||||
// Puts @actor into the action area of the notification, replacing
|
|
||||||
// the previous contents
|
|
||||||
setActionArea: function(actor, props) {
|
|
||||||
if (this._actionArea) {
|
|
||||||
this._actionArea.destroy();
|
|
||||||
this._actionArea = null;
|
|
||||||
if (this._buttonBox)
|
|
||||||
this._buttonBox = null;
|
|
||||||
}
|
|
||||||
this._actionArea = actor;
|
|
||||||
|
|
||||||
if (!props)
|
|
||||||
props = {};
|
|
||||||
props.row = 2;
|
|
||||||
props.col = 1;
|
|
||||||
|
|
||||||
this.actor.add(this._actionArea, props);
|
|
||||||
},
|
|
||||||
|
|
||||||
// addButton:
|
|
||||||
// @id: the action ID
|
|
||||||
// @label: the label for the action's button
|
|
||||||
//
|
|
||||||
// Adds a button with the given @label to the notification. All
|
|
||||||
// action buttons will appear in a single row at the bottom of
|
|
||||||
// the notification.
|
|
||||||
//
|
|
||||||
// If the button is clicked, the notification will emit the
|
|
||||||
// %action-invoked signal with @id as a parameter
|
|
||||||
addButton: function(id, label) {
|
|
||||||
if (!this._buttonBox) {
|
|
||||||
if (this._bannerBodyText)
|
|
||||||
this._addBannerBody();
|
|
||||||
|
|
||||||
let box = new St.BoxLayout({ name: 'notification-actions' });
|
|
||||||
this.setActionArea(box, { x_expand: false,
|
|
||||||
x_fill: false,
|
|
||||||
x_align: St.Align.END });
|
|
||||||
this._buttonBox = box;
|
|
||||||
}
|
|
||||||
|
|
||||||
let button = new St.Button({ style_class: 'notification-button',
|
|
||||||
label: label });
|
|
||||||
this._buttonBox.add(button);
|
|
||||||
button.connect('clicked', Lang.bind(this, function() { this.emit('action-invoked', id); }));
|
|
||||||
},
|
|
||||||
|
|
||||||
setUrgent: function(urgent) {
|
|
||||||
this.urgent = urgent;
|
|
||||||
},
|
|
||||||
|
|
||||||
_styleChanged: function() {
|
|
||||||
let [has_spacing, spacing] = this.actor.get_theme_node().get_length('spacing-columns', false);
|
|
||||||
this._spacing = has_spacing ? spacing : 0;
|
|
||||||
|
|
||||||
// Figure out now (before allocation starts) whether or not we
|
|
||||||
// need to be expandable, and add the expansion row if so
|
|
||||||
if (this._bannerBodyText) {
|
|
||||||
let [minBannerWidth, natBannerWidth] =
|
|
||||||
this._bannerBox.get_preferred_width(-1);
|
|
||||||
let [minNotificationWidth, natNotificationWidth] =
|
|
||||||
this.actor.get_preferred_width(-1);
|
|
||||||
|
|
||||||
if (natBannerWidth > natNotificationWidth)
|
|
||||||
this._addBannerBody();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_bannerBoxGetPreferredWidth: function(actor, forHeight, alloc) {
|
|
||||||
let [titleMin, titleNat] = this._titleLabel.get_preferred_width(forHeight);
|
|
||||||
let [bannerMin, bannerNat] = this._bannerLabel.get_preferred_width(forHeight);
|
|
||||||
|
|
||||||
alloc.min_size = titleMin;
|
|
||||||
alloc.natural_size = titleNat + this._spacing + bannerNat;
|
|
||||||
},
|
|
||||||
|
|
||||||
_bannerBoxGetPreferredHeight: function(actor, forWidth, alloc) {
|
|
||||||
[alloc.min_size, alloc.natural_size] =
|
|
||||||
this._titleLabel.get_preferred_height(forWidth);
|
|
||||||
},
|
|
||||||
|
|
||||||
_bannerBoxAllocate: function(actor, box, flags) {
|
|
||||||
let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
|
|
||||||
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(-1);
|
|
||||||
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(-1);
|
|
||||||
let availWidth = box.x2 - box.x1;
|
|
||||||
|
|
||||||
let titleBox = new Clutter.ActorBox();
|
|
||||||
titleBox.x1 = titleBox.y1 = 0;
|
|
||||||
titleBox.x2 = Math.min(titleNatW, availWidth);
|
|
||||||
titleBox.y2 = titleNatH;
|
|
||||||
this._titleLabel.allocate(titleBox, flags);
|
|
||||||
|
|
||||||
if (titleBox.x2 + this._spacing > availWidth) {
|
|
||||||
this._bannerLabel.hide();
|
|
||||||
} else {
|
|
||||||
let bannerBox = new Clutter.ActorBox();
|
|
||||||
bannerBox.x1 = titleBox.x2 + this._spacing;
|
|
||||||
bannerBox.y1 = 0;
|
|
||||||
bannerBox.x2 = Math.min(bannerBox.x1 + bannerNatW, availWidth);
|
|
||||||
bannerBox.y2 = titleNatH;
|
|
||||||
this._bannerLabel.show();
|
|
||||||
this._bannerLabel.allocate(bannerBox, flags);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
popOut: function() {
|
|
||||||
if (this.actor.row_count <= 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Tweener.addTween(this._bannerLabel,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad' });
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
popIn: function() {
|
|
||||||
if (this.actor.row_count <= 1)
|
|
||||||
return false;
|
|
||||||
Tweener.addTween(this._bannerLabel,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad' });
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
this.emit('destroy');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(Notification.prototype);
|
|
||||||
|
|
||||||
function Source(id, createIcon) {
|
|
||||||
this._init(id, createIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
Source.prototype = {
|
|
||||||
_init: function(id, createIcon) {
|
|
||||||
this.id = id;
|
|
||||||
this.text = null;
|
|
||||||
if (createIcon)
|
|
||||||
this.createIcon = createIcon;
|
|
||||||
},
|
|
||||||
|
|
||||||
// This can be overridden by a subclass, or by the createIcon
|
|
||||||
// parameter to _init()
|
|
||||||
createIcon: function(size) {
|
|
||||||
throw new Error('no implementation of createIcon in ' + this);
|
|
||||||
},
|
|
||||||
|
|
||||||
notify: function(notification) {
|
|
||||||
if (this.notification)
|
|
||||||
this.notification.disconnect(this._notificationDestroyedId);
|
|
||||||
|
|
||||||
this.notification = notification;
|
|
||||||
|
|
||||||
this._notificationDestroyedId = notification.connect('destroy', Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
if (this.notification == notification) {
|
|
||||||
this.notification = null;
|
|
||||||
this._notificationDestroyedId = 0;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.emit('notify', notification);
|
|
||||||
},
|
|
||||||
|
|
||||||
clicked: function() {
|
|
||||||
this.emit('clicked');
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
this.emit('destroy');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(Source.prototype);
|
|
||||||
|
|
||||||
function MessageTray() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageTray.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.BoxLayout({ name: 'message-tray',
|
|
||||||
reactive: true,
|
|
||||||
track_hover: true });
|
|
||||||
this.actor.connect('notify::hover', Lang.bind(this, this._onTrayHoverChanged));
|
|
||||||
|
|
||||||
this._notificationBin = new St.Bin();
|
|
||||||
this.actor.add(this._notificationBin);
|
|
||||||
this._notificationBin.hide();
|
|
||||||
this._notificationQueue = [];
|
|
||||||
this._notification = null;
|
|
||||||
|
|
||||||
this._summaryBin = new St.Bin({ anchor_gravity: Clutter.Gravity.NORTH_EAST });
|
|
||||||
this.actor.add(this._summaryBin);
|
|
||||||
this._summary = new St.BoxLayout({ name: 'summary-mode',
|
|
||||||
reactive: true,
|
|
||||||
track_hover: true });
|
|
||||||
this._summary.connect('notify::hover', Lang.bind(this, this._onSummaryHoverChanged));
|
|
||||||
this._summaryBin.child = this._summary;
|
|
||||||
this._summaryBin.opacity = 0;
|
|
||||||
|
|
||||||
this._summaryNotificationBin = new St.Bin({ name: 'summary-notification-bin',
|
|
||||||
anchor_gravity: Clutter.Gravity.NORTH_EAST,
|
|
||||||
reactive: true,
|
|
||||||
track_hover: true });
|
|
||||||
this.actor.add(this._summaryNotificationBin);
|
|
||||||
this._summaryNotificationBin.lower_bottom();
|
|
||||||
this._summaryNotificationBin.hide();
|
|
||||||
this._summaryNotificationBin.connect('notify::hover', Lang.bind(this, this._onSummaryNotificationHoverChanged));
|
|
||||||
this._summaryNotification = null;
|
|
||||||
this._hoverSource = null;
|
|
||||||
|
|
||||||
this._trayState = State.HIDDEN;
|
|
||||||
this._trayLeftTimeoutId = 0;
|
|
||||||
this._pointerInTray = false;
|
|
||||||
this._summaryState = State.HIDDEN;
|
|
||||||
this._summaryTimeoutId = 0;
|
|
||||||
this._pointerInSummary = false;
|
|
||||||
this._notificationState = State.HIDDEN;
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
this._summaryNotificationState = State.HIDDEN;
|
|
||||||
this._summaryNotificationTimeoutId = 0;
|
|
||||||
this._overviewVisible = false;
|
|
||||||
this._notificationRemoved = false;
|
|
||||||
|
|
||||||
Main.chrome.addActor(this.actor, { affectsStruts: false,
|
|
||||||
visibleInOverview: true });
|
|
||||||
Main.chrome.trackActor(this._notificationBin);
|
|
||||||
Main.chrome.trackActor(this._summaryNotificationBin);
|
|
||||||
|
|
||||||
global.connect('screen-size-changed',
|
|
||||||
Lang.bind(this, this._setSizePosition));
|
|
||||||
this._setSizePosition();
|
|
||||||
|
|
||||||
Main.overview.connect('showing', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._overviewVisible = true;
|
|
||||||
this._updateState();
|
|
||||||
}));
|
|
||||||
Main.overview.connect('hiding', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._overviewVisible = false;
|
|
||||||
this._updateState();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._sources = {};
|
|
||||||
this._icons = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
_setSizePosition: function() {
|
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
this.actor.x = primary.x;
|
|
||||||
this.actor.y = primary.y + primary.height - 1;
|
|
||||||
this.actor.width = primary.width;
|
|
||||||
this._notificationBin.x = 0;
|
|
||||||
this._notificationBin.width = primary.width;
|
|
||||||
|
|
||||||
// These work because of their anchor_gravity
|
|
||||||
this._summaryBin.x = primary.width;
|
|
||||||
this._summaryNotificationBin.x = primary.width;
|
|
||||||
},
|
|
||||||
|
|
||||||
contains: function(source) {
|
|
||||||
return this._sources.hasOwnProperty(source.id);
|
|
||||||
},
|
|
||||||
|
|
||||||
add: function(source) {
|
|
||||||
if (this.contains(source)) {
|
|
||||||
log('Trying to re-add source ' + source.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let iconBox = new St.Clickable({ style_class: 'summary-icon',
|
|
||||||
reactive: true });
|
|
||||||
iconBox.child = source.createIcon(ICON_SIZE);
|
|
||||||
this._summary.insert_actor(iconBox, 0);
|
|
||||||
this._summaryNeedsToBeShown = true;
|
|
||||||
this._icons[source.id] = iconBox;
|
|
||||||
this._sources[source.id] = source;
|
|
||||||
|
|
||||||
source.connect('notify', Lang.bind(this, this._onNotify));
|
|
||||||
|
|
||||||
iconBox.connect('notify::hover', Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
this._onSourceHoverChanged(source, iconBox.hover);
|
|
||||||
}));
|
|
||||||
iconBox.connect('clicked', Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
source.clicked();
|
|
||||||
}));
|
|
||||||
|
|
||||||
source.connect('destroy', Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
this.removeSource(source);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
removeSource: function(source) {
|
|
||||||
if (!this.contains(source))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// remove all notifications with this source from the queue
|
|
||||||
let newNotificationQueue = [];
|
|
||||||
for (let i = 0; i < this._notificationQueue.length; i++) {
|
|
||||||
if (this._notificationQueue[i].source != source)
|
|
||||||
newNotificationQueue.push(this._notificationQueue[i]);
|
|
||||||
}
|
|
||||||
this._notificationQueue = newNotificationQueue;
|
|
||||||
|
|
||||||
this._summary.remove_actor(this._icons[source.id]);
|
|
||||||
if (this._summary.get_children().length > 0)
|
|
||||||
this._summaryNeedsToBeShown = true;
|
|
||||||
else
|
|
||||||
this._summaryNeedsToBeShown = false;
|
|
||||||
delete this._icons[source.id];
|
|
||||||
delete this._sources[source.id];
|
|
||||||
|
|
||||||
let needUpdate = false;
|
|
||||||
|
|
||||||
if (this._notification && this._notification.source == source) {
|
|
||||||
if (this._notificationTimeoutId) {
|
|
||||||
Mainloop.source_remove(this._notificationTimeoutId);
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
}
|
|
||||||
this._notificationRemoved = true;
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
if (this._hoverSource == source) {
|
|
||||||
this._hoverSource = null;
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needUpdate);
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
removeSourceByApp: function(app) {
|
|
||||||
for (let source in this._sources)
|
|
||||||
if (this._sources[source].app == app)
|
|
||||||
this.removeSource(this._sources[source]);
|
|
||||||
},
|
|
||||||
|
|
||||||
removeNotification: function(notification) {
|
|
||||||
if (this._notification == notification && (this._notificationState == State.SHOWN || this._notificationState == State.SHOWING)) {
|
|
||||||
if (this._notificationTimeoutId) {
|
|
||||||
Mainloop.source_remove(this._notificationTimeoutId);
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
}
|
|
||||||
this._notificationRemoved = true;
|
|
||||||
this._updateState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = this._notificationQueue.indexOf(notification);
|
|
||||||
if (index != -1)
|
|
||||||
this._notificationQueue.splice(index, 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
getSource: function(id) {
|
|
||||||
return this._sources[id];
|
|
||||||
},
|
|
||||||
|
|
||||||
_getNotification: function(id, source) {
|
|
||||||
if (this._notification && this._notification.id == id)
|
|
||||||
return this._notification;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._notificationQueue.length; i++) {
|
|
||||||
if (this._notificationQueue[i].id == id && this._notificationQueue[i].source == source)
|
|
||||||
return this._notificationQueue[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
lock: function() {
|
|
||||||
this._locked = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
unlock: function() {
|
|
||||||
this._locked = false;
|
|
||||||
|
|
||||||
this.actor.sync_hover();
|
|
||||||
this._summary.sync_hover();
|
|
||||||
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNotify: function(source, notification) {
|
|
||||||
if (notification == this._summaryNotification)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._getNotification(notification.id, source) == null) {
|
|
||||||
notification.connect('destroy',
|
|
||||||
Lang.bind(this, this.removeNotification));
|
|
||||||
|
|
||||||
if (notification.urgent)
|
|
||||||
this._notificationQueue.unshift(notification);
|
|
||||||
else
|
|
||||||
this._notificationQueue.push(notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSourceHoverChanged: function(source, hover) {
|
|
||||||
if (!source.notification)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._summaryNotificationTimeoutId != 0) {
|
|
||||||
Mainloop.source_remove(this._summaryNotificationTimeoutId);
|
|
||||||
this._summaryNotificationTimeoutId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hover) {
|
|
||||||
this._hoverSource = source;
|
|
||||||
this._updateState();
|
|
||||||
} else if (this._hoverSource == source) {
|
|
||||||
let timeout = HIDE_TIMEOUT * 1000;
|
|
||||||
this._summaryNotificationTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onSourceHoverChangedTimeout, source));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSourceHoverChangedTimeout: function(source) {
|
|
||||||
this._summaryNotificationTimeoutId = 0;
|
|
||||||
if (this._hoverSource == source) {
|
|
||||||
this._hoverSource = null;
|
|
||||||
this._updateState();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSummaryNotificationHoverChanged: function() {
|
|
||||||
if (!this._summaryNotification)
|
|
||||||
return;
|
|
||||||
this._onSourceHoverChanged(this._summaryNotification.source,
|
|
||||||
this._summaryNotificationBin.hover);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSummaryHoverChanged: function() {
|
|
||||||
this._pointerInSummary = this._summary.hover;
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTrayHoverChanged: function() {
|
|
||||||
if (this.actor.hover) {
|
|
||||||
if (this._trayLeftTimeoutId) {
|
|
||||||
Mainloop.source_remove(this._trayLeftTimeoutId);
|
|
||||||
this._trayLeftTimeoutId = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._pointerInTray = true;
|
|
||||||
this._updateState();
|
|
||||||
} else {
|
|
||||||
// We wait just a little before hiding the message tray in case the
|
|
||||||
// user quickly moves the mouse back into it.
|
|
||||||
let timeout = HIDE_TIMEOUT * 1000;
|
|
||||||
this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTrayLeftTimeout: function() {
|
|
||||||
this._trayLeftTimeoutId = 0;
|
|
||||||
this._pointerInTray = false;
|
|
||||||
this._pointerInSummary = false;
|
|
||||||
this._updateState();
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
// All of the logic for what happens when occurs here; the various
|
|
||||||
// event handlers merely update variables such as
|
|
||||||
// 'this._pointerInTray', 'this._summaryState', etc, and
|
|
||||||
// _updateState() figures out what (if anything) needs to be done
|
|
||||||
// at the present time.
|
|
||||||
_updateState: function() {
|
|
||||||
// Notifications
|
|
||||||
let notificationsPending = this._notificationQueue.length > 0;
|
|
||||||
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
|
|
||||||
let notificationExpanded = this._notificationBin.y < 0;
|
|
||||||
let notificationExpired = (this._notificationTimeoutId == 0 && !this._pointerInTray && !this._locked) || this._notificationRemoved;
|
|
||||||
|
|
||||||
if (this._notificationState == State.HIDDEN) {
|
|
||||||
if (notificationsPending)
|
|
||||||
this._showNotification();
|
|
||||||
} else if (this._notificationState == State.SHOWN) {
|
|
||||||
if (notificationExpired)
|
|
||||||
this._hideNotification();
|
|
||||||
else if (notificationPinned && !notificationExpanded)
|
|
||||||
this._expandNotification();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Summary
|
|
||||||
let summarySummoned = this._pointerInSummary || this._overviewVisible;
|
|
||||||
let summaryPinned = this._summaryTimeoutId != 0 || this._pointerInTray || summarySummoned;
|
|
||||||
|
|
||||||
let notificationsVisible = (this._notificationState == State.SHOWING ||
|
|
||||||
this._notificationState == State.SHOWN);
|
|
||||||
let notificationsDone = !notificationsVisible && !notificationsPending;
|
|
||||||
|
|
||||||
if (this._summaryState == State.HIDDEN) {
|
|
||||||
if (notificationsDone && this._summaryNeedsToBeShown)
|
|
||||||
this._showSummary(true);
|
|
||||||
else if (!notificationsVisible && summarySummoned)
|
|
||||||
this._showSummary(false);
|
|
||||||
} else if (this._summaryState == State.SHOWN) {
|
|
||||||
if (!summaryPinned)
|
|
||||||
this._hideSummary();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Summary notification
|
|
||||||
let haveSummaryNotification = this._hoverSource != null;
|
|
||||||
let summaryNotificationIsMainNotification = (haveSummaryNotification &&
|
|
||||||
this._hoverSource.notification == this._notification);
|
|
||||||
let canShowSummaryNotification = this._summaryState == State.SHOWN;
|
|
||||||
let wrongSummaryNotification = (haveSummaryNotification &&
|
|
||||||
this._summaryNotification != this._hoverSource.notification);
|
|
||||||
|
|
||||||
if (this._summaryNotificationState == State.HIDDEN) {
|
|
||||||
if (haveSummaryNotification && !summaryNotificationIsMainNotification && canShowSummaryNotification)
|
|
||||||
this._showSummaryNotification();
|
|
||||||
} else if (this._summaryNotificationState == State.SHOWN) {
|
|
||||||
if (!haveSummaryNotification || !canShowSummaryNotification || wrongSummaryNotification)
|
|
||||||
this._hideSummaryNotification();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tray itself
|
|
||||||
let trayIsVisible = (this._trayState == State.SHOWING ||
|
|
||||||
this._trayState == State.SHOWN);
|
|
||||||
let trayShouldBeVisible = (!notificationsDone ||
|
|
||||||
this._summaryState == State.SHOWING ||
|
|
||||||
this._summaryState == State.SHOWN);
|
|
||||||
if (!trayIsVisible && trayShouldBeVisible)
|
|
||||||
this._showTray();
|
|
||||||
else if (trayIsVisible && !trayShouldBeVisible)
|
|
||||||
this._hideTray();
|
|
||||||
},
|
|
||||||
|
|
||||||
_tween: function(actor, statevar, value, params) {
|
|
||||||
let onComplete = params.onComplete;
|
|
||||||
let onCompleteScope = params.onCompleteScope;
|
|
||||||
let onCompleteParams = params.onCompleteParams;
|
|
||||||
|
|
||||||
params.onComplete = this._tweenComplete;
|
|
||||||
params.onCompleteScope = this;
|
|
||||||
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
|
|
||||||
|
|
||||||
Tweener.addTween(actor, params);
|
|
||||||
|
|
||||||
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
|
|
||||||
this[statevar] = valuing;
|
|
||||||
},
|
|
||||||
|
|
||||||
_tweenComplete: function(statevar, value, onComplete, onCompleteScope, onCompleteParams) {
|
|
||||||
this[statevar] = value;
|
|
||||||
if (onComplete)
|
|
||||||
onComplete.apply(onCompleteScope, onCompleteParams);
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_showTray: function() {
|
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
this._tween(this.actor, '_trayState', State.SHOWN,
|
|
||||||
{ y: primary.y + primary.height - this.actor.height,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideTray: function() {
|
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
this._tween(this.actor, '_trayState', State.HIDDEN,
|
|
||||||
{ y: primary.y + primary.height - 1,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_showNotification: function() {
|
|
||||||
this._notification = this._notificationQueue.shift();
|
|
||||||
this._notificationBin.child = this._notification.actor;
|
|
||||||
|
|
||||||
this._notificationBin.opacity = 0;
|
|
||||||
this._notificationBin.y = this.actor.height;
|
|
||||||
this._notificationBin.show();
|
|
||||||
|
|
||||||
this._tween(this._notificationBin, '_notificationState', State.SHOWN,
|
|
||||||
{ y: 0,
|
|
||||||
opacity: 255,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: this._showNotificationCompleted,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this._notification.urgent) {
|
|
||||||
// This will overwrite the y tween, but leave the opacity
|
|
||||||
// tween, and so the onComplete will remain as well.
|
|
||||||
this._expandNotification();
|
|
||||||
}
|
|
||||||
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
|
||||||
this._lastSeenMouseY = y;
|
|
||||||
},
|
|
||||||
|
|
||||||
_showNotificationCompleted: function() {
|
|
||||||
this._notificationTimeoutId =
|
|
||||||
Mainloop.timeout_add(NOTIFICATION_TIMEOUT * 1000,
|
|
||||||
Lang.bind(this, this._notificationTimeout));
|
|
||||||
},
|
|
||||||
|
|
||||||
_notificationTimeout: function() {
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
|
||||||
if (y > this._lastSeenMouseY + 10 && y < this.actor.y) {
|
|
||||||
// The mouse is moving towards the notification, so don't
|
|
||||||
// hide it yet. (We just create a new timeout (and destroy
|
|
||||||
// the old one) each time because the bookkeeping is
|
|
||||||
// simpler.)
|
|
||||||
this._lastSeenMouseY = y;
|
|
||||||
this._notificationTimeoutId =
|
|
||||||
Mainloop.timeout_add(1000,
|
|
||||||
Lang.bind(this, this._notificationTimeout));
|
|
||||||
} else {
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
this._updateState();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideNotification: function() {
|
|
||||||
this._notification.popIn();
|
|
||||||
|
|
||||||
if (this._reExpandNotificationId) {
|
|
||||||
this._notificationBin.disconnect(this._reExpandNotificationId);
|
|
||||||
this._reExpandNotificationId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tween(this._notificationBin, '_notificationState', State.HIDDEN,
|
|
||||||
{ y: this.actor.height,
|
|
||||||
opacity: 0,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: this._hideNotificationCompleted,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideNotificationCompleted: function() {
|
|
||||||
this._notificationRemoved = false;
|
|
||||||
this._notificationBin.hide();
|
|
||||||
this._notificationBin.child = null;
|
|
||||||
this._notification = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_expandNotification: function() {
|
|
||||||
if (this._notification && this._notification.popOut()) {
|
|
||||||
this._tween(this._notificationBin, '_notificationState', State.SHOWN,
|
|
||||||
{ y: this.actor.height - this._notificationBin.height,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this._reExpandNotificationId)
|
|
||||||
this._reExpandNotificationId = this._notificationBin.connect('notify::height', Lang.bind(this, this._expandNotification));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_showSummary: function(withTimeout) {
|
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
this._summaryBin.opacity = 0;
|
|
||||||
this._summaryBin.y = this.actor.height;
|
|
||||||
this._tween(this._summaryBin, '_summaryState', State.SHOWN,
|
|
||||||
{ y: 0,
|
|
||||||
opacity: 255,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: this._showSummaryCompleted,
|
|
||||||
onCompleteScope: this,
|
|
||||||
onCompleteParams: [withTimeout]
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_showSummaryCompleted: function(withTimeout) {
|
|
||||||
this._summaryNeedsToBeShown = false;
|
|
||||||
|
|
||||||
if (withTimeout) {
|
|
||||||
this._summaryTimeoutId =
|
|
||||||
Mainloop.timeout_add(SUMMARY_TIMEOUT * 1000,
|
|
||||||
Lang.bind(this, this._summaryTimeout));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_summaryTimeout: function() {
|
|
||||||
this._summaryTimeoutId = 0;
|
|
||||||
this._updateState();
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideSummary: function() {
|
|
||||||
this._tween(this._summaryBin, '_summaryState', State.HIDDEN,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
this._summaryNeedsToBeShown = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_showSummaryNotification: function() {
|
|
||||||
this._summaryNotification = this._hoverSource.notification;
|
|
||||||
|
|
||||||
let index = this._notificationQueue.indexOf(this._summaryNotification);
|
|
||||||
if (index != -1)
|
|
||||||
this._notificationQueue.splice(index, 1);
|
|
||||||
|
|
||||||
this._summaryNotificationBin.child = this._summaryNotification.actor;
|
|
||||||
this._summaryNotification.popOut();
|
|
||||||
|
|
||||||
this._summaryNotificationBin.opacity = 0;
|
|
||||||
this._summaryNotificationBin.y = this.actor.height;
|
|
||||||
this._summaryNotificationBin.show();
|
|
||||||
|
|
||||||
this._tween(this._summaryNotificationBin, '_summaryNotificationState', State.SHOWN,
|
|
||||||
{ y: this.actor.height - this._summaryNotificationBin.height,
|
|
||||||
opacity: 255,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this._reExpandSummaryNotificationId)
|
|
||||||
this._reExpandSummaryNotificationId = this._summaryNotificationBin.connect('notify::height', Lang.bind(this, this._reExpandSummaryNotification));
|
|
||||||
},
|
|
||||||
|
|
||||||
_reExpandSummaryNotification: function() {
|
|
||||||
this._tween(this._summaryNotificationBin, '_summaryNotificationState', State.SHOWN,
|
|
||||||
{ y: this.actor.height - this._summaryNotificationBin.height,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideSummaryNotification: function() {
|
|
||||||
this._summaryNotification.popIn();
|
|
||||||
|
|
||||||
this._tween(this._summaryNotificationBin, '_summaryNotificationState', State.HIDDEN,
|
|
||||||
{ y: this.actor.height,
|
|
||||||
opacity: 0,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: this._hideSummaryNotificationCompleted,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this._reExpandSummaryNotificationId) {
|
|
||||||
this._summaryNotificationBin.disconnect(this._reExpandSummaryNotificationId);
|
|
||||||
this._reExpandSummaryNotificationId = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideSummaryNotificationCompleted: function() {
|
|
||||||
this._summaryNotificationBin.hide();
|
|
||||||
this._summaryNotificationBin.child = null;
|
|
||||||
this._summaryNotification = null;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,357 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
|
|
||||||
let nextNotificationId = 1;
|
|
||||||
|
|
||||||
// Should really be defined in dbus.js
|
|
||||||
const BusIface = {
|
|
||||||
name: 'org.freedesktop.DBus',
|
|
||||||
methods: [{ name: 'GetConnectionUnixProcessID',
|
|
||||||
inSignature: 's',
|
|
||||||
outSignature: 'i' }]
|
|
||||||
};
|
|
||||||
|
|
||||||
const Bus = function () {
|
|
||||||
this._init();
|
|
||||||
};
|
|
||||||
|
|
||||||
Bus.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
DBus.session.proxifyObject(this, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(Bus.prototype, BusIface);
|
|
||||||
|
|
||||||
const NotificationDaemonIface = {
|
|
||||||
name: 'org.freedesktop.Notifications',
|
|
||||||
methods: [{ name: 'Notify',
|
|
||||||
inSignature: 'susssasa{sv}i',
|
|
||||||
outSignature: 'u'
|
|
||||||
},
|
|
||||||
{ name: 'CloseNotification',
|
|
||||||
inSignature: 'u',
|
|
||||||
outSignature: ''
|
|
||||||
},
|
|
||||||
{ name: 'GetCapabilities',
|
|
||||||
inSignature: '',
|
|
||||||
outSignature: 'as'
|
|
||||||
},
|
|
||||||
{ name: 'GetServerInformation',
|
|
||||||
inSignature: '',
|
|
||||||
outSignature: 'ssss'
|
|
||||||
}],
|
|
||||||
signals: [{ name: 'NotificationClosed',
|
|
||||||
inSignature: 'uu' },
|
|
||||||
{ name: 'ActionInvoked',
|
|
||||||
inSignature: 'us' }]
|
|
||||||
};
|
|
||||||
|
|
||||||
const NotificationClosedReason = {
|
|
||||||
EXPIRED: 1,
|
|
||||||
DISMISSED: 2,
|
|
||||||
APP_CLOSED: 3,
|
|
||||||
UNDEFINED: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
const Urgency = {
|
|
||||||
LOW: 0,
|
|
||||||
NORMAL: 1,
|
|
||||||
CRITICAL: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
const rewriteRules = {
|
|
||||||
'XChat': [
|
|
||||||
{ pattern: /^XChat: Private message from: (\S*) \(.*\)$/,
|
|
||||||
replacement: '<$1>' },
|
|
||||||
{ pattern: /^XChat: New public message from: (\S*) \((.*)\)$/,
|
|
||||||
replacement: '$2 <$1>' },
|
|
||||||
{ pattern: /^XChat: Highlighted message from: (\S*) \((.*)\)$/,
|
|
||||||
replacement: '$2 <$1>' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
function NotificationDaemon() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationDaemon.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
DBus.session.exportObject('/org/freedesktop/Notifications', this);
|
|
||||||
|
|
||||||
this._everAcquiredName = false;
|
|
||||||
DBus.session.acquire_name('org.freedesktop.Notifications',
|
|
||||||
// We pass MANY_INSTANCES so that if
|
|
||||||
// notification-daemon is running, we'll
|
|
||||||
// get queued behind it and then get the
|
|
||||||
// name after killing it below
|
|
||||||
DBus.MANY_INSTANCES,
|
|
||||||
Lang.bind(this, this._acquiredName),
|
|
||||||
Lang.bind(this, this._lostName));
|
|
||||||
|
|
||||||
this._currentNotifications = {};
|
|
||||||
|
|
||||||
Shell.WindowTracker.get_default().connect('notify::focus-app',
|
|
||||||
Lang.bind(this, this._onFocusAppChanged));
|
|
||||||
Main.overview.connect('hidden',
|
|
||||||
Lang.bind(this, this._onFocusAppChanged));
|
|
||||||
},
|
|
||||||
|
|
||||||
_acquiredName: function() {
|
|
||||||
this._everAcquiredName = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_lostName: function() {
|
|
||||||
if (this._everAcquiredName)
|
|
||||||
log('Lost name org.freedesktop.Notifications!');
|
|
||||||
else if (GLib.getenv('GNOME_SHELL_NO_REPLACE'))
|
|
||||||
log('Failed to acquire org.freedesktop.Notifications');
|
|
||||||
else {
|
|
||||||
log('Failed to acquire org.freedesktop.Notifications; trying again');
|
|
||||||
|
|
||||||
// kill the notification-daemon. pkill is more portable
|
|
||||||
// than killall, but on Linux at least it won't match if
|
|
||||||
// you pass more than 15 characters of the process name...
|
|
||||||
// However, if you use the '-f' flag to match the entire
|
|
||||||
// command line, it will work, but we have to be careful
|
|
||||||
// in that case that we don't match 'gedit
|
|
||||||
// notification-daemon.c' or whatever...
|
|
||||||
let p = new Shell.Process({ args: ['pkill', '-f',
|
|
||||||
'^([^ ]*/)?(notification-daemon|notify-osd)$']});
|
|
||||||
p.run();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_sourceId: function(id) {
|
|
||||||
return 'source-' + id;
|
|
||||||
},
|
|
||||||
|
|
||||||
Notify: function(appName, replacesId, icon, summary, body,
|
|
||||||
actions, hints, timeout) {
|
|
||||||
let source = Main.messageTray.getSource(this._sourceId(appName));
|
|
||||||
let id = null;
|
|
||||||
|
|
||||||
// Filter out notifications from Empathy, since we
|
|
||||||
// handle that information from telepathyClient.js
|
|
||||||
if (appName == 'Empathy') {
|
|
||||||
id = nextNotificationId++;
|
|
||||||
Mainloop.idle_add(Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
|
|
||||||
}));
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
|
|
||||||
|
|
||||||
// Source may be null if we have never received a notification
|
|
||||||
// from this app or if all notifications from this app have
|
|
||||||
// been acknowledged.
|
|
||||||
if (source == null) {
|
|
||||||
source = new Source(this._sourceId(appName), icon, hints);
|
|
||||||
Main.messageTray.add(source);
|
|
||||||
|
|
||||||
source.connect('clicked', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
source.destroy();
|
|
||||||
}));
|
|
||||||
|
|
||||||
let sender = DBus.getCurrentMessageContext().sender;
|
|
||||||
let busProxy = new Bus();
|
|
||||||
busProxy.GetConnectionUnixProcessIDRemote(sender, function (result, excp) {
|
|
||||||
let app = Shell.WindowTracker.get_default().get_app_from_pid(result);
|
|
||||||
if (app)
|
|
||||||
source.setApp(app);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
source.update(icon, hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
summary = GLib.markup_escape_text(summary, -1);
|
|
||||||
|
|
||||||
let rewrites = rewriteRules[appName];
|
|
||||||
if (rewrites) {
|
|
||||||
for (let i = 0; i < rewrites.length; i++) {
|
|
||||||
let rule = rewrites[i];
|
|
||||||
if (summary.search(rule.pattern) != -1)
|
|
||||||
summary = summary.replace(rule.pattern, rule.replacement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let notification;
|
|
||||||
if (replacesId != 0) {
|
|
||||||
id = replacesId;
|
|
||||||
notification = this._currentNotifications[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notification == null) {
|
|
||||||
id = nextNotificationId++;
|
|
||||||
notification = new MessageTray.Notification(id, source, summary, body, true);
|
|
||||||
this._currentNotifications[id] = notification;
|
|
||||||
notification.connect('dismissed', Lang.bind(this,
|
|
||||||
function(n) {
|
|
||||||
n.destroy();
|
|
||||||
this._emitNotificationClosed(n.id, NotificationClosedReason.DISMISSED);
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
// passing in true as the last parameter will clear out extra actors,
|
|
||||||
// such as actions
|
|
||||||
notification.update(summary, body, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actions.length) {
|
|
||||||
for (let i = 0; i < actions.length - 1; i += 2)
|
|
||||||
notification.addButton(actions[i], actions[i + 1]);
|
|
||||||
notification.connect('action-invoked', Lang.bind(this, this._actionInvoked, source, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
notification.setUrgent(hints.urgency == Urgency.CRITICAL);
|
|
||||||
|
|
||||||
source.notify(notification);
|
|
||||||
return id;
|
|
||||||
},
|
|
||||||
|
|
||||||
CloseNotification: function(id) {
|
|
||||||
let notification = this._currentNotifications[id];
|
|
||||||
if (notification)
|
|
||||||
notification.destroy();
|
|
||||||
this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
|
|
||||||
},
|
|
||||||
|
|
||||||
GetCapabilities: function() {
|
|
||||||
return [
|
|
||||||
'actions',
|
|
||||||
'body',
|
|
||||||
// 'body-hyperlinks',
|
|
||||||
// 'body-images',
|
|
||||||
'body-markup',
|
|
||||||
// 'icon-multi',
|
|
||||||
'icon-static'
|
|
||||||
// 'sound',
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
GetServerInformation: function() {
|
|
||||||
return [
|
|
||||||
'GNOME Shell',
|
|
||||||
'GNOME',
|
|
||||||
'0.1', // FIXME, get this from somewhere
|
|
||||||
'1.0'
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
_onFocusAppChanged: function() {
|
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
|
||||||
if (tracker.focus_app)
|
|
||||||
Main.messageTray.removeSourceByApp(tracker.focus_app);
|
|
||||||
},
|
|
||||||
|
|
||||||
_actionInvoked: function(notification, action, source, id) {
|
|
||||||
this._emitActionInvoked(id, action);
|
|
||||||
source.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
_emitNotificationClosed: function(id, reason) {
|
|
||||||
delete this._currentNotifications[id];
|
|
||||||
DBus.session.emit_signal('/org/freedesktop/Notifications',
|
|
||||||
'org.freedesktop.Notifications',
|
|
||||||
'NotificationClosed', 'uu',
|
|
||||||
[id, reason]);
|
|
||||||
},
|
|
||||||
|
|
||||||
_emitActionInvoked: function(id, action) {
|
|
||||||
DBus.session.emit_signal('/org/freedesktop/Notifications',
|
|
||||||
'org.freedesktop.Notifications',
|
|
||||||
'ActionInvoked', 'us',
|
|
||||||
[id, action]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
|
|
||||||
|
|
||||||
function Source(sourceId, icon, hints) {
|
|
||||||
this._init(sourceId, icon, hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
Source.prototype = {
|
|
||||||
__proto__: MessageTray.Source.prototype,
|
|
||||||
|
|
||||||
_init: function(sourceId, icon, hints) {
|
|
||||||
MessageTray.Source.prototype._init.call(this, sourceId);
|
|
||||||
|
|
||||||
this.app = null;
|
|
||||||
this._openAppRequested = false;
|
|
||||||
|
|
||||||
this.update(icon, hints);
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function(icon, hints) {
|
|
||||||
this._icon = icon;
|
|
||||||
this._iconData = hints.icon_data;
|
|
||||||
this._urgency = hints.urgency;
|
|
||||||
},
|
|
||||||
|
|
||||||
createIcon: function(size) {
|
|
||||||
let textureCache = St.TextureCache.get_default();
|
|
||||||
|
|
||||||
if (this._icon) {
|
|
||||||
if (this._icon.substr(0, 7) == 'file://')
|
|
||||||
return textureCache.load_uri_async(this._icon, size, size);
|
|
||||||
else if (this._icon[0] == '/') {
|
|
||||||
let uri = GLib.filename_to_uri(this._icon, null);
|
|
||||||
return textureCache.load_uri_async(uri, size, size);
|
|
||||||
} else
|
|
||||||
return textureCache.load_icon_name(this._icon, size);
|
|
||||||
} else if (this._iconData) {
|
|
||||||
let [width, height, rowStride, hasAlpha,
|
|
||||||
bitsPerSample, nChannels, data] = this._iconData;
|
|
||||||
return textureCache.load_from_raw(data, data.length, hasAlpha,
|
|
||||||
width, height, rowStride, size);
|
|
||||||
} else {
|
|
||||||
let stockIcon;
|
|
||||||
switch (this._urgency) {
|
|
||||||
case Urgency.LOW:
|
|
||||||
case Urgency.NORMAL:
|
|
||||||
stockIcon = 'gtk-dialog-info';
|
|
||||||
break;
|
|
||||||
case Urgency.CRITICAL:
|
|
||||||
stockIcon = 'gtk-dialog-error';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return textureCache.load_icon_name(stockIcon, size);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
clicked: function() {
|
|
||||||
this.openApp();
|
|
||||||
MessageTray.Source.prototype.clicked.call(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
setApp: function(app) {
|
|
||||||
this.app = app;
|
|
||||||
if (this._openAppRequested)
|
|
||||||
this.openApp();
|
|
||||||
},
|
|
||||||
|
|
||||||
openApp: function() {
|
|
||||||
if (this.app == null) {
|
|
||||||
this._openAppRequested = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let windows = this.app.get_windows();
|
|
||||||
if (windows.length > 0) {
|
|
||||||
let mostRecentWindow = windows[0];
|
|
||||||
Main.activateWindow(mostRecentWindow);
|
|
||||||
}
|
|
||||||
this._openAppRequested = false;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,5 +1,6 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
@ -7,18 +8,19 @@ const Mainloop = imports.mainloop;
|
|||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const St = imports.gi.St;
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const AppDisplay = imports.ui.appDisplay;
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const DocDisplay = imports.ui.docDisplay;
|
const DocDisplay = imports.ui.docDisplay;
|
||||||
const GenericDisplay = imports.ui.genericDisplay;
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
|
const Link = imports.ui.link;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const Dash = imports.ui.dash;
|
const Dash = imports.ui.dash;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const WorkspacesView = imports.ui.workspacesView;
|
const Workspaces = imports.ui.workspaces;
|
||||||
|
|
||||||
|
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
|
||||||
|
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
|
||||||
|
|
||||||
// Time for initial animation going into Overview mode
|
// Time for initial animation going into Overview mode
|
||||||
const ANIMATION_TIME = 0.25;
|
const ANIMATION_TIME = 0.25;
|
||||||
@ -72,101 +74,10 @@ const SHADOW_WIDTH = 6;
|
|||||||
|
|
||||||
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
||||||
|
|
||||||
const INFO_BAR_HIDE_TIMEOUT = 10;
|
|
||||||
|
|
||||||
let wideScreen = false;
|
let wideScreen = false;
|
||||||
let displayGridColumnWidth = null;
|
let displayGridColumnWidth = null;
|
||||||
let displayGridRowHeight = null;
|
let displayGridRowHeight = null;
|
||||||
|
let addRemoveButtonSize = null;
|
||||||
function InfoBar() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
InfoBar.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.Bin({ style_class: 'info-bar-panel',
|
|
||||||
x_fill: true,
|
|
||||||
y_fill: false });
|
|
||||||
this._label = new St.Label();
|
|
||||||
this._undo = new St.Button({ style_class: 'info-bar-link-button' });
|
|
||||||
|
|
||||||
let bin = new St.Bin({ x_fill: false,
|
|
||||||
y_fill: false,
|
|
||||||
x_align: St.Align.MIDDLE,
|
|
||||||
y_align: St.Align.MIDDLE });
|
|
||||||
this.actor.set_child(bin);
|
|
||||||
|
|
||||||
let box = new St.BoxLayout({ style_class: 'info-bar' });
|
|
||||||
bin.set_child(box);
|
|
||||||
this._timeoutId = 0;
|
|
||||||
|
|
||||||
box.add(this._label, {'y-fill' : false, 'y-align' : St.Align.MIDDLE});
|
|
||||||
box.add(this._undo);
|
|
||||||
|
|
||||||
this.actor.set_opacity(0);
|
|
||||||
|
|
||||||
this._undoCallback = null;
|
|
||||||
this._undo.connect('clicked', Lang.bind(this, this._onUndoClicked));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onUndoClicked: function() {
|
|
||||||
Mainloop.source_remove(this._timeoutId);
|
|
||||||
this._timeoutId = 0;
|
|
||||||
|
|
||||||
if (this._undoCallback)
|
|
||||||
this._undoCallback();
|
|
||||||
this.actor.set_opacity(0);
|
|
||||||
this._undoCallback = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideDone: function() {
|
|
||||||
this._undoCallback = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_hide: function() {
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 0,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
onComplete: this._hideDone,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTimeout: function() {
|
|
||||||
this._timeoutId = 0;
|
|
||||||
this._hide();
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
setMessage: function(text, undoCallback, undoLabel) {
|
|
||||||
if (this._timeoutId)
|
|
||||||
Mainloop.source_remove(this._timeoutId);
|
|
||||||
|
|
||||||
this._timeout = false;
|
|
||||||
|
|
||||||
this._label.text = text;
|
|
||||||
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 255,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
time: ANIMATION_TIME
|
|
||||||
});
|
|
||||||
|
|
||||||
this._timeoutId = Mainloop.timeout_add_seconds(INFO_BAR_HIDE_TIMEOUT, Lang.bind(this, this._onTimeout));
|
|
||||||
|
|
||||||
if (undoLabel)
|
|
||||||
this._undo.label = undoLabel;
|
|
||||||
else
|
|
||||||
this._undo.label = _("Undo");
|
|
||||||
|
|
||||||
this._undoCallback = undoCallback;
|
|
||||||
if (undoCallback)
|
|
||||||
this._undo.show();
|
|
||||||
else
|
|
||||||
this._undo.hide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Overview() {
|
function Overview() {
|
||||||
this._init();
|
this._init();
|
||||||
@ -174,14 +85,9 @@ function Overview() {
|
|||||||
|
|
||||||
Overview.prototype = {
|
Overview.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this._group = new St.BoxLayout({ style_class: 'overview' });
|
this._group = new Clutter.Group();
|
||||||
this._group._delegate = this;
|
this._group._delegate = this;
|
||||||
|
|
||||||
this.infoBar = new InfoBar();
|
|
||||||
this._group.add_actor(this.infoBar.actor);
|
|
||||||
|
|
||||||
this._workspacesManager = null;
|
|
||||||
|
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.animationInProgress = false;
|
this.animationInProgress = false;
|
||||||
this._hideInProgress = false;
|
this._hideInProgress = false;
|
||||||
@ -205,7 +111,7 @@ Overview.prototype = {
|
|||||||
this._group.add_actor(this._transparentBackground);
|
this._group.add_actor(this._transparentBackground);
|
||||||
|
|
||||||
// Background color for the Overview
|
// Background color for the Overview
|
||||||
this._backOver = new St.Label();
|
this._backOver = new Clutter.Rectangle({ color: ROOT_OVERVIEW_COLOR });
|
||||||
this._group.add_actor(this._backOver);
|
this._group.add_actor(this._backOver);
|
||||||
|
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
@ -216,7 +122,9 @@ Overview.prototype = {
|
|||||||
this._group.add_actor(this._dash.actor);
|
this._group.add_actor(this._dash.actor);
|
||||||
|
|
||||||
// Container to hold popup pane chrome.
|
// Container to hold popup pane chrome.
|
||||||
this._paneContainer = new St.BoxLayout({ style_class: 'overview-pane' });
|
this._paneContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
spacing: 6
|
||||||
|
});
|
||||||
// Note here we explicitly don't set the paneContainer to be reactive yet; that's done
|
// Note here we explicitly don't set the paneContainer to be reactive yet; that's done
|
||||||
// inside the notify::visible handler on panes.
|
// inside the notify::visible handler on panes.
|
||||||
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
|
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
|
||||||
@ -226,117 +134,79 @@ Overview.prototype = {
|
|||||||
this._group.add_actor(this._paneContainer);
|
this._group.add_actor(this._paneContainer);
|
||||||
|
|
||||||
this._transparentBackground.lower_bottom();
|
this._transparentBackground.lower_bottom();
|
||||||
this._paneContainer.hide();
|
this._paneContainer.lower_bottom();
|
||||||
|
|
||||||
this._coverPane.lower_bottom();
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
this.workspaces = null;
|
this._workspaces = null;
|
||||||
},
|
|
||||||
|
|
||||||
_onViewChanged: function() {
|
|
||||||
if (!this.visible)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.workspaces = this._workspacesManager.workspacesView;
|
|
||||||
|
|
||||||
// Show new workspacesView
|
|
||||||
this._group.add_actor(this.workspaces.actor);
|
|
||||||
this._workspacesBar.raise(this.workspaces.actor);
|
|
||||||
this._dash.actor.raise(this.workspaces.actor);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_recalculateGridSizes: function () {
|
_recalculateGridSizes: function () {
|
||||||
let primary = global.get_primary_monitor();
|
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO) &&
|
||||||
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
|
(global.screen_height >= WIDE_SCREEN_MINIMUM_HEIGHT);
|
||||||
(primary.height >= WIDE_SCREEN_MINIMUM_HEIGHT);
|
|
||||||
|
|
||||||
// We divide the screen into an imaginary grid which helps us determine the layout of
|
// We divide the screen into an imaginary grid which helps us determine the layout of
|
||||||
// different visual components.
|
// different visual components.
|
||||||
if (wideScreen) {
|
if (wideScreen) {
|
||||||
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_WIDE_SCREEN);
|
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
|
||||||
displayGridRowHeight = Math.floor(primary.height / ROWS_WIDE_SCREEN);
|
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
|
||||||
} else {
|
} else {
|
||||||
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_REGULAR_SCREEN);
|
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
|
||||||
displayGridRowHeight = Math.floor(primary.height / ROWS_REGULAR_SCREEN);
|
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
relayout: function () {
|
relayout: function () {
|
||||||
let primary = global.get_primary_monitor();
|
let screenHeight = global.screen_height;
|
||||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
let screenWidth = global.screen_width;
|
||||||
|
|
||||||
this._recalculateGridSizes();
|
|
||||||
|
|
||||||
this._group.set_position(primary.x, primary.y);
|
|
||||||
|
|
||||||
let contentY = Panel.PANEL_HEIGHT;
|
let contentY = Panel.PANEL_HEIGHT;
|
||||||
let contentHeight = primary.height - contentY;
|
let contentHeight = screenHeight - contentY;
|
||||||
|
|
||||||
this._coverPane.set_position(0, contentY);
|
this._coverPane.set_position(0, contentY);
|
||||||
this._coverPane.set_size(primary.width, contentHeight);
|
this._coverPane.set_size(screenWidth, contentHeight);
|
||||||
|
|
||||||
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||||
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||||
|
|
||||||
this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
|
this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
|
||||||
- WORKSPACE_GRID_PADDING * 2;
|
- WORKSPACE_GRID_PADDING * 2;
|
||||||
// We scale the vertical padding by (primary.height / primary.width)
|
// We scale the vertical padding by (screenHeight / screenWidth)
|
||||||
// so that the workspace preserves its aspect ratio.
|
// so that the workspace preserves its aspect ratio.
|
||||||
this._workspacesHeight = Math.floor(displayGridRowHeight * workspaceRowsUsed
|
this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed
|
||||||
- WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2);
|
- WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
|
||||||
|
|
||||||
if (rtl) {
|
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
||||||
this._workspacesX = WORKSPACE_GRID_PADDING;
|
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
|
||||||
} else {
|
|
||||||
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
|
||||||
}
|
|
||||||
this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width));
|
|
||||||
|
|
||||||
if (rtl) {
|
|
||||||
this._dash.actor.set_position(primary.width - displayGridColumnWidth, contentY);
|
|
||||||
} else {
|
|
||||||
this._dash.actor.set_position(0, contentY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this._dash.actor.set_position(0, contentY);
|
||||||
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
|
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
|
||||||
this._dash.searchArea.height = this._workspacesY - contentY;
|
this._dash.searchArea.height = this._workspacesY - contentY;
|
||||||
this._dash.sectionArea.height = this._workspacesHeight;
|
this._dash.sectionArea.height = this._workspacesHeight;
|
||||||
this._dash.searchResults.actor.height = this._workspacesHeight;
|
|
||||||
|
|
||||||
this.infoBar.actor.set_position(displayGridColumnWidth, Panel.PANEL_HEIGHT);
|
|
||||||
this.infoBar.actor.set_size(primary.width - displayGridColumnWidth, this._workspacesY - Panel.PANEL_HEIGHT);
|
|
||||||
this.infoBar.actor.raise_top();
|
|
||||||
|
|
||||||
// place the 'Add Workspace' button in the bottom row of the grid
|
// place the 'Add Workspace' button in the bottom row of the grid
|
||||||
this._workspacesBarX = this._workspacesX;
|
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
||||||
this._workspacesBarWidth = this._workspacesWidth;
|
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
|
||||||
this._workspacesBarY = primary.height - displayGridRowHeight;
|
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
|
||||||
|
|
||||||
// The parent (this._group) is positioned at the top left of the primary monitor
|
this._backOver.set_position(0, contentY);
|
||||||
// while this._backOver occupies the entire screen.
|
this._backOver.set_size(global.screen_width, contentHeight);
|
||||||
this._backOver.set_position(- primary.x, - primary.y);
|
|
||||||
this._backOver.set_size(global.screen_width, global.screen_height);
|
|
||||||
|
|
||||||
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
||||||
this._workspacesY);
|
contentY);
|
||||||
// Dynamic width
|
// Dynamic width
|
||||||
this._paneContainer.height = this._workspacesHeight;
|
this._paneContainer.height = contentHeight;
|
||||||
if (rtl) {
|
|
||||||
this._paneContainer.connect('notify::width', Lang.bind(this, function (paneContainer) {
|
|
||||||
paneContainer.x = this._dash.actor.x - (DEFAULT_PADDING + paneContainer.width);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._transparentBackground.set_position(primary.x, primary.y);
|
this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y);
|
||||||
this._transparentBackground.set_size(primary.width, primary.height);
|
this._transparentBackground.set_size(global.screen_width - this._paneContainer.x,
|
||||||
|
this._paneContainer.height);
|
||||||
|
|
||||||
|
if (this._activeDisplayPane != null)
|
||||||
|
this._activeDisplayPane.actor.width = displayGridColumnWidth * 2;
|
||||||
},
|
},
|
||||||
|
|
||||||
addPane: function (pane, align) {
|
addPane: function (pane) {
|
||||||
pane.actor.height = .9 * this._workspacesHeight;
|
this._paneContainer.append(pane.actor, Big.BoxPackFlags.NONE);
|
||||||
this._paneContainer.add(pane.actor, { expand: true,
|
|
||||||
y_fill: false,
|
|
||||||
y_align: align });
|
|
||||||
// When a pane is displayed, we raise the transparent background to the top
|
// When a pane is displayed, we raise the transparent background to the top
|
||||||
// and connect to button-release-event on it, then raise the pane above that.
|
// and connect to button-release-event on it, then raise the pane above that.
|
||||||
// The idea here is that clicking anywhere outside the pane should close it.
|
// The idea here is that clicking anywhere outside the pane should close it.
|
||||||
@ -344,24 +214,16 @@ Overview.prototype = {
|
|||||||
let backgroundEventId = null;
|
let backgroundEventId = null;
|
||||||
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
|
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
|
pane.actor.width = displayGridColumnWidth * 2;
|
||||||
this._activeDisplayPane = pane;
|
this._activeDisplayPane = pane;
|
||||||
this._transparentBackground.raise_top();
|
this._transparentBackground.raise_top();
|
||||||
this._paneContainer.raise_top();
|
this._paneContainer.raise_top();
|
||||||
this._paneContainer.show();
|
|
||||||
this._paneReady = false;
|
|
||||||
if (backgroundEventId != null)
|
if (backgroundEventId != null)
|
||||||
this._transparentBackground.disconnect(backgroundEventId);
|
this._transparentBackground.disconnect(backgroundEventId);
|
||||||
backgroundEventId = this._transparentBackground.connect('captured-event', Lang.bind(this, function (actor, event) {
|
backgroundEventId = this._transparentBackground.connect('button-release-event', Lang.bind(this, function () {
|
||||||
if (event.get_source() != this._transparentBackground)
|
this._activeDisplayPane.close();
|
||||||
return false;
|
|
||||||
if (event.type() == Clutter.EventType.BUTTON_PRESS)
|
|
||||||
this._paneReady = true;
|
|
||||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE
|
|
||||||
&& this._paneReady)
|
|
||||||
this._activeDisplayPane.close();
|
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
this.workspaces.actor.opacity = 64;
|
|
||||||
} else if (pane == this._activeDisplayPane) {
|
} else if (pane == this._activeDisplayPane) {
|
||||||
this._activeDisplayPane = null;
|
this._activeDisplayPane = null;
|
||||||
if (backgroundEventId != null) {
|
if (backgroundEventId != null) {
|
||||||
@ -369,8 +231,7 @@ Overview.prototype = {
|
|||||||
backgroundEventId = null;
|
backgroundEventId = null;
|
||||||
}
|
}
|
||||||
this._transparentBackground.lower_bottom();
|
this._transparentBackground.lower_bottom();
|
||||||
this._paneContainer.hide();
|
this._paneContainer.lower_bottom();
|
||||||
this.workspaces.actor.opacity = 255;
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -382,7 +243,7 @@ Overview.prototype = {
|
|||||||
// This allows the user to place the item on any workspace.
|
// This allows the user to place the item on any workspace.
|
||||||
handleDragOver : function(source, actor, x, y, time) {
|
handleDragOver : function(source, actor, x, y, time) {
|
||||||
if (source instanceof GenericDisplay.GenericDisplayItem
|
if (source instanceof GenericDisplay.GenericDisplayItem
|
||||||
|| source instanceof AppDisplay.AppIcon) {
|
|| source instanceof AppDisplay.BaseWellItem) {
|
||||||
if (this._activeDisplayPane != null)
|
if (this._activeDisplayPane != null)
|
||||||
this._activeDisplayPane.close();
|
this._activeDisplayPane.close();
|
||||||
return true;
|
return true;
|
||||||
@ -396,13 +257,13 @@ Overview.prototype = {
|
|||||||
// Returns the scale the Overview has when we just start zooming out
|
// Returns the scale the Overview has when we just start zooming out
|
||||||
// to overview mode. That is, when just the active workspace is showing.
|
// to overview mode. That is, when just the active workspace is showing.
|
||||||
getZoomedInScale : function() {
|
getZoomedInScale : function() {
|
||||||
return 1 / this.workspaces.getScale();
|
return 1 / this._workspaces.getScale();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the position the Overview has when we just start zooming out
|
// Returns the position the Overview has when we just start zooming out
|
||||||
// to overview mode. That is, when just the active workspace is showing.
|
// to overview mode. That is, when just the active workspace is showing.
|
||||||
getZoomedInPosition : function() {
|
getZoomedInPosition : function() {
|
||||||
let [posX, posY] = this.workspaces.getActiveWorkspacePosition();
|
let [posX, posY] = this._workspaces.getActiveWorkspacePosition();
|
||||||
let scale = this.getZoomedInScale();
|
let scale = this.getZoomedInScale();
|
||||||
|
|
||||||
return [- posX * scale, - posY * scale];
|
return [- posX * scale, - posY * scale];
|
||||||
@ -430,28 +291,20 @@ Overview.prototype = {
|
|||||||
this._dash.show();
|
this._dash.show();
|
||||||
|
|
||||||
/* TODO: make this stuff dynamic */
|
/* TODO: make this stuff dynamic */
|
||||||
this._workspacesManager =
|
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
|
||||||
new WorkspacesView.WorkspacesManager(this._workspacesWidth,
|
this._workspacesX, this._workspacesY);
|
||||||
this._workspacesHeight,
|
this._group.add_actor(this._workspaces.actor);
|
||||||
this._workspacesX,
|
|
||||||
this._workspacesY);
|
|
||||||
this._workspacesManager.connect('view-changed',
|
|
||||||
Lang.bind(this, this._onViewChanged));
|
|
||||||
this.workspaces = this._workspacesManager.workspacesView;
|
|
||||||
this._group.add_actor(this.workspaces.actor);
|
|
||||||
|
|
||||||
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
||||||
// for drag and drop to work. In the future we should fix the workspaces to not
|
// for drag and drop to work. In the future we should fix the workspaces to not
|
||||||
// be as big as the screen.
|
// be as big as the screen.
|
||||||
this._dash.actor.raise(this.workspaces.actor);
|
this._dash.actor.raise(this._workspaces.actor);
|
||||||
|
|
||||||
this._workspacesBar = this._workspacesManager.controlsBar.actor;
|
// Create (+) button
|
||||||
this._workspacesBar.set_position(this._workspacesBarX,
|
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
|
||||||
this._workspacesBarY);
|
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
|
||||||
this._workspacesBar.width = this._workspacesBarWidth;
|
this._group.add_actor(this._addButton.actor);
|
||||||
|
this._addButton.actor.raise(this._workspaces.actor);
|
||||||
this._group.add_actor(this._workspacesBar);
|
|
||||||
this._workspacesBar.raise(this.workspaces.actor);
|
|
||||||
|
|
||||||
// All the the actors in the window group are completely obscured,
|
// All the the actors in the window group are completely obscured,
|
||||||
// hiding the group holding them while the Overview is displayed greatly
|
// hiding the group holding them while the Overview is displayed greatly
|
||||||
@ -469,10 +322,9 @@ Overview.prototype = {
|
|||||||
// The opposite transition is used in hide().
|
// The opposite transition is used in hide().
|
||||||
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
|
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
|
||||||
[this._group.x, this._group.y] = this.getZoomedInPosition();
|
[this._group.x, this._group.y] = this.getZoomedInPosition();
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
Tweener.addTween(this._group,
|
Tweener.addTween(this._group,
|
||||||
{ x: primary.x,
|
{ x: 0,
|
||||||
y: primary.y,
|
y: 0,
|
||||||
scaleX: 1,
|
scaleX: 1,
|
||||||
scaleY: 1,
|
scaleY: 1,
|
||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad',
|
||||||
@ -481,7 +333,7 @@ Overview.prototype = {
|
|||||||
onCompleteScope: this
|
onCompleteScope: this
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make Dash fade in so that it doesn't appear too big.
|
// Make Dash fade in so that it doesn't appear to big.
|
||||||
this._dash.actor.opacity = 0;
|
this._dash.actor.opacity = 0;
|
||||||
Tweener.addTween(this._dash.actor,
|
Tweener.addTween(this._dash.actor,
|
||||||
{ opacity: 255,
|
{ opacity: 255,
|
||||||
@ -501,7 +353,7 @@ Overview.prototype = {
|
|||||||
this._hideInProgress = true;
|
this._hideInProgress = true;
|
||||||
if (this._activeDisplayPane != null)
|
if (this._activeDisplayPane != null)
|
||||||
this._activeDisplayPane.close();
|
this._activeDisplayPane.close();
|
||||||
this.workspaces.hide();
|
this._workspaces.hide();
|
||||||
|
|
||||||
// Create a zoom in effect by transforming the Overview group so that
|
// Create a zoom in effect by transforming the Overview group so that
|
||||||
// the active workspace fills up the whole screen. The opposite
|
// the active workspace fills up the whole screen. The opposite
|
||||||
@ -546,7 +398,21 @@ Overview.prototype = {
|
|||||||
* and will return %null.
|
* and will return %null.
|
||||||
*/
|
*/
|
||||||
getWorkspacesForWindow: function(metaWindow) {
|
getWorkspacesForWindow: function(metaWindow) {
|
||||||
return this.workspaces;
|
return this._workspaces;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* activateWindow:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
* @time: Event timestamp integer
|
||||||
|
*
|
||||||
|
* Make the given MetaWindow be the focus window, switching
|
||||||
|
* to the workspace it's on if necessary. This function
|
||||||
|
* should only be used when the Overview is currently active;
|
||||||
|
* outside of that, use the relevant methods on MetaDisplay.
|
||||||
|
*/
|
||||||
|
activateWindow: function (metaWindow, time) {
|
||||||
|
this._workspaces.activateWindowFromOverview(metaWindow, time);
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
@ -564,13 +430,8 @@ Overview.prototype = {
|
|||||||
_hideDone: function() {
|
_hideDone: function() {
|
||||||
global.window_group.show();
|
global.window_group.show();
|
||||||
|
|
||||||
this.workspaces.destroy();
|
this._workspaces.destroy();
|
||||||
this.workspaces = null;
|
this._workspaces = null;
|
||||||
|
|
||||||
this._workspacesBar.destroy();
|
|
||||||
this._workspacesBar = null;
|
|
||||||
|
|
||||||
this._workspacesManager = null;
|
|
||||||
|
|
||||||
this._dash.hide();
|
this._dash.hide();
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
@ -583,6 +444,43 @@ Overview.prototype = {
|
|||||||
|
|
||||||
Main.popModal(this._dash.actor);
|
Main.popModal(this._dash.actor);
|
||||||
this.emit('hidden');
|
this.emit('hidden');
|
||||||
|
},
|
||||||
|
|
||||||
|
_addNewWorkspace: function() {
|
||||||
|
global.screen.append_new_workspace(false, Main.currentTime());
|
||||||
|
},
|
||||||
|
|
||||||
|
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||||
|
this._addNewWorkspace();
|
||||||
|
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(Overview.prototype);
|
Signals.addSignalMethods(Overview.prototype);
|
||||||
|
|
||||||
|
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||||
|
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddWorkspaceButton.prototype = {
|
||||||
|
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||||
|
this.actor = new Clutter.Group({ x: buttonX,
|
||||||
|
y: buttonY,
|
||||||
|
width: global.screen_width - buttonX,
|
||||||
|
height: global.screen_height - buttonY,
|
||||||
|
reactive: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
this._acceptDropCallback = acceptDropCallback;
|
||||||
|
|
||||||
|
let plus = new Clutter.Texture({ x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: buttonSize,
|
||||||
|
height: buttonSize });
|
||||||
|
plus.set_from_file(global.imagedir + 'add-workspace.svg');
|
||||||
|
this.actor.add_actor(plus);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Draggable target interface
|
||||||
|
acceptDrop: function(source, actor, x, y, time) {
|
||||||
|
return this._acceptDropCallback(source, actor, x, y, time);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
1274
js/ui/panel.js
@ -1,598 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const DND = imports.ui.dnd;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Search = imports.ui.search;
|
|
||||||
|
|
||||||
const NAUTILUS_PREFS_DIR = '/apps/nautilus/preferences';
|
|
||||||
const DESKTOP_IS_HOME_KEY = NAUTILUS_PREFS_DIR + '/desktop_is_home_dir';
|
|
||||||
|
|
||||||
const PLACES_ICON_SIZE = 16;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a place object, which is most normally a bookmark entry,
|
|
||||||
* a mount/volume, or a special place like the Home Folder, Computer, and Network.
|
|
||||||
*
|
|
||||||
* @name: String title
|
|
||||||
* @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
|
|
||||||
* @launch: A JavaScript callback to launch the entry
|
|
||||||
*/
|
|
||||||
function PlaceInfo(id, name, iconFactory, launch) {
|
|
||||||
this._init(id, name, iconFactory, launch);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceInfo.prototype = {
|
|
||||||
_init: function(id, name, iconFactory, launch) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this._lowerName = name.toLowerCase();
|
|
||||||
this.iconFactory = iconFactory;
|
|
||||||
this.launch = launch;
|
|
||||||
},
|
|
||||||
|
|
||||||
matchTerms: function(terms) {
|
|
||||||
let mtype = Search.MatchType.NONE;
|
|
||||||
for (let i = 0; i < terms.length; i++) {
|
|
||||||
let term = terms[i];
|
|
||||||
let idx = this._lowerName.indexOf(term);
|
|
||||||
if (idx == 0)
|
|
||||||
return Search.MatchType.PREFIX;
|
|
||||||
else if (idx > 0)
|
|
||||||
mtype = Search.MatchType.SUBSTRING;
|
|
||||||
}
|
|
||||||
return mtype;
|
|
||||||
},
|
|
||||||
|
|
||||||
isRemovable: function() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function PlaceDeviceInfo(mount) {
|
|
||||||
this._init(mount);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceDeviceInfo.prototype = {
|
|
||||||
__proto__: PlaceInfo.prototype,
|
|
||||||
|
|
||||||
_init: function(mount) {
|
|
||||||
this._mount = mount;
|
|
||||||
this.name = mount.get_name();
|
|
||||||
this._lowerName = this.name.toLowerCase();
|
|
||||||
this.id = 'mount:' + mount.get_root().get_uri();
|
|
||||||
},
|
|
||||||
|
|
||||||
iconFactory: function(size) {
|
|
||||||
let icon = this._mount.get_icon();
|
|
||||||
return St.TextureCache.get_default().load_gicon(icon, size);
|
|
||||||
},
|
|
||||||
|
|
||||||
launch: function() {
|
|
||||||
Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
|
|
||||||
global.create_app_launch_context());
|
|
||||||
},
|
|
||||||
|
|
||||||
isRemovable: function() {
|
|
||||||
return this._mount.can_unmount();
|
|
||||||
},
|
|
||||||
|
|
||||||
remove: function() {
|
|
||||||
if (!this.isRemovable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._mount.can_eject())
|
|
||||||
this._mount.eject(0, null, Lang.bind(this, this._removeFinish));
|
|
||||||
else
|
|
||||||
this._mount.unmount(0, null, Lang.bind(this, this._removeFinish));
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeFinish: function(o, res, data) {
|
|
||||||
try {
|
|
||||||
if (this._mount.can_eject())
|
|
||||||
this._mount.eject_finish(res);
|
|
||||||
else
|
|
||||||
this._mount.unmount_finish(res);
|
|
||||||
} catch (e) {
|
|
||||||
let message = _("Failed to unmount '%s'").format(o.get_name());
|
|
||||||
Main.overview.infoBar.setMessage(message,
|
|
||||||
Lang.bind(this, this.remove),
|
|
||||||
_("Retry"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function PlacesManager() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
PlacesManager.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
let gconf = Shell.GConf.get_default();
|
|
||||||
gconf.watch_directory(NAUTILUS_PREFS_DIR);
|
|
||||||
|
|
||||||
this._defaultPlaces = [];
|
|
||||||
this._mounts = [];
|
|
||||||
this._bookmarks = [];
|
|
||||||
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
|
|
||||||
|
|
||||||
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
|
|
||||||
let homeUri = homeFile.get_uri();
|
|
||||||
let homeLabel = Shell.util_get_label_for_uri (homeUri);
|
|
||||||
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
|
|
||||||
this._home = new PlaceInfo('special:home', homeLabel,
|
|
||||||
function(size) {
|
|
||||||
return St.TextureCache.get_default().load_gicon(homeIcon, size);
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context());
|
|
||||||
});
|
|
||||||
|
|
||||||
let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
|
|
||||||
let desktopFile = Gio.file_new_for_path (desktopPath);
|
|
||||||
let desktopUri = desktopFile.get_uri();
|
|
||||||
let desktopLabel = Shell.util_get_label_for_uri (desktopUri);
|
|
||||||
let desktopIcon = Shell.util_get_icon_for_uri (desktopUri);
|
|
||||||
this._desktopMenu = new PlaceInfo('special:desktop', desktopLabel,
|
|
||||||
function(size) {
|
|
||||||
return St.TextureCache.get_default().load_gicon(desktopIcon, size);
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context());
|
|
||||||
});
|
|
||||||
|
|
||||||
this._connect = new PlaceInfo('special:connect', _("Connect to..."),
|
|
||||||
function (size) {
|
|
||||||
return St.TextureCache.get_default().load_icon_name('applications-internet', size);
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
|
|
||||||
});
|
|
||||||
|
|
||||||
let networkApp = null;
|
|
||||||
try {
|
|
||||||
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
|
|
||||||
} catch(e) {
|
|
||||||
try {
|
|
||||||
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop');
|
|
||||||
} catch(e) {
|
|
||||||
log('Cannot create "Network" item, .desktop file not found or corrupt.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkApp != null) {
|
|
||||||
this._network = new PlaceInfo('special:network', networkApp.get_name(),
|
|
||||||
function(size) {
|
|
||||||
return networkApp.create_icon_texture(size);
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
networkApp.launch();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this._defaultPlaces.push(this._home);
|
|
||||||
|
|
||||||
this._desktopMenuIndex = this._defaultPlaces.length;
|
|
||||||
if (!this._isDesktopHome)
|
|
||||||
this._defaultPlaces.push(this._desktopMenu);
|
|
||||||
|
|
||||||
if (this._network)
|
|
||||||
this._defaultPlaces.push(this._network);
|
|
||||||
|
|
||||||
this._defaultPlaces.push(this._connect);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show devices, code more or less ported from nautilus-places-sidebar.c
|
|
||||||
*/
|
|
||||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
|
||||||
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._updateDevices();
|
|
||||||
|
|
||||||
this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']);
|
|
||||||
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
|
|
||||||
let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
|
|
||||||
this._bookmarkTimeoutId = 0;
|
|
||||||
monitor.connect('changed', Lang.bind(this, function () {
|
|
||||||
if (this._bookmarkTimeoutId > 0)
|
|
||||||
return;
|
|
||||||
/* Defensive event compression */
|
|
||||||
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
|
|
||||||
this._bookmarkTimeoutId = 0;
|
|
||||||
this._reloadBookmarks();
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._reloadBookmarks();
|
|
||||||
|
|
||||||
gconf.connect('changed::' + DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility));
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateDevices: function() {
|
|
||||||
this._mounts = [];
|
|
||||||
|
|
||||||
/* first go through all connected drives */
|
|
||||||
let drives = this._volumeMonitor.get_connected_drives();
|
|
||||||
for (let i = 0; i < drives.length; i++) {
|
|
||||||
let volumes = drives[i].get_volumes();
|
|
||||||
for(let j = 0; j < volumes.length; j++) {
|
|
||||||
let mount = volumes[j].get_mount();
|
|
||||||
if(mount != null) {
|
|
||||||
this._addMount(mount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add all volumes that is not associated with a drive */
|
|
||||||
let volumes = this._volumeMonitor.get_volumes();
|
|
||||||
for(let i = 0; i < volumes.length; i++) {
|
|
||||||
if(volumes[i].get_drive() != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let mount = volumes[i].get_mount();
|
|
||||||
if(mount != null) {
|
|
||||||
this._addMount(mount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
|
|
||||||
let mounts = this._volumeMonitor.get_mounts();
|
|
||||||
for(let i = 0; i < mounts.length; i++) {
|
|
||||||
if(mounts[i].is_shadowed())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(mounts[i].get_volume())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this._addMount(mounts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We emit two signals, one for a generic 'all places' update
|
|
||||||
* and the other for one specific to mounts. We do this because
|
|
||||||
* clients like PlaceDisplay may only care about places in general
|
|
||||||
* being updated while clients like DashPlaceDisplay care which
|
|
||||||
* specific type of place got updated.
|
|
||||||
*/
|
|
||||||
this.emit('mounts-updated');
|
|
||||||
this.emit('places-updated');
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_reloadBookmarks: function() {
|
|
||||||
|
|
||||||
this._bookmarks = [];
|
|
||||||
|
|
||||||
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let bookmarks = bookmarksContent.split('\n');
|
|
||||||
|
|
||||||
let bookmarksToLabel = {};
|
|
||||||
let bookmarksOrder = [];
|
|
||||||
for (let i = 0; i < bookmarks.length; i++) {
|
|
||||||
let bookmarkLine = bookmarks[i];
|
|
||||||
let components = bookmarkLine.split(' ');
|
|
||||||
let bookmark = components[0];
|
|
||||||
if (bookmark in bookmarksToLabel)
|
|
||||||
continue;
|
|
||||||
let label = null;
|
|
||||||
if (components.length > 1)
|
|
||||||
label = components.slice(1).join(' ');
|
|
||||||
bookmarksToLabel[bookmark] = label;
|
|
||||||
bookmarksOrder.push(bookmark);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < bookmarksOrder.length; i++) {
|
|
||||||
let bookmark = bookmarksOrder[i];
|
|
||||||
let label = bookmarksToLabel[bookmark];
|
|
||||||
let file = Gio.file_new_for_uri(bookmark);
|
|
||||||
if (!file.query_exists(null))
|
|
||||||
continue;
|
|
||||||
if (label == null)
|
|
||||||
label = Shell.util_get_label_for_uri(bookmark);
|
|
||||||
if (label == null)
|
|
||||||
continue;
|
|
||||||
let icon = Shell.util_get_icon_for_uri(bookmark);
|
|
||||||
|
|
||||||
let item = new PlaceInfo('bookmark:' + bookmark, label,
|
|
||||||
function(size) {
|
|
||||||
return St.TextureCache.get_default().load_gicon(icon, size);
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context());
|
|
||||||
});
|
|
||||||
this._bookmarks.push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See comment in _updateDevices for explanation why there are two signals. */
|
|
||||||
this.emit('bookmarks-updated');
|
|
||||||
this.emit('places-updated');
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateDesktopMenuVisibility: function() {
|
|
||||||
let gconf = Shell.GConf.get_default();
|
|
||||||
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
|
|
||||||
|
|
||||||
if (this._isDesktopHome)
|
|
||||||
this._removeById(this._defaultPlaces, 'special:desktop');
|
|
||||||
else
|
|
||||||
this._defaultPlaces.splice(this._desktopMenuIndex, 0,
|
|
||||||
this._desktopMenu);
|
|
||||||
|
|
||||||
/* See comment in _updateDevices for explanation why there are two signals. */
|
|
||||||
this.emit('defaults-updated');
|
|
||||||
this.emit('places-updated');
|
|
||||||
},
|
|
||||||
|
|
||||||
_addMount: function(mount) {
|
|
||||||
let devItem = new PlaceDeviceInfo(mount);
|
|
||||||
this._mounts.push(devItem);
|
|
||||||
},
|
|
||||||
|
|
||||||
getAllPlaces: function () {
|
|
||||||
return this.getDefaultPlaces().concat(this.getBookmarks(), this.getMounts());
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultPlaces: function () {
|
|
||||||
return this._defaultPlaces;
|
|
||||||
},
|
|
||||||
|
|
||||||
getBookmarks: function () {
|
|
||||||
return this._bookmarks;
|
|
||||||
},
|
|
||||||
|
|
||||||
getMounts: function () {
|
|
||||||
return this._mounts;
|
|
||||||
},
|
|
||||||
|
|
||||||
_lookupIndexById: function(sourceArray, id) {
|
|
||||||
for (let i = 0; i < sourceArray.length; i++) {
|
|
||||||
let place = sourceArray[i];
|
|
||||||
if (place.id == id)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
lookupPlaceById: function(id) {
|
|
||||||
let colonIdx = id.indexOf(':');
|
|
||||||
let type = id.substring(0, colonIdx);
|
|
||||||
let sourceArray = null;
|
|
||||||
if (type == 'special')
|
|
||||||
sourceArray = this._defaultPlaces;
|
|
||||||
else if (type == 'mount')
|
|
||||||
sourceArray = this._mounts;
|
|
||||||
else if (type == 'bookmark')
|
|
||||||
sourceArray = this._bookmarks;
|
|
||||||
return sourceArray[this._lookupIndexById(sourceArray, id)];
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeById: function(sourceArray, id) {
|
|
||||||
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Signals.addSignalMethods(PlacesManager.prototype);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entry in the places menu.
|
|
||||||
* @info The corresponding PlaceInfo to populate this entry.
|
|
||||||
*/
|
|
||||||
function DashPlaceDisplayItem(info) {
|
|
||||||
this._init(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
DashPlaceDisplayItem.prototype = {
|
|
||||||
_init: function(info) {
|
|
||||||
this.name = info.name;
|
|
||||||
this._info = info;
|
|
||||||
this._icon = info.iconFactory(PLACES_ICON_SIZE);
|
|
||||||
|
|
||||||
this.actor = new St.Clickable({ style_class: 'places-item',
|
|
||||||
reactive: true,
|
|
||||||
x_align: St.Align.START,
|
|
||||||
x_fill: true });
|
|
||||||
|
|
||||||
let box = new St.BoxLayout({ style_class: 'places-item-box' });
|
|
||||||
this.actor.set_child(box);
|
|
||||||
|
|
||||||
let bin = new St.Bin({ child: this._icon });
|
|
||||||
box.add(bin);
|
|
||||||
|
|
||||||
let text = new St.Label({ text: info.name });
|
|
||||||
box.add(text, { expand: true, x_fill: true });
|
|
||||||
|
|
||||||
if (info.isRemovable()) {
|
|
||||||
let removeIcon = St.TextureCache.get_default().load_icon_name ('media-eject', PLACES_ICON_SIZE);
|
|
||||||
let removeIconBox = new St.Clickable({ child: removeIcon,
|
|
||||||
reactive: true });
|
|
||||||
box.add(removeIconBox);
|
|
||||||
removeIconBox.connect('clicked',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
this._info.remove();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
|
||||||
|
|
||||||
this.actor._delegate = this;
|
|
||||||
this._draggable = DND.makeDraggable(this.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClicked: function(b) {
|
|
||||||
this._info.launch();
|
|
||||||
Main.overview.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
getDragActorSource: function() {
|
|
||||||
return this._icon;
|
|
||||||
},
|
|
||||||
|
|
||||||
getDragActor: function(stageX, stageY) {
|
|
||||||
return this._info.iconFactory(PLACES_ICON_SIZE);
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Drag and drop methods ////
|
|
||||||
|
|
||||||
shellWorkspaceLaunch: function() {
|
|
||||||
this._info.launch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function DashPlaceDisplay() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
DashPlaceDisplay.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
|
|
||||||
// Places is divided semi-arbitrarily into left and right; a grid would
|
|
||||||
// look better in that there would be an even number of items left+right,
|
|
||||||
// but it seems like we want some sort of differentiation between actions
|
|
||||||
// like "Connect to server..." and regular folders
|
|
||||||
this.actor = new St.Table({ style_class: 'places-section',
|
|
||||||
homogeneous: true });
|
|
||||||
|
|
||||||
this._defaultsList = [];
|
|
||||||
this._bookmarksList = [];
|
|
||||||
this._mountsList = [];
|
|
||||||
|
|
||||||
Main.placesManager.connect('defaults-updated', Lang.bind(this, this._updateDefaults));
|
|
||||||
Main.placesManager.connect('bookmarks-updated', Lang.bind(this, this._updateBookmarks));
|
|
||||||
Main.placesManager.connect('mounts-updated', Lang.bind(this, this._updateMounts));
|
|
||||||
|
|
||||||
this._updateDefaults();
|
|
||||||
this._updateMounts();
|
|
||||||
this._updateBookmarks();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateDefaults: function() {
|
|
||||||
for (let i = 0; i < this._defaultsList.length; i++)
|
|
||||||
this._defaultsList[i].destroy();
|
|
||||||
|
|
||||||
this._defaultsList = [];
|
|
||||||
let places = Main.placesManager.getDefaultPlaces();
|
|
||||||
for (let i = 0; i < places.length; i++) {
|
|
||||||
this._defaultsList[i] = new DashPlaceDisplayItem(places[i]).actor;
|
|
||||||
this.actor.add(this._defaultsList[i], {row: i, col: 0});
|
|
||||||
}
|
|
||||||
this._updateMounts();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateMounts: function() {
|
|
||||||
for (let i = 0; i < this._mountsList.length; i++)
|
|
||||||
this._mountsList[i].destroy();
|
|
||||||
|
|
||||||
this._mountsList = [];
|
|
||||||
let places = Main.placesManager.getMounts();
|
|
||||||
for (let i = 0; i < places.length; i++) {
|
|
||||||
this._mountsList[i] = new DashPlaceDisplayItem(places[i]).actor;
|
|
||||||
this.actor.add(this._mountsList[i], {row: this._defaultsList.length + i, col: 0});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateBookmarks: function() {
|
|
||||||
for (let i = 0; i < this._bookmarksList.length; i++)
|
|
||||||
this._bookmarksList[i].destroy();
|
|
||||||
|
|
||||||
this._bookmarksList = [];
|
|
||||||
let places = Main.placesManager.getBookmarks();
|
|
||||||
for (let i = 0; i < places.length; i ++) {
|
|
||||||
this._bookmarksList[i] = new DashPlaceDisplayItem(places[i]).actor;
|
|
||||||
this.actor.add(this._bookmarksList[i], {row: i, col: 1});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Signals.addSignalMethods(DashPlaceDisplay.prototype);
|
|
||||||
|
|
||||||
function PlaceSearchProvider() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceSearchProvider.prototype = {
|
|
||||||
__proto__: Search.SearchProvider.prototype,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
|
|
||||||
},
|
|
||||||
|
|
||||||
getResultMeta: function(resultId) {
|
|
||||||
let placeInfo = Main.placesManager.lookupPlaceById(resultId);
|
|
||||||
if (!placeInfo)
|
|
||||||
return null;
|
|
||||||
return { 'id': resultId,
|
|
||||||
'name': placeInfo.name,
|
|
||||||
'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) };
|
|
||||||
},
|
|
||||||
|
|
||||||
activateResult: function(id) {
|
|
||||||
let placeInfo = Main.placesManager.lookupPlaceById(id);
|
|
||||||
placeInfo.launch();
|
|
||||||
},
|
|
||||||
|
|
||||||
_compareResultMeta: function (idA, idB) {
|
|
||||||
let infoA = Main.placesManager.lookupPlaceById(idA);
|
|
||||||
let infoB = Main.placesManager.lookupPlaceById(idB);
|
|
||||||
return infoA.name.localeCompare(infoB.name);
|
|
||||||
},
|
|
||||||
|
|
||||||
_searchPlaces: function(places, terms) {
|
|
||||||
let multipleResults = [];
|
|
||||||
let prefixResults = [];
|
|
||||||
let substringResults = [];
|
|
||||||
|
|
||||||
terms = terms.map(String.toLowerCase);
|
|
||||||
|
|
||||||
for (let i = 0; i < places.length; i++) {
|
|
||||||
let place = places[i];
|
|
||||||
let mtype = place.matchTerms(terms);
|
|
||||||
if (mtype == Search.MatchType.MULTIPLE)
|
|
||||||
multipleResults.push(place.id);
|
|
||||||
else if (mtype == Search.MatchType.PREFIX)
|
|
||||||
prefixResults.push(place.id);
|
|
||||||
else if (mtype == Search.MatchType.SUBSTRING)
|
|
||||||
substringResults.push(place.id);
|
|
||||||
}
|
|
||||||
multipleResults.sort(this._compareResultMeta);
|
|
||||||
prefixResults.sort(this._compareResultMeta);
|
|
||||||
substringResults.sort(this._compareResultMeta);
|
|
||||||
return multipleResults.concat(prefixResults.concat(substringResults));
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialResultSet: function(terms) {
|
|
||||||
let places = Main.placesManager.getAllPlaces();
|
|
||||||
return this._searchPlaces(places, terms);
|
|
||||||
},
|
|
||||||
|
|
||||||
getSubsearchResultSet: function(previousResults, terms) {
|
|
||||||
let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
|
|
||||||
return this._searchPlaces(places, terms);
|
|
||||||
}
|
|
||||||
};
|
|
278
js/ui/places.js
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
|
|
||||||
|
const PLACES_VSPACING = 8;
|
||||||
|
const PLACES_ICON_SIZE = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entry in the places menu.
|
||||||
|
* @name: String title
|
||||||
|
* @iconFactory: A JavaScript callback which will create an icon texture
|
||||||
|
* @onActivate: A JavaScript callback to launch the entry
|
||||||
|
*/
|
||||||
|
function PlaceDisplay(name, iconFactory, onActivate) {
|
||||||
|
this._init(name, iconFactory, onActivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlaceDisplay.prototype = {
|
||||||
|
_init : function(name, iconFactory, onActivate) {
|
||||||
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
reactive: true,
|
||||||
|
spacing: 4 });
|
||||||
|
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
|
||||||
|
onActivate(this);
|
||||||
|
Main.overview.hide();
|
||||||
|
}));
|
||||||
|
let text = new Clutter.Text({ font_name: "Sans 14px",
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
|
text: name });
|
||||||
|
let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
|
this._icon = iconFactory();
|
||||||
|
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
|
||||||
|
this.actor.append(iconBox, Big.BoxPackFlags.NONE);
|
||||||
|
this.actor.append(text, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
this._iconFactory = iconFactory;
|
||||||
|
this._onActivate = onActivate;
|
||||||
|
|
||||||
|
this.actor._delegate = this;
|
||||||
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
getDragActorSource: function() {
|
||||||
|
return this._icon;
|
||||||
|
},
|
||||||
|
|
||||||
|
getDragActor: function(stageX, stageY) {
|
||||||
|
return this._iconFactory();
|
||||||
|
},
|
||||||
|
|
||||||
|
//// Drag and drop methods ////
|
||||||
|
|
||||||
|
shellWorkspaceLaunch : function() {
|
||||||
|
this._onActivate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(PlaceDisplay.prototype);
|
||||||
|
|
||||||
|
function Places() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Places.prototype = {
|
||||||
|
_init : function() {
|
||||||
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
spacing: 4 });
|
||||||
|
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
spacing: PLACES_VSPACING });
|
||||||
|
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
spacing: PLACES_VSPACING });
|
||||||
|
|
||||||
|
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
spacing: PLACES_VSPACING });
|
||||||
|
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
|
||||||
|
let homeUri = homeFile.get_uri();
|
||||||
|
let homeLabel = Shell.util_get_label_for_uri (homeUri);
|
||||||
|
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
|
||||||
|
let home = new PlaceDisplay(homeLabel,
|
||||||
|
function() {
|
||||||
|
return Shell.TextureCache.get_default().load_gicon(homeIcon, PLACES_ICON_SIZE);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
Gio.app_info_launch_default_for_uri(homeUri, Main.createAppLaunchContext());
|
||||||
|
});
|
||||||
|
|
||||||
|
this._menuBox.append(home.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show devices, code more or less ported from nautilus-places-sidebar.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
this._menuBox.append(this._devBox, Big.BoxPackFlags.NONE);
|
||||||
|
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||||
|
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._updateDevices();
|
||||||
|
|
||||||
|
let networkApp = null;
|
||||||
|
try {
|
||||||
|
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
|
||||||
|
} catch(e) {
|
||||||
|
try {
|
||||||
|
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop');
|
||||||
|
} catch(e) {
|
||||||
|
log("Cannot create \"Network\" item, .desktop file not found or corrupt.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkApp != null) {
|
||||||
|
let network = new PlaceDisplay(networkApp.get_name(),
|
||||||
|
function() {
|
||||||
|
return networkApp.create_icon_texture(PLACES_ICON_SIZE);
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
networkApp.launch();
|
||||||
|
});
|
||||||
|
this._menuBox.append(network.actor, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
let connect = new PlaceDisplay('Connect to...',
|
||||||
|
function () {
|
||||||
|
return Shell.TextureCache.get_default().load_icon_name("applications-internet", PLACES_ICON_SIZE);
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
|
||||||
|
});
|
||||||
|
this._menuBox.append(connect.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), ".gtk-bookmarks"]);
|
||||||
|
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
|
||||||
|
let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
|
||||||
|
this._bookmarkTimeoutId = 0;
|
||||||
|
monitor.connect('changed', Lang.bind(this, function () {
|
||||||
|
if (this._bookmarkTimeoutId > 0)
|
||||||
|
return;
|
||||||
|
/* Defensive event compression */
|
||||||
|
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
|
||||||
|
this._bookmarkTimeoutId = 0;
|
||||||
|
this._reloadBookmarks();
|
||||||
|
return false;
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._reloadBookmarks();
|
||||||
|
},
|
||||||
|
|
||||||
|
_reloadBookmarks: function() {
|
||||||
|
|
||||||
|
this._dirsBox.remove_all();
|
||||||
|
|
||||||
|
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let bookmarks = bookmarksContent.split('\n');
|
||||||
|
|
||||||
|
let bookmarksToLabel = {};
|
||||||
|
let bookmarksOrder = [];
|
||||||
|
for (let i = 0; i < bookmarks.length; i++) {
|
||||||
|
let bookmarkLine = bookmarks[i];
|
||||||
|
let components = bookmarkLine.split(' ');
|
||||||
|
let bookmark = components[0];
|
||||||
|
if (bookmark in bookmarksToLabel)
|
||||||
|
continue;
|
||||||
|
let label = null;
|
||||||
|
if (components.length > 1)
|
||||||
|
label = components.slice(1).join(' ');
|
||||||
|
bookmarksToLabel[bookmark] = label;
|
||||||
|
bookmarksOrder.push(bookmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < bookmarksOrder.length; i++) {
|
||||||
|
let bookmark = bookmarksOrder[i];
|
||||||
|
let label = bookmarksToLabel[bookmark];
|
||||||
|
let file = Gio.file_new_for_uri(bookmark);
|
||||||
|
if (!file.query_exists(null))
|
||||||
|
continue;
|
||||||
|
if (label == null)
|
||||||
|
label = Shell.util_get_label_for_uri(bookmark);
|
||||||
|
if (label == null)
|
||||||
|
continue;
|
||||||
|
let icon = Shell.util_get_icon_for_uri(bookmark);
|
||||||
|
|
||||||
|
let item = new PlaceDisplay(label,
|
||||||
|
function() {
|
||||||
|
return Shell.TextureCache.get_default().load_gicon(icon, PLACES_ICON_SIZE);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
Gio.app_info_launch_default_for_uri(bookmark, Main.createAppLaunchContext());
|
||||||
|
});
|
||||||
|
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDevices: function() {
|
||||||
|
this._devBox.remove_all();
|
||||||
|
|
||||||
|
/* first go through all connected drives */
|
||||||
|
let drives = this._volumeMonitor.get_connected_drives();
|
||||||
|
for (let i = 0; i < drives.length; i++) {
|
||||||
|
let volumes = drives[i].get_volumes();
|
||||||
|
for(let j = 0; j < volumes.length; j++) {
|
||||||
|
let mount = volumes[j].get_mount();
|
||||||
|
if(mount != null) {
|
||||||
|
this._addMount(mount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add all volumes that is not associated with a drive */
|
||||||
|
let volumes = this._volumeMonitor.get_volumes();
|
||||||
|
for(let i = 0; i < volumes.length; i++) {
|
||||||
|
if(volumes[i].get_drive() != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let mount = volumes[i].get_mount();
|
||||||
|
if(mount != null) {
|
||||||
|
this._addMount(mount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
|
||||||
|
let mounts = this._volumeMonitor.get_mounts();
|
||||||
|
for(let i = 0; i < mounts.length; i++) {
|
||||||
|
if(mounts[i].is_shadowed())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(mounts[i].get_volume())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
this._addMount(mounts[i]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_addMount: function(mount) {
|
||||||
|
let mountLabel = mount.get_name();
|
||||||
|
let mountIcon = mount.get_icon();
|
||||||
|
let root = mount.get_root();
|
||||||
|
let mountUri = root.get_uri();
|
||||||
|
let devItem = new PlaceDisplay(mountLabel,
|
||||||
|
function() {
|
||||||
|
return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext());
|
||||||
|
});
|
||||||
|
this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(Places.prototype);
|
@ -1,12 +1,11 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const St = imports.gi.St;
|
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
@ -15,180 +14,30 @@ const _ = Gettext.gettext;
|
|||||||
const Lightbox = imports.ui.lightbox;
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const MAX_FILE_DELETED_BEFORE_INVALID = 10;
|
const BOX_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
|
BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
|
||||||
|
|
||||||
const HISTORY_KEY = 'run_dialog/history';
|
const BOX_TEXT_COLOR = new Clutter.Color();
|
||||||
const HISTORY_LIMIT = 512;
|
BOX_TEXT_COLOR.from_pixel(0xffffffff);
|
||||||
|
|
||||||
function CommandCompleter() {
|
const DIALOG_WIDTH = 320;
|
||||||
this._init();
|
const DIALOG_PADDING = 6;
|
||||||
}
|
const ICON_SIZE = 24;
|
||||||
|
const ICON_BOX_SIZE = 36;
|
||||||
CommandCompleter.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
this._changedCount = 0;
|
|
||||||
this._paths = GLib.getenv('PATH').split(':');
|
|
||||||
this._paths.push(GLib.get_home_dir());
|
|
||||||
this._valid = false;
|
|
||||||
this._updateInProgress = false;
|
|
||||||
this._childs = new Array(this._paths.length);
|
|
||||||
this._monitors = new Array(this._paths.length);
|
|
||||||
for (let i = 0; i < this._paths.length; i++) {
|
|
||||||
this._childs[i] = [];
|
|
||||||
let file = Gio.file_new_for_path(this._paths[i]);
|
|
||||||
let info;
|
|
||||||
try {
|
|
||||||
info = file.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, null);
|
|
||||||
} catch (e) {
|
|
||||||
// FIXME catchall
|
|
||||||
this._paths[i] = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_STANDARD_TYPE) != Gio.FileType.DIRECTORY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this._paths[i] = file.get_path();
|
|
||||||
this._monitors[i] = file.monitor_directory(Gio.FileMonitorFlags.NONE, null);
|
|
||||||
if (this._monitors[i] != null) {
|
|
||||||
this._monitors[i].connect('changed', Lang.bind(this, this._onChanged));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._paths = this._paths.filter(function(a) {
|
|
||||||
return a != null;
|
|
||||||
});
|
|
||||||
this._update(0);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onGetEnumerateComplete : function(obj, res) {
|
|
||||||
this._enumerator = obj.enumerate_children_finish(res);
|
|
||||||
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNextFileComplete : function(obj, res) {
|
|
||||||
let files = obj.next_files_finish(res);
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
|
||||||
this._childs[this._i].push(files[i].get_name());
|
|
||||||
}
|
|
||||||
if (files.length) {
|
|
||||||
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
|
|
||||||
} else {
|
|
||||||
this._enumerator.close(null);
|
|
||||||
this._enumerator = null;
|
|
||||||
this._update(this._i + 1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
update : function() {
|
|
||||||
if (this._valid)
|
|
||||||
return;
|
|
||||||
this._update(0);
|
|
||||||
},
|
|
||||||
|
|
||||||
_update : function(i) {
|
|
||||||
if (i == 0 && this._updateInProgress)
|
|
||||||
return;
|
|
||||||
this._updateInProgress = true;
|
|
||||||
this._changedCount = 0;
|
|
||||||
this._i = i;
|
|
||||||
if (i >= this._paths.length) {
|
|
||||||
this._valid = true;
|
|
||||||
this._updateInProgress = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let file = Gio.file_new_for_path(this._paths[i]);
|
|
||||||
this._childs[this._i] = [];
|
|
||||||
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onGetEnumerateComplete));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onChanged : function(m, f, of, type) {
|
|
||||||
if (!this._valid)
|
|
||||||
return;
|
|
||||||
let path = f.get_parent().get_path();
|
|
||||||
let k = undefined;
|
|
||||||
for (let i = 0; i < this._paths.length; i++) {
|
|
||||||
if (this._paths[i] == path)
|
|
||||||
k = i;
|
|
||||||
}
|
|
||||||
if (k === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (type == Gio.FileMonitorEvent.CREATED) {
|
|
||||||
this._childs[k].push(f.get_basename());
|
|
||||||
}
|
|
||||||
if (type == Gio.FileMonitorEvent.DELETED) {
|
|
||||||
this._changedCount++;
|
|
||||||
if (this._changedCount > MAX_FILE_DELETED_BEFORE_INVALID) {
|
|
||||||
this._valid = false;
|
|
||||||
}
|
|
||||||
let name = f.get_basename();
|
|
||||||
this._childs[k] = this._childs[k].filter(function(e) {
|
|
||||||
return e != name;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (type == Gio.FileMonitorEvent.UNMOUNTED) {
|
|
||||||
this._childs[k] = [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getCompletion: function(text) {
|
|
||||||
let common = '';
|
|
||||||
let notInit = true;
|
|
||||||
if (!this._valid) {
|
|
||||||
this._update(0);
|
|
||||||
return common;
|
|
||||||
}
|
|
||||||
function _getCommon(s1, s2) {
|
|
||||||
let k = 0;
|
|
||||||
for (; k < s1.length && k < s2.length; k++) {
|
|
||||||
if (s1[k] != s2[k])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k == 0)
|
|
||||||
return '';
|
|
||||||
return s1.substr(0, k);
|
|
||||||
}
|
|
||||||
function _hasPrefix(s1, prefix) {
|
|
||||||
return s1.indexOf(prefix) == 0;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < this._childs.length; i++) {
|
|
||||||
for (let k = 0; k < this._childs[i].length; k++) {
|
|
||||||
if (!_hasPrefix(this._childs[i][k], text))
|
|
||||||
continue;
|
|
||||||
if (notInit) {
|
|
||||||
common = this._childs[i][k];
|
|
||||||
notInit = false;
|
|
||||||
}
|
|
||||||
common = _getCommon(common, this._childs[i][k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (common.length)
|
|
||||||
return common.substr(text.length);
|
|
||||||
return common;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function RunDialog() {
|
function RunDialog() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
};
|
||||||
|
|
||||||
RunDialog.prototype = {
|
RunDialog.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
|
|
||||||
this._gconf = Shell.GConf.get_default();
|
let gconf = Shell.GConf.get_default();
|
||||||
this._gconf.connect('changed::development_tools', Lang.bind(this, function () {
|
gconf.connect('changed::development_tools', Lang.bind(this, function () {
|
||||||
this._enableInternalCommands = this._gconf.get_boolean('development_tools');
|
this._enableInternalCommands = gconf.get_boolean('development_tools');
|
||||||
}));
|
|
||||||
this._enableInternalCommands = this._gconf.get_boolean('development_tools');
|
|
||||||
|
|
||||||
this._history = this._gconf.get_string_list(HISTORY_KEY);
|
|
||||||
this._historyIndex = -1;
|
|
||||||
|
|
||||||
this._gconf.connect('changed::' + HISTORY_KEY, Lang.bind(this, function() {
|
|
||||||
this._history = this._gconf.get_string_list(HISTORY_KEY);
|
|
||||||
this._historyIndex = this._history.length;
|
|
||||||
}));
|
}));
|
||||||
|
this._enableInternalCommands = gconf.get_boolean('development_tools');
|
||||||
|
|
||||||
this._internalCommands = { 'lg':
|
this._internalCommands = { 'lg':
|
||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
@ -211,192 +60,121 @@ RunDialog.prototype = {
|
|||||||
|
|
||||||
// All actors are inside _group. We create it initially
|
// All actors are inside _group. We create it initially
|
||||||
// hidden then show it in show()
|
// hidden then show it in show()
|
||||||
this._group = new Clutter.Group({ visible: false,
|
this._group = new Clutter.Group({ visible: false });
|
||||||
x: 0, y: 0 });
|
global.stage.add_actor(this._group);
|
||||||
Main.uiGroup.add_actor(this._group);
|
|
||||||
|
|
||||||
let lightbox = new Lightbox.Lightbox(this._group, true);
|
this._lightbox = new Lightbox.Lightbox(this._group);
|
||||||
|
|
||||||
this._box = new St.Bin({ x_align: St.Align.MIDDLE,
|
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
y_align: St.Align.MIDDLE });
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
|
width: global.screen_width,
|
||||||
|
height: global.screen_height });
|
||||||
|
|
||||||
this._group.add_actor(this._box);
|
this._group.add_actor(boxH);
|
||||||
lightbox.highlight(this._box);
|
this._lightbox.highlight(boxH);
|
||||||
|
|
||||||
let dialogBox = new St.BoxLayout({ style_class: 'run-dialog', vertical: true });
|
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
y_align: Big.BoxAlignment.CENTER });
|
||||||
|
|
||||||
this._box.set_child(dialogBox);
|
boxH.append(boxV, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
let label = new St.Label({ style_class: 'run-dialog-label',
|
|
||||||
text: _("Please enter a command:") });
|
|
||||||
|
|
||||||
dialogBox.add(label, { expand: true, y_fill: false });
|
let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
background_color: BOX_BACKGROUND_COLOR,
|
||||||
|
corner_radius: 4,
|
||||||
|
reactive: false,
|
||||||
|
padding: DIALOG_PADDING,
|
||||||
|
width: DIALOG_WIDTH });
|
||||||
|
|
||||||
let entry = new St.Entry({ style_class: 'run-dialog-entry' });
|
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this._entryText = entry.clutter_text;
|
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||||
dialogBox.add(entry, { expand: true });
|
font_name: '18px Sans',
|
||||||
|
text: _("Please enter a command:") });
|
||||||
|
|
||||||
this._errorBox = new St.BoxLayout();
|
dialogBox.append(label, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
dialogBox.add(this._errorBox, { expand: true });
|
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||||
|
font_name: '20px Sans Bold',
|
||||||
|
editable: true,
|
||||||
|
activatable: true,
|
||||||
|
singleLineMode: true });
|
||||||
|
|
||||||
let errorIcon = new St.Button({ style_class: 'run-dialog-error-icon' });
|
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._errorBox.add(errorIcon);
|
this._errorBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
padding_top: DIALOG_PADDING });
|
||||||
|
|
||||||
|
dialogBox.append(this._errorBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
|
width: ICON_BOX_SIZE,
|
||||||
|
height: ICON_BOX_SIZE });
|
||||||
|
|
||||||
|
this._errorBox.append(iconBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this._commandError = false;
|
this._commandError = false;
|
||||||
|
|
||||||
this._errorMessage = new St.Label({ style_class: 'run-dialog-error-label' });
|
let errorIcon = Shell.TextureCache.get_default().load_icon_name("gtk-dialog-error", ICON_SIZE);
|
||||||
this._errorMessage.clutter_text.line_wrap = true;
|
iconBox.append(errorIcon, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._errorBox.add(this._errorMessage, { expand: true });
|
this._errorMessage = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||||
|
font_name: '18px Sans Bold',
|
||||||
|
line_wrap: true });
|
||||||
|
|
||||||
|
this._errorBox.append(this._errorMessage, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._errorBox.hide();
|
this._errorBox.hide();
|
||||||
|
|
||||||
this._pathCompleter = new Gio.FilenameCompleter();
|
this._entry.connect('activate', Lang.bind(this, function (o, e) {
|
||||||
this._commandCompleter = new CommandCompleter();
|
this._run(o.get_text());
|
||||||
this._group.connect('notify::visible', Lang.bind(this._commandCompleter, this._commandCompleter.update));
|
if (!this._commandError)
|
||||||
this._entryText.connect('key-press-event', Lang.bind(this, function(o, e) {
|
this.close();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||||
let symbol = e.get_key_symbol();
|
let symbol = e.get_key_symbol();
|
||||||
if (symbol == Clutter.Down) {
|
|
||||||
this._setCommandFromHistory(this._historyIndex++);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (symbol == Clutter.Up) {
|
|
||||||
this._setCommandFromHistory(this._historyIndex--);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
|
|
||||||
if (Shell.get_event_state(e) & Clutter.ModifierType.CONTROL_MASK)
|
|
||||||
this._run(o.get_text(), true);
|
|
||||||
else
|
|
||||||
this._run(o.get_text(), false);
|
|
||||||
if (!this._commandError)
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
if (symbol == Clutter.Escape) {
|
if (symbol == Clutter.Escape) {
|
||||||
this.close();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (symbol == Clutter.slash) {
|
|
||||||
// Need preload data before get completion. GFilenameCompleter load content of parent directory.
|
|
||||||
// Parent directory for /usr/include/ is /usr/. So need to add fake name('a').
|
|
||||||
let text = o.get_text().concat('/a');
|
|
||||||
let prefix;
|
|
||||||
if (text.lastIndexOf(' ') == -1)
|
|
||||||
prefix = text;
|
|
||||||
else
|
|
||||||
prefix = text.substr(text.lastIndexOf(' ') + 1);
|
|
||||||
this._getCompletion(prefix);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (symbol == Clutter.Tab) {
|
|
||||||
let text = o.get_text();
|
|
||||||
let prefix;
|
|
||||||
if (text.lastIndexOf(' ') == -1)
|
|
||||||
prefix = text;
|
|
||||||
else
|
|
||||||
prefix = text.substr(text.lastIndexOf(' ') + 1);
|
|
||||||
let postfix = this._getCompletion(prefix);
|
|
||||||
if (postfix != null && postfix.length > 0) {
|
|
||||||
o.insert_text(postfix, -1);
|
|
||||||
o.set_cursor_position(text.length + postfix.length);
|
|
||||||
if (postfix[postfix.length - 1] == '/')
|
|
||||||
this._getCompletion(text + postfix + 'a');
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_getCompletion : function(text) {
|
_run : function(command) {
|
||||||
if (text.indexOf('/') != -1) {
|
|
||||||
return this._pathCompleter.get_completion_suffix(text);
|
|
||||||
} else {
|
|
||||||
return this._commandCompleter.getCompletion(text);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_saveHistory : function() {
|
|
||||||
if (this._history.length > HISTORY_LIMIT) {
|
|
||||||
this._history.splice(0, this._history.length - HISTORY_LIMIT);
|
|
||||||
}
|
|
||||||
this._gconf.set_string_list(HISTORY_KEY, this._history);
|
|
||||||
},
|
|
||||||
|
|
||||||
_run : function(input, inTerminal) {
|
|
||||||
let command = input;
|
|
||||||
|
|
||||||
if (this._history.length > 0 && this._history[this._history.length - 1] != input) {
|
|
||||||
this._history.push(input);
|
|
||||||
this._saveHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._commandError = false;
|
|
||||||
let f;
|
let f;
|
||||||
if (this._enableInternalCommands)
|
if (this._enableInternalCommands)
|
||||||
f = this._internalCommands[input];
|
f = this._internalCommands[command];
|
||||||
else
|
else
|
||||||
f = null;
|
f = null;
|
||||||
if (f) {
|
if (f) {
|
||||||
f();
|
f();
|
||||||
} else if (input) {
|
} else if (command) {
|
||||||
try {
|
try {
|
||||||
if (inTerminal)
|
this._commandError = false;
|
||||||
command = 'gnome-terminal -x ' + input;
|
|
||||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||||
let p = new Shell.Process({ 'args' : args });
|
let p = new Shell.Process({'args' : args});
|
||||||
p.run();
|
p.run();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Mmmh, that failed - see if @input matches an existing file
|
this._commandError = true;
|
||||||
let path = null;
|
/*
|
||||||
if (input.charAt(0) == '/') {
|
* The exception contains an error string like:
|
||||||
path = input;
|
* Error invoking Shell.run: Failed to execute child process "foo"
|
||||||
} else {
|
* (No such file or directory)
|
||||||
if (input.charAt(0) == '~')
|
* We are only interested in the actual error, so parse that out.
|
||||||
input = input.slice(1);
|
*/
|
||||||
path = GLib.get_home_dir() + '/' + input;
|
let m = /.+\((.+)\)/.exec(e);
|
||||||
}
|
let errorStr = "Execution of '" + command + "' failed:\n" + m[1];
|
||||||
|
this._errorMessage.set_text(errorStr);
|
||||||
if (GLib.file_test(path, GLib.FileTest.EXISTS)) {
|
this._errorBox.show();
|
||||||
let file = Gio.file_new_for_path(path);
|
|
||||||
Gio.app_info_launch_default_for_uri(file.get_uri(),
|
|
||||||
global.create_app_launch_context());
|
|
||||||
} else {
|
|
||||||
this._commandError = true;
|
|
||||||
// The exception contains an error string like:
|
|
||||||
// Error invoking Shell.run: Failed to execute child
|
|
||||||
// process "foo" (No such file or directory)
|
|
||||||
// We are only interested in the actual error, so parse
|
|
||||||
//that out.
|
|
||||||
let m = /.+\((.+)\)/.exec(e);
|
|
||||||
let errorStr = _("Execution of '%s' failed:").format(command) + '\n' + m[1];
|
|
||||||
this._errorMessage.set_text(errorStr);
|
|
||||||
|
|
||||||
this._errorBox.show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_setCommandFromHistory: function(lastI) {
|
|
||||||
if (this._historyIndex < 0)
|
|
||||||
this._historyIndex = 0;
|
|
||||||
if (this._historyIndex > this._history.length)
|
|
||||||
this._historyIndex = this._history.length;
|
|
||||||
|
|
||||||
let text = this._entryText.get_text();
|
|
||||||
if (text) {
|
|
||||||
this._history[lastI] = text;
|
|
||||||
}
|
|
||||||
if (this._history[this._historyIndex]) {
|
|
||||||
this._entryText.set_text(this._history[this._historyIndex]);
|
|
||||||
} else
|
|
||||||
this._entryText.set_text('');
|
|
||||||
},
|
|
||||||
|
|
||||||
open : function() {
|
open : function() {
|
||||||
if (this._isOpen) // Already shown
|
if (this._isOpen) // Already shown
|
||||||
return;
|
return;
|
||||||
@ -404,18 +182,10 @@ RunDialog.prototype = {
|
|||||||
if (!Main.pushModal(this._group))
|
if (!Main.pushModal(this._group))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Position the dialog on the current monitor
|
|
||||||
let monitor = global.get_focus_monitor();
|
|
||||||
|
|
||||||
this._historyIndex = this._history.length;
|
|
||||||
|
|
||||||
this._box.set_position(monitor.x, monitor.y);
|
|
||||||
this._box.set_size(monitor.width, monitor.height);
|
|
||||||
|
|
||||||
this._isOpen = true;
|
this._isOpen = true;
|
||||||
this._group.show();
|
this._group.show();
|
||||||
|
|
||||||
global.stage.set_key_focus(this._entryText);
|
global.stage.set_key_focus(this._entry);
|
||||||
},
|
},
|
||||||
|
|
||||||
close : function() {
|
close : function() {
|
||||||
@ -428,7 +198,7 @@ RunDialog.prototype = {
|
|||||||
this._commandError = false;
|
this._commandError = false;
|
||||||
|
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
this._entryText.set_text('');
|
this._entry.text = '';
|
||||||
|
|
||||||
Main.popModal(this._group);
|
Main.popModal(this._group);
|
||||||
}
|
}
|
||||||
|
@ -1,261 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
|
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
|
|
||||||
// This module provides functionality for driving the shell user interface
|
|
||||||
// in an automated fashion. The primary current use case for this is
|
|
||||||
// automated performance testing (see runPerfScript()), but it could
|
|
||||||
// be applied to other forms of automation, such as testing for
|
|
||||||
// correctness as well.
|
|
||||||
//
|
|
||||||
// When scripting an automated test we want to make a series of calls
|
|
||||||
// in a linear fashion, but we also want to be able to let the main
|
|
||||||
// loop run so actions can finish. For this reason we write the script
|
|
||||||
// as a generator function that yields when it want to let the main
|
|
||||||
// loop run.
|
|
||||||
//
|
|
||||||
// yield Scripting.sleep(1000);
|
|
||||||
// main.overview.show();
|
|
||||||
// yield Scripting.waitLeisure();
|
|
||||||
//
|
|
||||||
// While it isn't important to the person writing the script, the actual
|
|
||||||
// yielded result is a function that the caller uses to provide the
|
|
||||||
// callback for resuming the script.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sleep:
|
|
||||||
* @milliseconds: number of milliseconds to wait
|
|
||||||
*
|
|
||||||
* Used within an automation script to pause the the execution of the
|
|
||||||
* current script for the specified amount of time. Use as
|
|
||||||
* 'yield Scripting.sleep(500);'
|
|
||||||
*/
|
|
||||||
function sleep(milliseconds) {
|
|
||||||
let cb;
|
|
||||||
|
|
||||||
Mainloop.timeout_add(milliseconds, function() {
|
|
||||||
if (cb)
|
|
||||||
cb();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return function(callback) {
|
|
||||||
cb = callback;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* waitLeisure:
|
|
||||||
*
|
|
||||||
* Used within an automation script to pause the the execution of the
|
|
||||||
* current script until the shell is completely idle. Use as
|
|
||||||
* 'yield Scripting.waitLeisure();'
|
|
||||||
*/
|
|
||||||
function waitLeisure() {
|
|
||||||
let cb;
|
|
||||||
|
|
||||||
global.run_at_leisure(function() {
|
|
||||||
if (cb)
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
|
|
||||||
return function(callback) {
|
|
||||||
cb = callback;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* defineScriptEvent
|
|
||||||
* @name: The event will be called script.<name>
|
|
||||||
* @description: Short human-readable description of the event
|
|
||||||
*
|
|
||||||
* Convenience function to define a zero-argument performance event
|
|
||||||
* within the 'script' namespace that is reserved for events defined locally
|
|
||||||
* within a performance automation script
|
|
||||||
*/
|
|
||||||
function defineScriptEvent(name, description) {
|
|
||||||
Shell.PerfLog.get_default().define_event("script." + name,
|
|
||||||
description,
|
|
||||||
"");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* scriptEvent
|
|
||||||
* @name: Name registered with defineScriptEvent()
|
|
||||||
*
|
|
||||||
* Convenience function to record a script-local performance event
|
|
||||||
* previously defined with defineScriptEvent
|
|
||||||
*/
|
|
||||||
function scriptEvent(name) {
|
|
||||||
Shell.PerfLog.get_default().event("script." + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* collectStatistics
|
|
||||||
*
|
|
||||||
* Convenience function to trigger statistics collection
|
|
||||||
*/
|
|
||||||
function collectStatistics() {
|
|
||||||
Shell.PerfLog.get_default().collect_statistics();
|
|
||||||
}
|
|
||||||
|
|
||||||
function _step(g, finish, onError) {
|
|
||||||
try {
|
|
||||||
let waitFunction = g.next();
|
|
||||||
waitFunction(function() {
|
|
||||||
_step(g, finish, onError);
|
|
||||||
});
|
|
||||||
} catch (err if err instanceof StopIteration) {
|
|
||||||
if (finish)
|
|
||||||
finish();
|
|
||||||
} catch (err) {
|
|
||||||
if (onError)
|
|
||||||
onError(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _collect(scriptModule, outputFile) {
|
|
||||||
let eventHandlers = {};
|
|
||||||
|
|
||||||
for (let f in scriptModule) {
|
|
||||||
let m = /([A-Za-z]+)_([A-Za-z]+)/.exec(f);
|
|
||||||
if (m)
|
|
||||||
eventHandlers[m[1] + "." + m[2]] = scriptModule[f];
|
|
||||||
}
|
|
||||||
|
|
||||||
Shell.PerfLog.get_default().replay(
|
|
||||||
function(time, eventName, signature, arg) {
|
|
||||||
if (eventName in eventHandlers)
|
|
||||||
eventHandlers[eventName](time, arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
if ('finish' in scriptModule)
|
|
||||||
scriptModule.finish();
|
|
||||||
|
|
||||||
if (outputFile) {
|
|
||||||
let f = Gio.file_new_for_path(outputFile);
|
|
||||||
let raw = f.replace(null, false,
|
|
||||||
Gio.FileCreateFlags.NONE,
|
|
||||||
null);
|
|
||||||
let out = Gio.BufferedOutputStream.new_sized (raw, 4096);
|
|
||||||
Shell.write_string_to_stream (out, "{\n");
|
|
||||||
|
|
||||||
Shell.write_string_to_stream(out, '"events":\n');
|
|
||||||
Shell.PerfLog.get_default().dump_events(out);
|
|
||||||
|
|
||||||
let monitors = global.get_monitors()
|
|
||||||
let primary = global.get_primary_monitor()
|
|
||||||
Shell.write_string_to_stream(out, ',\n"monitors":\n[');
|
|
||||||
for (let i = 0; i < monitors.length; i++) {
|
|
||||||
let monitor = monitors[i];
|
|
||||||
let is_primary = (monitor.x == primary.x &&
|
|
||||||
monitor.y == primary.y &&
|
|
||||||
monitor.width == primary.width &&
|
|
||||||
monitor.height == primary.height);
|
|
||||||
if (i != 0)
|
|
||||||
Shell.write_string_to_stream(out, ', ');
|
|
||||||
Shell.write_string_to_stream(out, '"%s%dx%d+%d+%d"'.format(is_primary ? "*" : "",
|
|
||||||
monitor.width, monitor.height,
|
|
||||||
monitor.x, monitor.y));
|
|
||||||
}
|
|
||||||
Shell.write_string_to_stream(out, ' ]');
|
|
||||||
|
|
||||||
Shell.write_string_to_stream(out, ',\n"metrics":\n[ ');
|
|
||||||
let first = true;
|
|
||||||
for (let name in scriptModule.METRICS) {
|
|
||||||
let metric = scriptModule.METRICS[name];
|
|
||||||
|
|
||||||
if (!first)
|
|
||||||
Shell.write_string_to_stream(out, ',\n ');
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
Shell.write_string_to_stream(out,
|
|
||||||
'{ "name": ' + JSON.stringify(name) + ',\n' +
|
|
||||||
' "description": ' + JSON.stringify(metric.description) + ',\n' +
|
|
||||||
' "units": ' + JSON.stringify(metric.units) + ',\n' +
|
|
||||||
' "value": ' + JSON.stringify(metric.value) + ' }');
|
|
||||||
}
|
|
||||||
Shell.write_string_to_stream(out, ' ]');
|
|
||||||
|
|
||||||
Shell.write_string_to_stream (out, ',\n"log":\n');
|
|
||||||
Shell.PerfLog.get_default().dump_log(out);
|
|
||||||
|
|
||||||
Shell.write_string_to_stream (out, '\n}\n');
|
|
||||||
out.close(null);
|
|
||||||
} else {
|
|
||||||
let metrics = [];
|
|
||||||
for (let metric in scriptModule.METRICS)
|
|
||||||
metrics.push(metric);
|
|
||||||
|
|
||||||
metrics.sort();
|
|
||||||
|
|
||||||
print ('------------------------------------------------------------');
|
|
||||||
for (let i = 0; i < metrics.length; i++) {
|
|
||||||
let metric = metrics[i];
|
|
||||||
print ('# ' + scriptModule.METRIC_DESCRIPTIONS[metric]);
|
|
||||||
print (metric + ': ' + scriptModule.METRICS[metric]);
|
|
||||||
}
|
|
||||||
print ('------------------------------------------------------------');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* runPerfScript
|
|
||||||
* @scriptModule: module object with run and finish functions
|
|
||||||
* and event handlers
|
|
||||||
*
|
|
||||||
* Runs a script for automated collection of performance data. The
|
|
||||||
* script is defined as a Javascript module with specified contents.
|
|
||||||
*
|
|
||||||
* First the run() function within the module will be called as a
|
|
||||||
* generator to automate a series of actions. These actions will
|
|
||||||
* trigger performance events and the script can also record its
|
|
||||||
* own performance events.
|
|
||||||
*
|
|
||||||
* Then the recorded event log is replayed using handler functions
|
|
||||||
* within the module. The handler for the event 'foo.bar' is called
|
|
||||||
* foo_bar().
|
|
||||||
*
|
|
||||||
* Finally if the module has a function called finish(), that will
|
|
||||||
* be called.
|
|
||||||
*
|
|
||||||
* The event handler and finish functions are expected to fill in
|
|
||||||
* metrics to an object within the module called METRICS. Each
|
|
||||||
* property of this object represents an individual metric. The
|
|
||||||
* name of the property is the name of the metric, the value
|
|
||||||
* of the property is an object with the following properties:
|
|
||||||
*
|
|
||||||
* description: human readable description of the metric
|
|
||||||
* units: a string representing the units of the metric. It has
|
|
||||||
* the form '<unit> <unit> ... / <unit> / <unit> ...'. Certain
|
|
||||||
* unit values are recognized: s, ms, us, B, KiB, MiB. Other
|
|
||||||
* values can appear but are uninterpreted. Examples 's',
|
|
||||||
* '/ s', 'frames', 'frames / s', 'MiB / s / frame'
|
|
||||||
* value: computed value of the metric
|
|
||||||
*
|
|
||||||
* The resulting metrics will be written to @outputFile as JSON, or,
|
|
||||||
* if @outputFile is not provided, logged.
|
|
||||||
*
|
|
||||||
* After running the script and collecting statistics from the
|
|
||||||
* event log, GNOME Shell will exit.
|
|
||||||
**/
|
|
||||||
function runPerfScript(scriptModule, outputFile) {
|
|
||||||
Shell.PerfLog.get_default().set_enabled(true);
|
|
||||||
|
|
||||||
let g = scriptModule.run();
|
|
||||||
|
|
||||||
_step(g,
|
|
||||||
function() {
|
|
||||||
_collect(scriptModule, outputFile);
|
|
||||||
Meta.exit(Meta.ExitCode.SUCCESS);
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
log("Script failed: " + err + "\n" + err.stack);
|
|
||||||
Meta.exit(Meta.ExitCode.ERROR);
|
|
||||||
});
|
|
||||||
}
|
|
279
js/ui/search.js
@ -1,279 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const RESULT_ICON_SIZE = 24;
|
|
||||||
|
|
||||||
// Not currently referenced by the search API, but
|
|
||||||
// this enumeration can be useful for provider
|
|
||||||
// implementations.
|
|
||||||
const MatchType = {
|
|
||||||
NONE: 0,
|
|
||||||
MULTIPLE: 1,
|
|
||||||
PREFIX: 2,
|
|
||||||
SUBSTRING: 3
|
|
||||||
};
|
|
||||||
|
|
||||||
function SearchResultDisplay(provider) {
|
|
||||||
this._init(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchResultDisplay.prototype = {
|
|
||||||
_init: function(provider) {
|
|
||||||
this.provider = provider;
|
|
||||||
this.actor = null;
|
|
||||||
this.selectionIndex = -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* renderResults:
|
|
||||||
* @results: List of identifier strings
|
|
||||||
* @terms: List of search term strings
|
|
||||||
*
|
|
||||||
* Display the given search matches which resulted
|
|
||||||
* from the given terms. It's expected that not
|
|
||||||
* all results will fit in the space for the container
|
|
||||||
* actor; in this case, show as many as makes sense
|
|
||||||
* for your result type.
|
|
||||||
*
|
|
||||||
* The terms are useful for search match highlighting.
|
|
||||||
*/
|
|
||||||
renderResults: function(results, terms) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clear:
|
|
||||||
* Remove all results from this display and reset the selection index.
|
|
||||||
*/
|
|
||||||
clear: function() {
|
|
||||||
this.actor.get_children().forEach(function (actor) { actor.destroy(); });
|
|
||||||
this.selectionIndex = -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getSelectionIndex:
|
|
||||||
*
|
|
||||||
* Returns the index of the selected actor, or -1 if none.
|
|
||||||
*/
|
|
||||||
getSelectionIndex: function() {
|
|
||||||
return this.selectionIndex;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getVisibleResultCount:
|
|
||||||
*
|
|
||||||
* Returns: The number of actors visible.
|
|
||||||
*/
|
|
||||||
getVisibleResultCount: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* selectIndex:
|
|
||||||
* @index: Integer index
|
|
||||||
*
|
|
||||||
* Move selection to the given index.
|
|
||||||
* Return true if successful, false if no more results
|
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
selectIndex: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activate the currently selected search result.
|
|
||||||
*/
|
|
||||||
activateSelected: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SearchProvider:
|
|
||||||
*
|
|
||||||
* Subclass this object to add a new result type
|
|
||||||
* to the search system, then call registerProvider()
|
|
||||||
* in SearchSystem with an instance.
|
|
||||||
*/
|
|
||||||
function SearchProvider(title) {
|
|
||||||
this._init(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchProvider.prototype = {
|
|
||||||
_init: function(title) {
|
|
||||||
this.title = title;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getInitialResultSet:
|
|
||||||
* @terms: Array of search terms, treated as logical OR
|
|
||||||
*
|
|
||||||
* Called when the user first begins a search (most likely
|
|
||||||
* therefore a single term of length one or two), or when
|
|
||||||
* a new term is added.
|
|
||||||
*
|
|
||||||
* Should return an array of result identifier strings representing
|
|
||||||
* items which match the given search terms. This
|
|
||||||
* is expected to be a substring match on the metadata for a given
|
|
||||||
* item. Ordering of returned results is up to the discretion of the provider,
|
|
||||||
* but you should follow these heruistics:
|
|
||||||
*
|
|
||||||
* * Put items which match multiple search terms before single matches
|
|
||||||
* * Put items which match on a prefix before non-prefix substring matches
|
|
||||||
*
|
|
||||||
* This function should be fast; do not perform unindexed full-text searches
|
|
||||||
* or network queries.
|
|
||||||
*/
|
|
||||||
getInitialResultSet: function(terms) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getSubsearchResultSet:
|
|
||||||
* @previousResults: Array of item identifiers
|
|
||||||
* @newTerms: Updated search terms
|
|
||||||
*
|
|
||||||
* Called when a search is performed which is a "subsearch" of
|
|
||||||
* the previous search; i.e. when every search term has exactly
|
|
||||||
* one corresponding term in the previous search which is a prefix
|
|
||||||
* of the new term.
|
|
||||||
*
|
|
||||||
* This allows search providers to only search through the previous
|
|
||||||
* result set, rather than possibly performing a full re-query.
|
|
||||||
*/
|
|
||||||
getSubsearchResultSet: function(previousResults, newTerms) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getResultInfo:
|
|
||||||
* @id: Result identifier string
|
|
||||||
*
|
|
||||||
* Return an object with 'id', 'name', (both strings) and 'icon' (Clutter.Texture)
|
|
||||||
* properties which describe the given search result.
|
|
||||||
*/
|
|
||||||
getResultMeta: function(id) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* createResultContainer:
|
|
||||||
*
|
|
||||||
* Search providers may optionally override this to render their
|
|
||||||
* results in a custom fashion. The default implementation
|
|
||||||
* will create a vertical list.
|
|
||||||
*
|
|
||||||
* Returns: An instance of SearchResultDisplay.
|
|
||||||
*/
|
|
||||||
createResultContainerActor: function() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* createResultActor:
|
|
||||||
* @resultMeta: Object with result metadata
|
|
||||||
* @terms: Array of search terms, should be used for highlighting
|
|
||||||
*
|
|
||||||
* Search providers may optionally override this to render a
|
|
||||||
* particular serch result in a custom fashion. The default
|
|
||||||
* implementation will show the icon next to the name.
|
|
||||||
*
|
|
||||||
* The actor should be an instance of St.Widget, with the style class
|
|
||||||
* 'dash-search-result-content'.
|
|
||||||
*/
|
|
||||||
createResultActor: function(resultMeta, terms) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* activateResult:
|
|
||||||
* @id: Result identifier string
|
|
||||||
*
|
|
||||||
* Called when the user chooses a given result.
|
|
||||||
*/
|
|
||||||
activateResult: function(id) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* expandSearch:
|
|
||||||
*
|
|
||||||
* Called when the user clicks on the header for this
|
|
||||||
* search section. Should typically launch an external program
|
|
||||||
* displaying search results for that item type.
|
|
||||||
*/
|
|
||||||
expandSearch: function(terms) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(SearchProvider.prototype);
|
|
||||||
|
|
||||||
function SearchSystem() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchSystem.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this._providers = [];
|
|
||||||
this.reset();
|
|
||||||
},
|
|
||||||
|
|
||||||
registerProvider: function (provider) {
|
|
||||||
this._providers.push(provider);
|
|
||||||
},
|
|
||||||
|
|
||||||
getProviders: function() {
|
|
||||||
return this._providers;
|
|
||||||
},
|
|
||||||
|
|
||||||
getTerms: function() {
|
|
||||||
return this._previousTerms;
|
|
||||||
},
|
|
||||||
|
|
||||||
reset: function() {
|
|
||||||
this._previousTerms = [];
|
|
||||||
this._previousResults = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
updateSearch: function(searchString) {
|
|
||||||
searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
|
||||||
if (searchString == '')
|
|
||||||
return null;
|
|
||||||
|
|
||||||
let terms = searchString.split(/\s+/);
|
|
||||||
let isSubSearch = terms.length == this._previousTerms.length;
|
|
||||||
if (isSubSearch) {
|
|
||||||
for (let i = 0; i < terms.length; i++) {
|
|
||||||
if (terms[i].indexOf(this._previousTerms[i]) != 0) {
|
|
||||||
isSubSearch = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let results = [];
|
|
||||||
if (isSubSearch) {
|
|
||||||
for (let i = 0; i < this._previousResults.length; i++) {
|
|
||||||
let [provider, previousResults] = this._previousResults[i];
|
|
||||||
let providerResults = provider.getSubsearchResultSet(previousResults, terms);
|
|
||||||
if (providerResults.length > 0)
|
|
||||||
results.push([provider, providerResults]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (let i = 0; i < this._providers.length; i++) {
|
|
||||||
let provider = this._providers[i];
|
|
||||||
let providerResults = provider.getInitialResultSet(terms);
|
|
||||||
if (providerResults.length > 0)
|
|
||||||
results.push([provider, providerResults]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._previousTerms = terms;
|
|
||||||
this._previousResults = results;
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(SearchSystem.prototype);
|
|
@ -8,16 +8,16 @@ const Mainloop = imports.mainloop;
|
|||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const GnomeShellIface = {
|
const GnomeShellIface = {
|
||||||
name: 'org.gnome.Shell',
|
name: "org.gnome.Shell",
|
||||||
methods: [{ name: 'Eval',
|
methods: [{ name: "Eval",
|
||||||
inSignature: 's',
|
inSignature: "s",
|
||||||
outSignature: 'bs'
|
outSignature: "bs"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
signals: [],
|
signals: [],
|
||||||
properties: [{ name: 'OverviewActive',
|
properties: [{ name: "OverviewActive",
|
||||||
signature: 'b',
|
signature: "b",
|
||||||
access: 'readwrite' }]
|
access: "readwrite" }]
|
||||||
};
|
};
|
||||||
|
|
||||||
function GnomeShell() {
|
function GnomeShell() {
|
||||||
@ -48,9 +48,6 @@ GnomeShell.prototype = {
|
|||||||
let success;
|
let success;
|
||||||
try {
|
try {
|
||||||
returnValue = JSON.stringify(eval(code));
|
returnValue = JSON.stringify(eval(code));
|
||||||
// A hack; DBus doesn't have null/undefined
|
|
||||||
if (returnValue == undefined)
|
|
||||||
returnValue = '';
|
|
||||||
success = true;
|
success = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
returnValue = JSON.stringify(e);
|
returnValue = JSON.stringify(e);
|
||||||
|
176
js/ui/sidebar.js
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Panel = imports.ui.panel;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
const Widget = imports.ui.widget;
|
||||||
|
const WidgetBox = imports.ui.widgetBox;
|
||||||
|
|
||||||
|
const SIDEBAR_SPACING = 4;
|
||||||
|
const SIDEBAR_PADDING = 4;
|
||||||
|
|
||||||
|
// The total sidebar width is the widget width plus the widget padding
|
||||||
|
// (counted twice for the widget box, and once again for the
|
||||||
|
// out-of-screen padding), plus the empty space between the border of
|
||||||
|
// the bar and of the windows
|
||||||
|
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
||||||
|
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
||||||
|
|
||||||
|
function Sidebar() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sidebar.prototype = {
|
||||||
|
_init : function() {
|
||||||
|
// The top-left corner of the sidebar is fixed at:
|
||||||
|
// x = -WidgetBox.WIDGETBOX_PADDING, y = Panel.PANEL_HEIGHT.
|
||||||
|
// (The negative X is so that we don't see the rounded
|
||||||
|
// WidgetBox corners on the screen edge side.)
|
||||||
|
this.actor = new Clutter.Group({ x: -WidgetBox.WIDGETBOX_PADDING,
|
||||||
|
y: Panel.PANEL_HEIGHT,
|
||||||
|
width: SIDEBAR_EXPANDED_WIDTH });
|
||||||
|
|
||||||
|
// The actual widgets go into a Big.Box inside this.actor. The
|
||||||
|
// box's width will vary during the expand/collapse animations,
|
||||||
|
// but this.actor's width will remain constant until we adjust
|
||||||
|
// it at the end of the animation, because we don't want the
|
||||||
|
// wm strut to move and cause windows to move multiple times
|
||||||
|
// during the animation.
|
||||||
|
this.box = new Big.Box ({ padding_top: SIDEBAR_PADDING,
|
||||||
|
padding_bottom: SIDEBAR_PADDING,
|
||||||
|
padding_right: 0,
|
||||||
|
padding_left: 0,
|
||||||
|
spacing: SIDEBAR_SPACING });
|
||||||
|
this.actor.add_actor(this.box);
|
||||||
|
|
||||||
|
this._gconf = Shell.GConf.get_default();
|
||||||
|
|
||||||
|
this._expanded = this._gconf.get_boolean ("sidebar/expanded");
|
||||||
|
if (!this._expanded)
|
||||||
|
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
|
||||||
|
|
||||||
|
this._visible = this._gconf.get_boolean ("sidebar/visible");
|
||||||
|
if (this._visible)
|
||||||
|
Main.chrome.addActor(this.actor);
|
||||||
|
|
||||||
|
this._widgets = [];
|
||||||
|
this.addWidget(new ToggleWidget());
|
||||||
|
|
||||||
|
let default_widgets = this._gconf.get_string_list("sidebar/widgets");
|
||||||
|
for (let i = 0; i < default_widgets.length; i++)
|
||||||
|
this.addWidget(default_widgets[i]);
|
||||||
|
|
||||||
|
this._gconf.connect('changed::sidebar/expanded',
|
||||||
|
Lang.bind(this, this._expandedChanged));
|
||||||
|
this._gconf.connect('changed::sidebar/visible',
|
||||||
|
Lang.bind(this, this._visibleChanged));
|
||||||
|
},
|
||||||
|
|
||||||
|
addWidget: function(widget) {
|
||||||
|
let widgetBox;
|
||||||
|
try {
|
||||||
|
widgetBox = new WidgetBox.WidgetBox(widget, this._expanded);
|
||||||
|
} catch(e) {
|
||||||
|
logError(e, "Failed to add widget '" + widget + "'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.box.append(widgetBox.actor, Big.BoxPackFlags.NONE);
|
||||||
|
this._widgets.push(widgetBox);
|
||||||
|
},
|
||||||
|
|
||||||
|
_visibleChanged: function() {
|
||||||
|
let visible = this._gconf.get_boolean("sidebar/visible");
|
||||||
|
if (visible == this._visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._visible = visible;
|
||||||
|
if (visible)
|
||||||
|
Main.chrome.addActor(this.actor);
|
||||||
|
else
|
||||||
|
Main.chrome.removeActor(this.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_expandedChanged: function() {
|
||||||
|
let expanded = this._gconf.get_boolean("sidebar/expanded");
|
||||||
|
if (expanded == this._expanded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._expanded = expanded;
|
||||||
|
if (expanded)
|
||||||
|
this._expand();
|
||||||
|
else
|
||||||
|
this._collapse();
|
||||||
|
},
|
||||||
|
|
||||||
|
_expand: function() {
|
||||||
|
this._expanded = true;
|
||||||
|
for (let i = 0; i < this._widgets.length; i++)
|
||||||
|
this._widgets[i].expand();
|
||||||
|
|
||||||
|
// Updated the strut/stage area after the animation completes
|
||||||
|
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
|
||||||
|
onComplete: function () {
|
||||||
|
this.actor.width = SIDEBAR_EXPANDED_WIDTH;
|
||||||
|
} });
|
||||||
|
},
|
||||||
|
|
||||||
|
_collapse: function() {
|
||||||
|
this._expanded = false;
|
||||||
|
for (let i = 0; i < this._widgets.length; i++)
|
||||||
|
this._widgets[i].collapse();
|
||||||
|
|
||||||
|
// Updated the strut/stage area after the animation completes
|
||||||
|
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
|
||||||
|
onComplete: function () {
|
||||||
|
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
|
||||||
|
} });
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
this.hide();
|
||||||
|
|
||||||
|
for (let i = 0; i < this._widgets.length; i++)
|
||||||
|
this._widgets[i].destroy();
|
||||||
|
this.actor.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LEFT_DOUBLE_ARROW = "\u00AB";
|
||||||
|
const RIGHT_DOUBLE_ARROW = "\u00BB";
|
||||||
|
|
||||||
|
function ToggleWidget() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleWidget.prototype = {
|
||||||
|
__proto__ : Widget.Widget.prototype,
|
||||||
|
|
||||||
|
_init : function() {
|
||||||
|
this._gconf = Shell.GConf.get_default();
|
||||||
|
|
||||||
|
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
|
||||||
|
text: LEFT_DOUBLE_ARROW,
|
||||||
|
reactive: true });
|
||||||
|
this.actor.connect('button-release-event',
|
||||||
|
Lang.bind(this, this._collapse));
|
||||||
|
this.collapsedActor = new Clutter.Text({ font_name: "Sans Bold 16px",
|
||||||
|
text: RIGHT_DOUBLE_ARROW,
|
||||||
|
reactive: true });
|
||||||
|
this.collapsedActor.connect('button-release-event',
|
||||||
|
Lang.bind(this, this._expand));
|
||||||
|
},
|
||||||
|
|
||||||
|
_collapse : function () {
|
||||||
|
this._gconf.set_boolean ("sidebar/expanded", false);
|
||||||
|
},
|
||||||
|
|
||||||
|
_expand : function () {
|
||||||
|
this._gconf.set_boolean ("sidebar/expanded", true);
|
||||||
|
}
|
||||||
|
};
|
@ -1,170 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Gdm = imports.gi.Gdm;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const GnomeSession = imports.misc.gnomeSession;
|
|
||||||
const Panel = imports.ui.panel;
|
|
||||||
|
|
||||||
// Adapted from gdm/gui/user-switch-applet/applet.c
|
|
||||||
//
|
|
||||||
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
|
|
||||||
// Copyright (C) 2008,2009 Red Hat, Inc.
|
|
||||||
|
|
||||||
function StatusMenuButton() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusMenuButton.prototype = {
|
|
||||||
__proto__: Panel.PanelMenuButton.prototype,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
Panel.PanelMenuButton.prototype._init.call(this, St.Align.START);
|
|
||||||
let box = new St.BoxLayout({ name: 'panelStatusMenu' });
|
|
||||||
this.actor.set_child(box);
|
|
||||||
|
|
||||||
this._gdm = Gdm.UserManager.ref_default();
|
|
||||||
this._user = this._gdm.get_user(GLib.get_user_name());
|
|
||||||
this._presence = new GnomeSession.Presence();
|
|
||||||
|
|
||||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
|
||||||
|
|
||||||
this._iconBox = new St.Bin();
|
|
||||||
box.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false });
|
|
||||||
|
|
||||||
let textureCache = St.TextureCache.get_default();
|
|
||||||
// FIXME: these icons are all wrong (likewise in createSubMenu)
|
|
||||||
this._availableIcon = textureCache.load_icon_name('gtk-yes', 16);
|
|
||||||
this._busyIcon = textureCache.load_icon_name('gtk-no', 16);
|
|
||||||
this._invisibleIcon = textureCache.load_icon_name('gtk-close', 16);
|
|
||||||
this._idleIcon = textureCache.load_icon_name('gtk-media-pause', 16);
|
|
||||||
|
|
||||||
this._presence.connect('StatusChanged', Lang.bind(this, this._updatePresenceIcon));
|
|
||||||
this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon));
|
|
||||||
|
|
||||||
this._name = new St.Label({ text: this._user.get_real_name() });
|
|
||||||
box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false });
|
|
||||||
this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName));
|
|
||||||
|
|
||||||
this._createSubMenu();
|
|
||||||
this._gdm.connect('users-loaded', Lang.bind(this, this._updateSwitchUser));
|
|
||||||
this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser));
|
|
||||||
this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onDestroy: function() {
|
|
||||||
this._user.disconnect(this._userNameChangedId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateUserName: function() {
|
|
||||||
this._name.set_text(this._user.get_real_name());
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateSwitchUser: function() {
|
|
||||||
let users = this._gdm.list_users();
|
|
||||||
if (users.length > 1)
|
|
||||||
this._loginScreenItem.actor.show();
|
|
||||||
else
|
|
||||||
this._loginScreenItem.actor.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updatePresenceIcon: function(presence, status) {
|
|
||||||
if (status == GnomeSession.PresenceStatus.AVAILABLE)
|
|
||||||
this._iconBox.child = this._availableIcon;
|
|
||||||
else if (status == GnomeSession.PresenceStatus.BUSY)
|
|
||||||
this._iconBox.child = this._busyIcon;
|
|
||||||
else if (status == GnomeSession.PresenceStatus.INVISIBLE)
|
|
||||||
this._iconBox.child = this._invisibleIcon;
|
|
||||||
else
|
|
||||||
this._iconBox.child = this._idleIcon;
|
|
||||||
},
|
|
||||||
|
|
||||||
_createSubMenu: function() {
|
|
||||||
let item;
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Available"), 'gtk-yes', true);
|
|
||||||
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.AVAILABLE));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Busy"), 'gtk-no', true);
|
|
||||||
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.BUSY));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Invisible"), 'gtk-close', true);
|
|
||||||
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.INVISIBLE));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelSeparatorMenuItem();
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Account Information..."), 'user-info');
|
|
||||||
item.connect('activate', Lang.bind(this, this._onAccountInformationActivate));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("System Preferences..."), 'preferences-desktop');
|
|
||||||
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelSeparatorMenuItem();
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Lock Screen"), 'system-lock-screen');
|
|
||||||
item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Switch User"), 'system-users');
|
|
||||||
item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
this._loginScreenItem = item;
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Log Out..."), 'system-log-out');
|
|
||||||
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
|
|
||||||
item = new Panel.PanelImageMenuItem(_("Shut Down..."), 'system-shutdown');
|
|
||||||
item.connect('activate', Lang.bind(this, this._onShutDownActivate));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setPresenceStatus: function(item, event, status) {
|
|
||||||
this._presence.setStatus(status);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onAccountInformationActivate: function() {
|
|
||||||
this._spawn(['gnome-about-me']);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onPreferencesActivate: function() {
|
|
||||||
this._spawn(['gnome-control-center']);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onLockScreenActivate: function() {
|
|
||||||
this._spawn(['gnome-screensaver-command', '--lock']);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onLoginScreenActivate: function() {
|
|
||||||
this._gdm.goto_login_session();
|
|
||||||
this._onLockScreenActivate();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onQuitSessionActivate: function() {
|
|
||||||
this._spawn(['gnome-session-save', '--logout-dialog']);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onShutDownActivate: function() {
|
|
||||||
this._spawn(['gnome-session-save', '--shutdown-dialog']);
|
|
||||||
},
|
|
||||||
|
|
||||||
_spawn: function(args) {
|
|
||||||
// FIXME: once Shell.Process gets support for signalling
|
|
||||||
// errors we should pop up an error dialog or something here
|
|
||||||
// on failure
|
|
||||||
let p = new Shell.Process({'args' : args});
|
|
||||||
p.run();
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,686 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
const Telepathy = imports.misc.telepathy;
|
|
||||||
|
|
||||||
let contactManager;
|
|
||||||
let channelDispatcher;
|
|
||||||
|
|
||||||
// See Notification.appendMessage
|
|
||||||
const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
|
|
||||||
const SCROLLBACK_RECENT_LENGTH = 20;
|
|
||||||
const SCROLLBACK_IDLE_LENGTH = 5;
|
|
||||||
|
|
||||||
// A 'Qualified_Property_Value_Map' that represents a single-user
|
|
||||||
// text-based chat.
|
|
||||||
let singleUserTextChannel = {};
|
|
||||||
singleUserTextChannel[Telepathy.CHANNEL_NAME + '.ChannelType'] = Telepathy.CHANNEL_TEXT_NAME;
|
|
||||||
singleUserTextChannel[Telepathy.CHANNEL_NAME + '.TargetHandleType'] = Telepathy.HandleType.CONTACT;
|
|
||||||
|
|
||||||
// Some protocols only support 'multi-user' chats, and single-user
|
|
||||||
// chats are just treated as multi-user chats with only one other
|
|
||||||
// participant. Telepathy uses HandleType.NONE for all chats in these
|
|
||||||
// protocols; there's no good way for us to tell if the channel is
|
|
||||||
// single- or multi-user.
|
|
||||||
let oneOrMoreUserTextChannel = {};
|
|
||||||
oneOrMoreUserTextChannel[Telepathy.CHANNEL_NAME + '.ChannelType'] = Telepathy.CHANNEL_TEXT_NAME;
|
|
||||||
oneOrMoreUserTextChannel[Telepathy.CHANNEL_NAME + '.TargetHandleType'] = Telepathy.HandleType.NONE;
|
|
||||||
|
|
||||||
// The (non-chat) channel indicating the users whose presence
|
|
||||||
// information we subscribe to
|
|
||||||
let subscribedContactsChannel = {};
|
|
||||||
subscribedContactsChannel[Telepathy.CHANNEL_NAME + '.ChannelType'] = Telepathy.CHANNEL_CONTACT_LIST_NAME;
|
|
||||||
subscribedContactsChannel[Telepathy.CHANNEL_NAME + '.TargetHandleType'] = Telepathy.HandleType.LIST;
|
|
||||||
subscribedContactsChannel[Telepathy.CHANNEL_NAME + '.TargetID'] = 'subscribe';
|
|
||||||
|
|
||||||
|
|
||||||
// This is GNOME Shell's implementation of the Telepathy 'Client'
|
|
||||||
// interface. Specifically, the shell is a Telepathy 'Observer', which
|
|
||||||
// lets us see messages even if they belong to another app (eg,
|
|
||||||
// Empathy).
|
|
||||||
|
|
||||||
function Client() {
|
|
||||||
this._init();
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
let name = Telepathy.CLIENT_NAME + '.GnomeShell';
|
|
||||||
DBus.session.exportObject(Telepathy.nameToPath(name), this);
|
|
||||||
DBus.session.acquire_name(name, DBus.SINGLE_INSTANCE,
|
|
||||||
function (name) { /* FIXME: acquired */ },
|
|
||||||
function (name) { /* FIXME: lost */ });
|
|
||||||
|
|
||||||
this._accounts = {};
|
|
||||||
this._sources = {};
|
|
||||||
|
|
||||||
contactManager = new ContactManager();
|
|
||||||
contactManager.connect('presence-changed', Lang.bind(this, this._presenceChanged));
|
|
||||||
|
|
||||||
channelDispatcher = new Telepathy.ChannelDispatcher(DBus.session,
|
|
||||||
Telepathy.CHANNEL_DISPATCHER_NAME,
|
|
||||||
Telepathy.nameToPath(Telepathy.CHANNEL_DISPATCHER_NAME));
|
|
||||||
|
|
||||||
// Acquire existing connections. (Needed to make things work
|
|
||||||
// through a restart.)
|
|
||||||
let accountManager = new Telepathy.AccountManager(DBus.session,
|
|
||||||
Telepathy.ACCOUNT_MANAGER_NAME,
|
|
||||||
Telepathy.nameToPath(Telepathy.ACCOUNT_MANAGER_NAME));
|
|
||||||
accountManager.GetRemote('ValidAccounts', Lang.bind(this,
|
|
||||||
function (accounts, err) {
|
|
||||||
if (!accounts)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < accounts.length; i++)
|
|
||||||
this._gotAccount(accounts[i]);
|
|
||||||
}));
|
|
||||||
accountManager.connect('AccountValidityChanged', Lang.bind(this, this._accountValidityChanged));
|
|
||||||
},
|
|
||||||
|
|
||||||
_accountValidityChanged: function(accountManager, accountPath, valid) {
|
|
||||||
if (!valid) {
|
|
||||||
delete this._accounts[accountPath];
|
|
||||||
// We don't need to clean up connections, sources, etc; they'll
|
|
||||||
// get Closed and cleaned up independently.
|
|
||||||
} else
|
|
||||||
this._gotAccount(accountPath);
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotAccount: function(accountPath) {
|
|
||||||
let account = new Telepathy.Account(DBus.session,
|
|
||||||
Telepathy.ACCOUNT_MANAGER_NAME,
|
|
||||||
accountPath);
|
|
||||||
this._accounts[accountPath] = account;
|
|
||||||
account.GetRemote('Connection', Lang.bind(this,
|
|
||||||
function (connPath, err) {
|
|
||||||
if (!connPath || connPath == '/')
|
|
||||||
return;
|
|
||||||
|
|
||||||
let connReq = new Telepathy.ConnectionRequests(DBus.session,
|
|
||||||
Telepathy.pathToName(connPath),
|
|
||||||
connPath);
|
|
||||||
connReq.GetRemote('Channels', Lang.bind(this,
|
|
||||||
function(channels, err) {
|
|
||||||
if (!channels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._addChannels(accountPath, connPath, channels);
|
|
||||||
}));
|
|
||||||
|
|
||||||
contactManager.addConnection(connPath);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
get Interfaces() {
|
|
||||||
return [ Telepathy.CLIENT_OBSERVER_NAME ];
|
|
||||||
},
|
|
||||||
|
|
||||||
get ObserverChannelFilter() {
|
|
||||||
return [ singleUserTextChannel, oneOrMoreUserTextChannel ];
|
|
||||||
},
|
|
||||||
|
|
||||||
ObserveChannels: function(accountPath, connPath, channels,
|
|
||||||
dispatchOperation, requestsSatisfied,
|
|
||||||
observerInfo) {
|
|
||||||
this._addChannels(accountPath, connPath, channels);
|
|
||||||
},
|
|
||||||
|
|
||||||
_addChannels: function(accountPath, connPath, channelDetailsList) {
|
|
||||||
for (let i = 0; i < channelDetailsList.length; i++) {
|
|
||||||
let [channelPath, props] = channelDetailsList[i];
|
|
||||||
|
|
||||||
// If this is being called from the startup code then it
|
|
||||||
// won't have passed through our filters, so we need to
|
|
||||||
// check the channel/targetHandle type ourselves.
|
|
||||||
|
|
||||||
let channelType = props[Telepathy.CHANNEL_NAME + '.ChannelType'];
|
|
||||||
if (channelType != Telepathy.CHANNEL_TEXT_NAME)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let targetHandleType = props[Telepathy.CHANNEL_NAME + '.TargetHandleType'];
|
|
||||||
if (targetHandleType != Telepathy.HandleType.CONTACT &&
|
|
||||||
targetHandleType != Telepathy.HandleType.NONE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let targetHandle = props[Telepathy.CHANNEL_NAME + '.TargetHandle'];
|
|
||||||
let targetId = props[Telepathy.CHANNEL_NAME + '.TargetID'];
|
|
||||||
|
|
||||||
if (this._sources[connPath + ':' + targetHandle])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let source = new Source(accountPath, connPath, channelPath,
|
|
||||||
targetHandle, targetHandleType, targetId);
|
|
||||||
this._sources[connPath + ':' + targetHandle] = source;
|
|
||||||
source.connect('destroy', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
delete this._sources[connPath + ':' + targetHandle];
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_presenceChanged: function(contactManager, connPath, handle,
|
|
||||||
type, message) {
|
|
||||||
let source = this._sources[connPath + ':' + handle];
|
|
||||||
if (!source)
|
|
||||||
return;
|
|
||||||
|
|
||||||
source.setPresence(type, message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
DBus.conformExport(Client.prototype, Telepathy.ClientIface);
|
|
||||||
DBus.conformExport(Client.prototype, Telepathy.ClientObserverIface);
|
|
||||||
|
|
||||||
|
|
||||||
function ContactManager() {
|
|
||||||
this._init();
|
|
||||||
};
|
|
||||||
|
|
||||||
ContactManager.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this._connections = {};
|
|
||||||
// Note that if we changed this to '/telepathy/avatars' then
|
|
||||||
// we would share cache files with empathy. But since this is
|
|
||||||
// not documented/guaranteed, it seems a little sketchy
|
|
||||||
this._cacheDir = GLib.get_user_cache_dir() + '/gnome-shell/avatars';
|
|
||||||
},
|
|
||||||
|
|
||||||
addConnection: function(connPath) {
|
|
||||||
let info = this._connections[connPath];
|
|
||||||
if (info)
|
|
||||||
return info;
|
|
||||||
|
|
||||||
info = {};
|
|
||||||
|
|
||||||
// Figure out the cache subdirectory for this connection by
|
|
||||||
// parsing the connection manager name (eg, 'gabble') and
|
|
||||||
// protocol name (eg, 'jabber') from the Connection's path.
|
|
||||||
// Telepathy requires the D-Bus path for a connection to have
|
|
||||||
// a specific form, and explicitly says that clients are
|
|
||||||
// allowed to parse it.
|
|
||||||
let match = connPath.match(/\/org\/freedesktop\/Telepathy\/Connection\/([^\/]*\/[^\/]*)\/.*/);
|
|
||||||
if (!match)
|
|
||||||
throw new Error('Could not parse connection path ' + connPath);
|
|
||||||
|
|
||||||
info.cacheDir = this._cacheDir + '/' + match[1];
|
|
||||||
GLib.mkdir_with_parents(info.cacheDir, 0700);
|
|
||||||
|
|
||||||
// info.names[handle] is @handle's real name
|
|
||||||
// info.tokens[handle] is the token for @handle's avatar
|
|
||||||
info.names = {};
|
|
||||||
info.tokens = {};
|
|
||||||
|
|
||||||
// info.icons[handle] is an array of the icon actors currently
|
|
||||||
// being displayed for @handle. These will be updated
|
|
||||||
// automatically if @handle's avatar changes.
|
|
||||||
info.icons = {};
|
|
||||||
|
|
||||||
let connName = Telepathy.pathToName(connPath);
|
|
||||||
|
|
||||||
info.connectionAvatars = new Telepathy.ConnectionAvatars(DBus.session, connName, connPath);
|
|
||||||
info.updatedId = info.connectionAvatars.connect(
|
|
||||||
'AvatarUpdated', Lang.bind(this, this._avatarUpdated));
|
|
||||||
info.retrievedId = info.connectionAvatars.connect(
|
|
||||||
'AvatarRetrieved', Lang.bind(this, this._avatarRetrieved));
|
|
||||||
|
|
||||||
info.connectionContacts = new Telepathy.ConnectionContacts(DBus.session, connName, connPath);
|
|
||||||
|
|
||||||
info.connectionPresence = new Telepathy.ConnectionSimplePresence(DBus.session, connName, connPath);
|
|
||||||
info.presenceChangedId = info.connectionPresence.connect(
|
|
||||||
'PresencesChanged', Lang.bind(this, this._presencesChanged));
|
|
||||||
|
|
||||||
let conn = new Telepathy.Connection(DBus.session, connName, connPath);
|
|
||||||
info.statusChangedId = conn.connect('StatusChanged', Lang.bind(this,
|
|
||||||
function (status, reason) {
|
|
||||||
if (status == Telepathy.ConnectionStatus.DISCONNECTED)
|
|
||||||
this._removeConnection(conn);
|
|
||||||
}));
|
|
||||||
|
|
||||||
let connReq = new Telepathy.ConnectionRequests(DBus.session,
|
|
||||||
connName, connPath);
|
|
||||||
connReq.EnsureChannelRemote(subscribedContactsChannel, Lang.bind(this,
|
|
||||||
function (result, err) {
|
|
||||||
if (!result)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let [mine, channelPath, props] = result;
|
|
||||||
this._gotContactsChannel(connPath, channelPath, props);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._connections[connPath] = info;
|
|
||||||
return info;
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotContactsChannel: function(connPath, channelPath, props) {
|
|
||||||
let info = this._connections[connPath];
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
info.contactsGroup = new Telepathy.ChannelGroup(DBus.session,
|
|
||||||
Telepathy.pathToName(connPath),
|
|
||||||
channelPath);
|
|
||||||
info.contactsListChangedId =
|
|
||||||
info.contactsGroup.connect('MembersChanged', Lang.bind(this, this._contactsListChanged, info));
|
|
||||||
|
|
||||||
info.contactsGroup.GetRemote('Members', Lang.bind(this,
|
|
||||||
function(contacts, err) {
|
|
||||||
if (!contacts)
|
|
||||||
return;
|
|
||||||
|
|
||||||
info.connectionContacts.GetContactAttributesRemote(
|
|
||||||
contacts, [Telepathy.CONNECTION_ALIASING_NAME], false,
|
|
||||||
Lang.bind(this, this._gotContactAttributes, info));
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_contactsListChanged: function(group, message, added, removed,
|
|
||||||
local_pending, remote_pending,
|
|
||||||
actor, reason, info) {
|
|
||||||
for (let i = 0; i < removed.length; i++)
|
|
||||||
delete info.names[removed[i]];
|
|
||||||
|
|
||||||
info.connectionContacts.GetContactAttributesRemote(
|
|
||||||
added, [Telepathy.CONNECTION_ALIASING_NAME], false,
|
|
||||||
Lang.bind(this, this._gotContactAttributes, info));
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotContactAttributes: function(attrs, err, info) {
|
|
||||||
if (!attrs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let handle in attrs)
|
|
||||||
info.names[handle] = attrs[handle][Telepathy.CONNECTION_ALIASING_NAME + '/alias'];
|
|
||||||
},
|
|
||||||
|
|
||||||
_presencesChanged: function(conn, presences, err) {
|
|
||||||
if (!presences)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let info = this._connections[conn.getPath()];
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let handle in presences) {
|
|
||||||
let [type, status, message] = presences[handle];
|
|
||||||
this.emit('presence-changed', conn.getPath(), handle, type, message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeConnection: function(conn) {
|
|
||||||
let info = this._connections[conn.getPath()];
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
conn.disconnect(info.statusChangedId);
|
|
||||||
info.connectionAvatars.disconnect(info.updatedId);
|
|
||||||
info.connectionAvatars.disconnect(info.retrievedId);
|
|
||||||
info.connectionPresence.disconnect(info.presenceChangedId);
|
|
||||||
info.contactsGroup.disconnect(info.contactsListChangedId);
|
|
||||||
|
|
||||||
delete this._connections[conn.getPath()];
|
|
||||||
},
|
|
||||||
|
|
||||||
_getFileForToken: function(info, token) {
|
|
||||||
return info.cacheDir + '/' + Telepathy.escapeAsIdentifier(token);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setIcon: function(iconBox, info, handle) {
|
|
||||||
let textureCache = St.TextureCache.get_default();
|
|
||||||
let token = info.tokens[handle];
|
|
||||||
let file;
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
file = this._getFileForToken(info, token);
|
|
||||||
if (!GLib.file_test(file, GLib.FileTest.EXISTS))
|
|
||||||
file = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
let uri = GLib.filename_to_uri(file, null);
|
|
||||||
iconBox.child = textureCache.load_uri_async(uri, iconBox._size, iconBox._size);
|
|
||||||
} else {
|
|
||||||
iconBox.child = textureCache.load_icon_name('stock_person', iconBox._size);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateIcons: function(info, handle) {
|
|
||||||
if (!info.icons[handle])
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < info.icons[handle].length; i++) {
|
|
||||||
let iconBox = info.icons[handle][i];
|
|
||||||
this._setIcon(iconBox, info, handle);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_avatarUpdated: function(conn, handle, token) {
|
|
||||||
let info = this._connections[conn.getPath()];
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (info.tokens[handle] == token)
|
|
||||||
return;
|
|
||||||
|
|
||||||
info.tokens[handle] = token;
|
|
||||||
if (token != '') {
|
|
||||||
let file = this._getFileForToken(info, token);
|
|
||||||
if (!GLib.file_test(file, GLib.FileTest.EXISTS)) {
|
|
||||||
info.connectionAvatars.RequestAvatarsRemote([handle]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateIcons(info, handle);
|
|
||||||
},
|
|
||||||
|
|
||||||
_avatarRetrieved: function(conn, handle, token, avatarData, mimeType) {
|
|
||||||
let info = this._connections[conn.getPath()];
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let file = this._getFileForToken(info, token);
|
|
||||||
let success = false;
|
|
||||||
try {
|
|
||||||
success = GLib.file_set_contents(file, avatarData, avatarData.length);
|
|
||||||
} catch (e) {
|
|
||||||
logError(e, 'Error caching avatar data');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
this._updateIcons(info, handle);
|
|
||||||
},
|
|
||||||
|
|
||||||
createAvatar: function(conn, handle, size) {
|
|
||||||
let iconBox = new St.Bin({ style_class: 'avatar-box' });
|
|
||||||
iconBox._size = size;
|
|
||||||
|
|
||||||
let info = this._connections[conn.getPath()];
|
|
||||||
if (!info)
|
|
||||||
info = this.addConnection(conn.getPath());
|
|
||||||
|
|
||||||
if (!info.icons[handle])
|
|
||||||
info.icons[handle] = [];
|
|
||||||
info.icons[handle].push(iconBox);
|
|
||||||
|
|
||||||
iconBox.connect('destroy', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
let i = info.icons[handle].indexOf(iconBox);
|
|
||||||
if (i != -1)
|
|
||||||
info.icons[handle].splice(i, 1);
|
|
||||||
}));
|
|
||||||
|
|
||||||
// If we already have the icon cached and know its token, this
|
|
||||||
// will fill it in. Otherwise it will fill in the default
|
|
||||||
// icon.
|
|
||||||
this._setIcon(iconBox, info, handle);
|
|
||||||
|
|
||||||
// Asynchronously load the real avatar if we don't have it yet.
|
|
||||||
if (info.tokens[handle] == null) {
|
|
||||||
info.connectionAvatars.GetKnownAvatarTokensRemote([handle], Lang.bind(this,
|
|
||||||
function (tokens, err) {
|
|
||||||
let token = tokens && tokens[handle] ? tokens[handle] : '';
|
|
||||||
this._avatarUpdated(conn, handle, token);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return iconBox;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(ContactManager.prototype);
|
|
||||||
|
|
||||||
|
|
||||||
function Source(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) {
|
|
||||||
this._init(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Source.prototype = {
|
|
||||||
__proto__: MessageTray.Source.prototype,
|
|
||||||
|
|
||||||
_init: function(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) {
|
|
||||||
MessageTray.Source.prototype._init.call(this, targetId);
|
|
||||||
|
|
||||||
this._accountPath = accountPath;
|
|
||||||
|
|
||||||
let connName = Telepathy.pathToName(connPath);
|
|
||||||
this._conn = new Telepathy.Connection(DBus.session, connName, connPath);
|
|
||||||
this._channel = new Telepathy.Channel(DBus.session, connName, channelPath);
|
|
||||||
this._closedId = this._channel.connect('Closed', Lang.bind(this, this._channelClosed));
|
|
||||||
|
|
||||||
this._targetHandle = targetHandle;
|
|
||||||
this._targetHandleType = targetHandleType;
|
|
||||||
this._targetId = targetId;
|
|
||||||
|
|
||||||
this.name = this._targetId;
|
|
||||||
if (targetHandleType == Telepathy.HandleType.CONTACT) {
|
|
||||||
let aliasing = new Telepathy.ConnectionAliasing(DBus.session, connName, connPath);
|
|
||||||
aliasing.RequestAliasesRemote([this._targetHandle], Lang.bind(this,
|
|
||||||
function (aliases, err) {
|
|
||||||
if (aliases && aliases.length)
|
|
||||||
this.name = aliases[0];
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since we only create sources when receiving a message, this
|
|
||||||
// is a plausible default
|
|
||||||
this._presence = Telepathy.ConnectionPresenceType.AVAILABLE;
|
|
||||||
|
|
||||||
this._channelText = new Telepathy.ChannelText(DBus.session, connName, channelPath);
|
|
||||||
this._receivedId = this._channelText.connect('Received', Lang.bind(this, this._messageReceived));
|
|
||||||
|
|
||||||
this._channelText.ListPendingMessagesRemote(false, Lang.bind(this, this._gotPendingMessages));
|
|
||||||
},
|
|
||||||
|
|
||||||
createIcon: function(size) {
|
|
||||||
return contactManager.createAvatar(this._conn, this._targetHandle, size);
|
|
||||||
},
|
|
||||||
|
|
||||||
clicked: function() {
|
|
||||||
channelDispatcher.EnsureChannelRemote(this._accountPath,
|
|
||||||
{ 'org.freedesktop.Telepathy.Channel.ChannelType': Telepathy.CHANNEL_TEXT_NAME,
|
|
||||||
'org.freedesktop.Telepathy.Channel.TargetHandle': this._targetHandle,
|
|
||||||
'org.freedesktop.Telepathy.Channel.TargetHandleType': this._targetHandleType },
|
|
||||||
global.get_current_time(),
|
|
||||||
'',
|
|
||||||
Lang.bind(this, this._gotChannelRequest));
|
|
||||||
|
|
||||||
MessageTray.Source.prototype.clicked.call(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotChannelRequest: function (chanReqPath, ex) {
|
|
||||||
if (ex) {
|
|
||||||
log ('EnsureChannelRemote failed? ' + ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let chanReq = new Telepathy.ChannelRequest(DBus.session, Telepathy.CHANNEL_DISPATCHER_NAME, chanReqPath);
|
|
||||||
chanReq.ProceedRemote();
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotPendingMessages: function(msgs, err) {
|
|
||||||
if (!msgs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < msgs.length; i++)
|
|
||||||
this._messageReceived.apply(this, [this._channel].concat(msgs[i]));
|
|
||||||
},
|
|
||||||
|
|
||||||
_channelClosed: function() {
|
|
||||||
this._channel.disconnect(this._closedId);
|
|
||||||
this._channelText.disconnect(this._receivedId);
|
|
||||||
this.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
_ensureNotification: function() {
|
|
||||||
if (!Main.messageTray.contains(this))
|
|
||||||
Main.messageTray.add(this);
|
|
||||||
|
|
||||||
if (!this._notification)
|
|
||||||
this._notification = new Notification(this._targetId, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
_messageReceived: function(channel, id, timestamp, sender,
|
|
||||||
type, flags, text) {
|
|
||||||
this._ensureNotification();
|
|
||||||
this._notification.appendMessage(text);
|
|
||||||
this.notify(this._notification);
|
|
||||||
},
|
|
||||||
|
|
||||||
respond: function(text) {
|
|
||||||
this._channelText.SendRemote(Telepathy.ChannelTextMessageType.NORMAL, text);
|
|
||||||
},
|
|
||||||
|
|
||||||
setPresence: function(presence, message) {
|
|
||||||
let msg, notify;
|
|
||||||
|
|
||||||
if (presence == Telepathy.ConnectionPresenceType.AVAILABLE) {
|
|
||||||
msg = _("%s is online.").format(this.name);
|
|
||||||
notify = (this._presence == Telepathy.ConnectionPresenceType.OFFLINE);
|
|
||||||
} else if (presence == Telepathy.ConnectionPresenceType.OFFLINE ||
|
|
||||||
presence == Telepathy.ConnectionPresenceType.EXTENDED_AWAY) {
|
|
||||||
presence = Telepathy.ConnectionPresenceType.OFFLINE;
|
|
||||||
msg = _("%s is offline.").format(this.name);
|
|
||||||
notify = (this._presence != Telepathy.ConnectionPresenceType.OFFLINE);
|
|
||||||
} else if (presence == Telepathy.ConnectionPresenceType.AWAY) {
|
|
||||||
msg = _("%s is away.").format(this.name);
|
|
||||||
notify = false;
|
|
||||||
} else if (presence == Telepathy.ConnectionPresenceType.BUSY) {
|
|
||||||
msg = _("%s is busy.").format(this.name);
|
|
||||||
notify = false;
|
|
||||||
} else
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._presence = presence;
|
|
||||||
|
|
||||||
if (message)
|
|
||||||
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
|
|
||||||
|
|
||||||
this._ensureNotification();
|
|
||||||
this._notification.appendMessage(msg, true);
|
|
||||||
if (notify)
|
|
||||||
this.notify(this._notification);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Notification(id, source) {
|
|
||||||
this._init(id, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification.prototype = {
|
|
||||||
__proto__: MessageTray.Notification.prototype,
|
|
||||||
|
|
||||||
_init: function(id, source) {
|
|
||||||
MessageTray.Notification.prototype._init.call(this, id, source, source.name);
|
|
||||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
|
||||||
|
|
||||||
this._responseEntry = new St.Entry({ style_class: 'chat-response' });
|
|
||||||
this._responseEntry.clutter_text.connect('key-focus-in', Lang.bind(this, this._onEntryFocused));
|
|
||||||
this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated));
|
|
||||||
this.setActionArea(this._responseEntry);
|
|
||||||
|
|
||||||
this._history = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
appendMessage: function(text, asTitle) {
|
|
||||||
if (asTitle)
|
|
||||||
this.update(text);
|
|
||||||
else
|
|
||||||
this.update(this.source.name, text);
|
|
||||||
this._append(text, 'chat-received');
|
|
||||||
},
|
|
||||||
|
|
||||||
_append: function(text, style) {
|
|
||||||
let body = this.addBody(text);
|
|
||||||
body.add_style_class_name(style);
|
|
||||||
this.scrollTo(St.Side.BOTTOM);
|
|
||||||
|
|
||||||
let now = new Date().getTime() / 1000;
|
|
||||||
this._history.unshift({ actor: body, time: now });
|
|
||||||
|
|
||||||
if (this._history.length > 1) {
|
|
||||||
// Keep the scrollback from growing too long. If the most
|
|
||||||
// recent message (before the one we just added) is within
|
|
||||||
// SCROLLBACK_RECENT_TIME, we will keep
|
|
||||||
// SCROLLBACK_RECENT_LENGTH previous messages. Otherwise
|
|
||||||
// we'll keep SCROLLBACK_IDLE_LENGTH messages.
|
|
||||||
|
|
||||||
let lastMessageTime = this._history[1].time;
|
|
||||||
let maxLength = (lastMessageTime < now - SCROLLBACK_RECENT_TIME) ?
|
|
||||||
SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
|
|
||||||
if (this._history.length > maxLength) {
|
|
||||||
let expired = this._history.splice(maxLength);
|
|
||||||
for (let i = 0; i < expired.length; i++)
|
|
||||||
expired[i].actor.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onButtonPress: function(notification, event) {
|
|
||||||
if (!this._active)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let source = event.get_source ();
|
|
||||||
while (source) {
|
|
||||||
if (source == notification)
|
|
||||||
return false;
|
|
||||||
source = source.get_parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// @source is outside @notification, which has to mean that
|
|
||||||
// we have a pointer grab, and the user clicked outside the
|
|
||||||
// notification, so we should deactivate.
|
|
||||||
this._deactivate();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onEntryFocused: function() {
|
|
||||||
if (this._active)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Main.pushModal(this.actor))
|
|
||||||
return;
|
|
||||||
Clutter.grab_pointer(this.actor);
|
|
||||||
|
|
||||||
this._active = true;
|
|
||||||
Main.messageTray.lock();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onEntryActivated: function() {
|
|
||||||
let text = this._responseEntry.get_text();
|
|
||||||
if (text == '') {
|
|
||||||
this._deactivate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._responseEntry.set_text('');
|
|
||||||
this._append(text, 'chat-sent');
|
|
||||||
this.source.respond(text);
|
|
||||||
},
|
|
||||||
|
|
||||||
_deactivate: function() {
|
|
||||||
if (this._active) {
|
|
||||||
Clutter.ungrab_pointer(this.actor);
|
|
||||||
Main.popModal(this.actor);
|
|
||||||
global.stage.set_key_focus(null);
|
|
||||||
|
|
||||||
// We have to do this after calling popModal(), because
|
|
||||||
// that will return the keyboard focus to
|
|
||||||
// this._responseEntry (because that's where it was when
|
|
||||||
// pushModal() was called), which will cause
|
|
||||||
// _onEntryFocused() to be called again, but we don't want
|
|
||||||
// it to do anything.
|
|
||||||
this._active = false;
|
|
||||||
|
|
||||||
Main.messageTray.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -46,7 +46,7 @@ let slowDownFactor = 1.0;
|
|||||||
|
|
||||||
// Called from Main.start
|
// Called from Main.start
|
||||||
function init() {
|
function init() {
|
||||||
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
|
let slowdownEnv = GLib.getenv("GNOME_SHELL_SLOWDOWN_FACTOR");
|
||||||
if (slowdownEnv) {
|
if (slowdownEnv) {
|
||||||
let factor = parseFloat(slowdownEnv);
|
let factor = parseFloat(slowdownEnv);
|
||||||
if (!isNaN(factor) && factor > 0.0)
|
if (!isNaN(factor) && factor > 0.0)
|
||||||
@ -178,7 +178,7 @@ function resumeTweens() {
|
|||||||
function registerSpecialProperty(name, getFunction, setFunction,
|
function registerSpecialProperty(name, getFunction, setFunction,
|
||||||
parameters, preProcessFunction) {
|
parameters, preProcessFunction) {
|
||||||
Tweener.registerSpecialProperty(name, getFunction, setFunction,
|
Tweener.registerSpecialProperty(name, getFunction, setFunction,
|
||||||
parameters, preProcessFunction);
|
parameters, preProcessFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
|
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
|
||||||
@ -190,7 +190,7 @@ function registerSpecialPropertySplitter(name, splitFunction, parameters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The 'FrameTicker' object is an object used to feed new frames to
|
// The "FrameTicker" object is an object used to feed new frames to
|
||||||
// Tweener so it can update values and redraw. The default frame
|
// Tweener so it can update values and redraw. The default frame
|
||||||
// ticker for Tweener just uses a simple timeout at a fixed frame rate
|
// ticker for Tweener just uses a simple timeout at a fixed frame rate
|
||||||
// and has no idea of "catching up" by dropping frames.
|
// and has no idea of "catching up" by dropping frames.
|
||||||
@ -243,14 +243,12 @@ ClutterFrameTicker.prototype = {
|
|||||||
|
|
||||||
start : function() {
|
start : function() {
|
||||||
this._timeline.start();
|
this._timeline.start();
|
||||||
global.begin_work();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
stop : function() {
|
stop : function() {
|
||||||
this._timeline.stop();
|
this._timeline.stop();
|
||||||
this._startTime = -1;
|
this._startTime = -1;
|
||||||
this._currentTime = -1;
|
this._currentTime = -1;
|
||||||
global.end_work();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
367
js/ui/widget.js
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
const DocInfo = imports.misc.docInfo;
|
||||||
|
|
||||||
|
const COLLAPSED_WIDTH = 24;
|
||||||
|
const EXPANDED_WIDTH = 200;
|
||||||
|
|
||||||
|
const STATE_EXPANDED = 0;
|
||||||
|
const STATE_COLLAPSING = 1;
|
||||||
|
const STATE_COLLAPSED = 2;
|
||||||
|
const STATE_EXPANDING = 3;
|
||||||
|
const STATE_POPPING_OUT = 4;
|
||||||
|
const STATE_POPPED_OUT = 5;
|
||||||
|
const STATE_POPPING_IN = 6;
|
||||||
|
|
||||||
|
function Widget() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget.prototype = {
|
||||||
|
// _init():
|
||||||
|
//
|
||||||
|
// Your widget constructor. Your constructor function should look
|
||||||
|
// like:
|
||||||
|
//
|
||||||
|
// function MyWidgetType() {
|
||||||
|
// this._init.apply(this, arguments);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// and your _init method should start by doing:
|
||||||
|
//
|
||||||
|
// Widget.Widget.prototype._init.apply(this, arguments);
|
||||||
|
//
|
||||||
|
// The _init method must define a field named "actor" containing
|
||||||
|
// the Clutter.Actor to show in expanded mode. This actor will be
|
||||||
|
// clipped to Widget.EXPANDED_WIDTH. Most widgets will also define
|
||||||
|
// a field named "title" containing the title string to show above
|
||||||
|
// the widget in the sidebar.
|
||||||
|
//
|
||||||
|
// If you want to have a separate collapsed view, you can define a
|
||||||
|
// field "collapsedActor" containing the Clutter.Actor to show in
|
||||||
|
// that mode. (It may be the same actor.) This actor will be
|
||||||
|
// clipped to Widget.COLLAPSED_WIDTH, and will normally end up
|
||||||
|
// having the same height as the main actor.
|
||||||
|
//
|
||||||
|
// If you do not set a collapsedActor, then you must set a title,
|
||||||
|
// since that is what will be displayed in collapsed mode, and
|
||||||
|
// in this case (and only in this case), the widget will support
|
||||||
|
// pop-out, meaning that if the user hovers over its title while
|
||||||
|
// the sidebar is collapsed, the widget's expanded view will pop
|
||||||
|
// out of the sidebar until either the cursor moves out of it,
|
||||||
|
// or else the widget calls this.activated() on itself.
|
||||||
|
_init: function (initialState) {
|
||||||
|
this.state = initialState;
|
||||||
|
},
|
||||||
|
|
||||||
|
// destroy():
|
||||||
|
//
|
||||||
|
// Optional. Will be called when the widget is removed from the
|
||||||
|
// sidebar. (Note that you don't need to destroy the actors,
|
||||||
|
// since they will be destroyed for you.)
|
||||||
|
|
||||||
|
// collapse():
|
||||||
|
//
|
||||||
|
// Optional. Called during the sidebar collapse process, at the
|
||||||
|
// point when the expanded sidebar has slid offscreen, but the
|
||||||
|
// collapsed sidebar has not yet slid onscreen.
|
||||||
|
|
||||||
|
// expand():
|
||||||
|
//
|
||||||
|
// Optional. Called during the sidebar expand process, at the
|
||||||
|
// point when the collapsed sidebar has slid offscreen, but the
|
||||||
|
// expanded sidebar has not yet slid onscreen.
|
||||||
|
|
||||||
|
// activated():
|
||||||
|
//
|
||||||
|
// Emits the "activated" signal for you, which will cause pop-out
|
||||||
|
// to end.
|
||||||
|
activated: function() {
|
||||||
|
this.emit('activated');
|
||||||
|
}
|
||||||
|
|
||||||
|
// state:
|
||||||
|
//
|
||||||
|
// A field set on your widget by the sidebar. Will contain one of
|
||||||
|
// the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED).
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(Widget.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
function ClockWidget() {
|
||||||
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClockWidget.prototype = {
|
||||||
|
__proto__ : Widget.prototype,
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
Widget.prototype._init.apply(this, arguments);
|
||||||
|
|
||||||
|
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
|
||||||
|
text: "",
|
||||||
|
// Give an explicit height to ensure
|
||||||
|
// it's the same in both modes
|
||||||
|
height: COLLAPSED_WIDTH });
|
||||||
|
|
||||||
|
this.collapsedActor = new Clutter.CairoTexture({ width: COLLAPSED_WIDTH,
|
||||||
|
height: COLLAPSED_WIDTH,
|
||||||
|
surface_width: COLLAPSED_WIDTH,
|
||||||
|
surface_height: COLLAPSED_WIDTH });
|
||||||
|
|
||||||
|
this._update();
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
if (this.timer)
|
||||||
|
Mainloop.source_remove(this.timer);
|
||||||
|
},
|
||||||
|
|
||||||
|
expand: function() {
|
||||||
|
this._update();
|
||||||
|
},
|
||||||
|
|
||||||
|
collapse: function() {
|
||||||
|
this._update();
|
||||||
|
},
|
||||||
|
|
||||||
|
_update: function() {
|
||||||
|
let time = new Date();
|
||||||
|
let msec_remaining = 60000 - (1000 * time.getSeconds() +
|
||||||
|
time.getMilliseconds());
|
||||||
|
if (msec_remaining < 500) {
|
||||||
|
time.setMinutes(time.getMinutes() + 1);
|
||||||
|
msec_remaining += 60000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state == STATE_COLLAPSED || this.state == STATE_COLLAPSING)
|
||||||
|
this._updateCairo(time);
|
||||||
|
else
|
||||||
|
this._updateText(time);
|
||||||
|
|
||||||
|
if (this.timer)
|
||||||
|
Mainloop.source_remove(this.timer);
|
||||||
|
this.timer = Mainloop.timeout_add(msec_remaining, Lang.bind(this, this._update));
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateText: function(time) {
|
||||||
|
// Translators: This is a time format.
|
||||||
|
this.actor.set_text(time.toLocaleFormat(_("%H:%M")));
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateCairo: function(time) {
|
||||||
|
Shell.draw_clock(this.collapsedActor,
|
||||||
|
time.getHours() % 12,
|
||||||
|
time.getMinutes());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const ITEM_ICON_SIZE = 48;
|
||||||
|
const ITEM_PADDING = 1;
|
||||||
|
const ITEM_SPACING = 4;
|
||||||
|
|
||||||
|
const ITEM_BG_COLOR = new Clutter.Color();
|
||||||
|
ITEM_BG_COLOR.from_pixel(0x00000000);
|
||||||
|
const ITEM_NAME_COLOR = new Clutter.Color();
|
||||||
|
ITEM_NAME_COLOR.from_pixel(0x000000ff);
|
||||||
|
|
||||||
|
function LauncherWidget() {
|
||||||
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
LauncherWidget.prototype = {
|
||||||
|
__proto__ : Widget.prototype,
|
||||||
|
|
||||||
|
addItem : function(info) {
|
||||||
|
let item = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
width: EXPANDED_WIDTH,
|
||||||
|
height: ITEM_ICON_SIZE,
|
||||||
|
padding: ITEM_PADDING,
|
||||||
|
spacing: ITEM_SPACING,
|
||||||
|
reactive: true });
|
||||||
|
item._info = info;
|
||||||
|
item.append(info.createIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
|
||||||
|
item.append(new Clutter.Text({ color: ITEM_NAME_COLOR,
|
||||||
|
font_name: "Sans 14px",
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
text: info.name }),
|
||||||
|
Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this.actor.append(item, Big.BoxPackFlags.NONE);
|
||||||
|
item.connect('button-press-event', Lang.bind(this, this._buttonPress));
|
||||||
|
item.connect('button-release-event', Lang.bind(this, this._buttonRelease));
|
||||||
|
item.connect('leave-event', Lang.bind(this, this._leave));
|
||||||
|
item.connect('enter-event', Lang.bind(this, this._enter));
|
||||||
|
|
||||||
|
if (!this.collapsedActor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item = new Big.Box({ width: COLLAPSED_WIDTH,
|
||||||
|
height: COLLAPSED_WIDTH,
|
||||||
|
padding: ITEM_PADDING,
|
||||||
|
reactive: true });
|
||||||
|
item._info = info;
|
||||||
|
item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
|
||||||
|
Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
|
||||||
|
item.connect('button-press-event', Lang.bind(this, this._buttonPress));
|
||||||
|
item.connect('button-release-event', Lang.bind(this, this._buttonRelease));
|
||||||
|
item.connect('leave-event', Lang.bind(this, this._leave));
|
||||||
|
item.connect('enter-event', Lang.bind(this, this._enter));
|
||||||
|
},
|
||||||
|
|
||||||
|
clear : function() {
|
||||||
|
let children, i;
|
||||||
|
|
||||||
|
children = this.actor.get_children();
|
||||||
|
for (i = 0; i < children.length; i++)
|
||||||
|
children[i].destroy();
|
||||||
|
|
||||||
|
if (this.collapsedActor) {
|
||||||
|
children = this.collapsedActor.get_children();
|
||||||
|
for (i = 0; i < children.length; i++)
|
||||||
|
children[i].destroy();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_buttonPress : function(item) {
|
||||||
|
Clutter.grab_pointer(item);
|
||||||
|
item._buttonDown = true;
|
||||||
|
item._inItem = true;
|
||||||
|
this._updateItemState(item);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_leave : function(item, evt) {
|
||||||
|
if (evt.get_source() == item && item._buttonDown) {
|
||||||
|
item._inItem = false;
|
||||||
|
this._updateItemState(item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_enter : function(item, evt) {
|
||||||
|
if (evt.get_source() == item && item._buttonDown) {
|
||||||
|
item._inItem = true;
|
||||||
|
this._updateItemState(item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_buttonRelease : function(item) {
|
||||||
|
Clutter.ungrab_pointer(item);
|
||||||
|
item._buttonDown = false;
|
||||||
|
this._updateItemState(item);
|
||||||
|
|
||||||
|
if (item._inItem) {
|
||||||
|
item._info.launch();
|
||||||
|
this.activated();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateItemState : function(item) {
|
||||||
|
if (item._buttonDown && item._inItem) {
|
||||||
|
item.padding_top = item.padding_left = 2 * ITEM_PADDING;
|
||||||
|
item.padding_bottom = item.padding_right = 0;
|
||||||
|
} else
|
||||||
|
item.padding = ITEM_PADDING;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function AppsWidgetInfo(appInfo) {
|
||||||
|
this._init(appInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppsWidgetInfo.prototype = {
|
||||||
|
_init : function(appInfo) {
|
||||||
|
this._info = appInfo;
|
||||||
|
this.name = appInfo.get_name();
|
||||||
|
},
|
||||||
|
|
||||||
|
createIcon : function(size) {
|
||||||
|
return this._info.create_icon_texture(size);
|
||||||
|
},
|
||||||
|
|
||||||
|
launch : function() {
|
||||||
|
this._info.launch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function AppsWidget() {
|
||||||
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppsWidget.prototype = {
|
||||||
|
__proto__ : LauncherWidget.prototype,
|
||||||
|
|
||||||
|
_init : function() {
|
||||||
|
Widget.prototype._init.apply(this, arguments);
|
||||||
|
|
||||||
|
this.title = _("Applications");
|
||||||
|
this.actor = new Big.Box({ spacing: 2 });
|
||||||
|
this.collapsedActor = new Big.Box({ spacing: 2});
|
||||||
|
|
||||||
|
let appSystem = Shell.AppSystem.get_default();
|
||||||
|
let apps = appSystem.get_favorites();
|
||||||
|
for (let i = 0; i < apps.length; i++) {
|
||||||
|
let app = appSystem.lookup_cached_app(apps[i]);
|
||||||
|
if (!app)
|
||||||
|
continue;
|
||||||
|
this.addItem(new AppsWidgetInfo(app));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function RecentDocsWidget() {
|
||||||
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecentDocsWidget.prototype = {
|
||||||
|
__proto__ : LauncherWidget.prototype,
|
||||||
|
|
||||||
|
_init : function() {
|
||||||
|
Widget.prototype._init.apply(this, arguments);
|
||||||
|
|
||||||
|
this.title = _("Recent Documents");
|
||||||
|
this.actor = new Big.Box({ spacing: 2 });
|
||||||
|
|
||||||
|
this._recentManager = Gtk.RecentManager.get_default();
|
||||||
|
this._recentManager.connect('changed', Lang.bind(this, this._recentChanged));
|
||||||
|
this._recentChanged();
|
||||||
|
},
|
||||||
|
|
||||||
|
_recentChanged: function() {
|
||||||
|
let i;
|
||||||
|
|
||||||
|
this.clear();
|
||||||
|
|
||||||
|
let items = [];
|
||||||
|
let docs = this._recentManager.get_items();
|
||||||
|
for (i = 0; i < docs.length; i++) {
|
||||||
|
let docInfo = new DocInfo.DocInfo (docs[i]);
|
||||||
|
|
||||||
|
if (docInfo.exists())
|
||||||
|
items.push(docInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
items.sort(function (a,b) { return b.timestamp - a.timestamp; });
|
||||||
|
for (i = 0; i < Math.min(items.length, 5); i++)
|
||||||
|
this.addItem(items[i]);
|
||||||
|
}
|
||||||
|
};
|
381
js/ui/widgetBox.js
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
const Widget = imports.ui.widget;
|
||||||
|
|
||||||
|
const WIDGETBOX_BG_COLOR = new Clutter.Color();
|
||||||
|
WIDGETBOX_BG_COLOR.from_pixel(0xf0f0f0ff);
|
||||||
|
const BLACK = new Clutter.Color();
|
||||||
|
BLACK.from_pixel(0x000000ff);
|
||||||
|
|
||||||
|
const WIDGETBOX_PADDING = 2;
|
||||||
|
const ANIMATION_TIME = 0.5;
|
||||||
|
const POP_IN_LAG = 250; /* milliseconds */
|
||||||
|
|
||||||
|
function WidgetBox(widget, expanded) {
|
||||||
|
this._init(widget, expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetBox.prototype = {
|
||||||
|
_init: function(widget, expanded) {
|
||||||
|
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
|
||||||
|
|
||||||
|
if (widget instanceof Widget.Widget) {
|
||||||
|
this._widget = widget;
|
||||||
|
this._widget.state = this.state;
|
||||||
|
} else {
|
||||||
|
let ctor = this._ctorFromName(widget);
|
||||||
|
this._widget = new ctor(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._widget.actor)
|
||||||
|
throw new Error("widget has no actor");
|
||||||
|
else if (!this._widget.title && !this._widget.collapsedActor)
|
||||||
|
throw new Error("widget has neither title nor collapsedActor");
|
||||||
|
|
||||||
|
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
|
||||||
|
|
||||||
|
// The structure of a WidgetBox:
|
||||||
|
//
|
||||||
|
// The top level is a Clutter.Group, which exists to make
|
||||||
|
// pop-out work correctly; when another widget pops out, its
|
||||||
|
// width will increase, which will in turn cause the sidebar's
|
||||||
|
// width to increase, which will cause the sidebar to increase
|
||||||
|
// the width of each of its children (the WidgetBoxes). But we
|
||||||
|
// don't want the non-popped-out widgets to expand, so we make
|
||||||
|
// the top-level actor be a Clutter.Group, which will accept
|
||||||
|
// the new width from the Sidebar, but not impose it on its
|
||||||
|
// own child.
|
||||||
|
//
|
||||||
|
// Inside the toplevel group is a horizontal Big.Box
|
||||||
|
// containing 2 Clutter.Groups; one for the collapsed state
|
||||||
|
// (cgroup) and one for the expanded state (egroup). Each
|
||||||
|
// group contains a single vertical Big.Box (cbox and ebox
|
||||||
|
// respectively), which have the appropriate fixed width. The
|
||||||
|
// cbox contains either the collapsed widget actor or else the
|
||||||
|
// rotated title. The ebox contains the horizontal title (if
|
||||||
|
// any), separator line, and the expanded widget actor. (If
|
||||||
|
// the widget doesn't have a collapsed actor, and therefore
|
||||||
|
// supports pop-out, then it will also have a vertical line
|
||||||
|
// between the two groups, which will only be shown during
|
||||||
|
// pop-out.)
|
||||||
|
//
|
||||||
|
// In the expanded view, cgroup is hidden and egroup is shown.
|
||||||
|
// When animating to the collapsed view, first the ebox is
|
||||||
|
// slid offscreen by giving it increasingly negative x
|
||||||
|
// coordinates within egroup. Then once it's fully offscreen,
|
||||||
|
// we hide egroup, show cgroup, and slide cbox back in in the
|
||||||
|
// same way.
|
||||||
|
//
|
||||||
|
// The pop-out view works similarly to the second half of the
|
||||||
|
// collapsed-to-expanded transition, except that the
|
||||||
|
// horizontal title gets hidden to avoid duplication.
|
||||||
|
|
||||||
|
this.actor = new Clutter.Group();
|
||||||
|
this._hbox = new Big.Box({ background_color: WIDGETBOX_BG_COLOR,
|
||||||
|
padding_top: WIDGETBOX_PADDING,
|
||||||
|
padding_bottom: WIDGETBOX_PADDING,
|
||||||
|
padding_right: WIDGETBOX_PADDING,
|
||||||
|
// Left padding is here to make up for
|
||||||
|
// the X offset used for the sidebar
|
||||||
|
// to hide its rounded corners
|
||||||
|
padding_left: 2 * WIDGETBOX_PADDING,
|
||||||
|
spacing: WIDGETBOX_PADDING,
|
||||||
|
corner_radius: WIDGETBOX_PADDING,
|
||||||
|
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
reactive: true });
|
||||||
|
this.actor.add_actor(this._hbox);
|
||||||
|
|
||||||
|
this._cgroup = new Clutter.Group({ clip_to_allocation: true });
|
||||||
|
this._hbox.append(this._cgroup, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._cbox = new Big.Box({ width: Widget.COLLAPSED_WIDTH,
|
||||||
|
clip_to_allocation: true });
|
||||||
|
this._cgroup.add_actor(this._cbox);
|
||||||
|
|
||||||
|
if (this._widget.collapsedActor) {
|
||||||
|
if (this._widget.collapsedActor == this._widget.actor)
|
||||||
|
this._singleActor = true;
|
||||||
|
else {
|
||||||
|
this._cbox.append(this._widget.collapsedActor,
|
||||||
|
Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let vtitle = new Clutter.Text({ font_name: "Sans 16px",
|
||||||
|
text: this._widget.title,
|
||||||
|
rotation_angle_z: -90.0 });
|
||||||
|
let signalId = vtitle.connect('notify::allocation',
|
||||||
|
function () {
|
||||||
|
vtitle.disconnect(signalId);
|
||||||
|
vtitle.set_anchor_point(vtitle.natural_width, 0);
|
||||||
|
vtitle.set_size(vtitle.natural_height,
|
||||||
|
vtitle.natural_width);
|
||||||
|
});
|
||||||
|
this._vtitle = vtitle;
|
||||||
|
this._cbox.append(this._vtitle, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._vline = new Clutter.Rectangle({ color: BLACK, width: 1 });
|
||||||
|
this._hbox.append(this._vline, Big.BoxPackFlags.NONE);
|
||||||
|
this._vline.hide();
|
||||||
|
|
||||||
|
// Set up pop-out
|
||||||
|
this._eventHandler = this._hbox.connect('captured-event',
|
||||||
|
Lang.bind(this, this._popEventHandler));
|
||||||
|
this._activationHandler = this._widget.connect('activated',
|
||||||
|
Lang.bind(this, this._activationHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._egroup = new Clutter.Group({ clip_to_allocation: true });
|
||||||
|
this._hbox.append(this._egroup, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._ebox = new Big.Box({ spacing: WIDGETBOX_PADDING,
|
||||||
|
width: Widget.EXPANDED_WIDTH,
|
||||||
|
clip_to_allocation: true });
|
||||||
|
this._egroup.add_actor(this._ebox);
|
||||||
|
|
||||||
|
if (this._widget.title) {
|
||||||
|
this._htitle = new Clutter.Text({ font_name: "Sans 16px",
|
||||||
|
text: this._widget.title });
|
||||||
|
this._ebox.append(this._htitle, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._hline = new Clutter.Rectangle({ color: BLACK, height: 1 });
|
||||||
|
this._ebox.append(this._hline, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
if (expanded)
|
||||||
|
this._setWidgetExpanded();
|
||||||
|
else
|
||||||
|
this._setWidgetCollapsed();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Given a name like "imports.ui.widget.ClockWidget", turn that
|
||||||
|
// into a constructor function
|
||||||
|
_ctorFromName: function(name) {
|
||||||
|
// Make sure it's a valid import
|
||||||
|
if (!name.match(/^imports(\.[a-zA-Z0-9_]+)+$/))
|
||||||
|
throw new Error("widget name must start with 'imports.'");
|
||||||
|
if (name.match(/^imports\.gi\./))
|
||||||
|
throw new Error("cannot import widget from GIR");
|
||||||
|
|
||||||
|
let ctor = eval(name);
|
||||||
|
|
||||||
|
// Make sure it's really a constructor
|
||||||
|
if (!ctor || typeof(ctor) != "function")
|
||||||
|
throw new Error("widget name is not a constructor");
|
||||||
|
|
||||||
|
// Make sure it's a widget
|
||||||
|
let proto = ctor.prototype;
|
||||||
|
while (proto && proto != Widget.Widget.prototype)
|
||||||
|
proto = proto.__proto__;
|
||||||
|
if (!proto)
|
||||||
|
throw new Error("widget does not inherit from Widget prototype");
|
||||||
|
|
||||||
|
return ctor;
|
||||||
|
},
|
||||||
|
|
||||||
|
expand: function() {
|
||||||
|
Tweener.addTween(this._cbox, { x: -Widget.COLLAPSED_WIDTH,
|
||||||
|
time: ANIMATION_TIME / 2,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._expandPart1Complete,
|
||||||
|
onCompleteScope: this });
|
||||||
|
this.state = this._widget.state = Widget.STATE_EXPANDING;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setWidgetExpanded: function() {
|
||||||
|
this._cgroup.hide();
|
||||||
|
this._egroup.show();
|
||||||
|
|
||||||
|
if (this._singleActor) {
|
||||||
|
this._widget.actor.unparent();
|
||||||
|
this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._htitle) {
|
||||||
|
this._htitle.show();
|
||||||
|
this._hline.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_expandPart1Complete: function() {
|
||||||
|
this._cbox.x = 0;
|
||||||
|
this._setWidgetExpanded();
|
||||||
|
|
||||||
|
if (this._widget.expand) {
|
||||||
|
try {
|
||||||
|
this._widget.expand();
|
||||||
|
} catch (e) {
|
||||||
|
logError(e, 'Widget failed to expand');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._ebox.x = -Widget.EXPANDED_WIDTH;
|
||||||
|
Tweener.addTween(this._ebox, { x: 0,
|
||||||
|
time: ANIMATION_TIME / 2,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._expandComplete,
|
||||||
|
onCompleteScope: this });
|
||||||
|
},
|
||||||
|
|
||||||
|
_expandComplete: function() {
|
||||||
|
this.state = this._widget.state = Widget.STATE_EXPANDED;
|
||||||
|
},
|
||||||
|
|
||||||
|
collapse: function() {
|
||||||
|
Tweener.addTween(this._ebox, { x: -Widget.EXPANDED_WIDTH,
|
||||||
|
time: ANIMATION_TIME / 2,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._collapsePart1Complete,
|
||||||
|
onCompleteScope: this });
|
||||||
|
this.state = this._widget.state = Widget.STATE_COLLAPSING;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setWidgetCollapsed: function() {
|
||||||
|
this._egroup.hide();
|
||||||
|
this._cgroup.show();
|
||||||
|
|
||||||
|
if (this._singleActor) {
|
||||||
|
this._widget.actor.unparent();
|
||||||
|
this._cbox.append(this._widget.actor, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._htitle) {
|
||||||
|
this._htitle.hide();
|
||||||
|
this._hline.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._vtitle)
|
||||||
|
this._cbox.height = this._ebox.height;
|
||||||
|
},
|
||||||
|
|
||||||
|
_collapsePart1Complete: function() {
|
||||||
|
this._ebox.x = 0;
|
||||||
|
this._setWidgetCollapsed();
|
||||||
|
|
||||||
|
if (this._widget.collapse) {
|
||||||
|
try {
|
||||||
|
this._widget.collapse();
|
||||||
|
} catch (e) {
|
||||||
|
logError(e, 'Widget failed to collapse');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._cbox.x = -Widget.COLLAPSED_WIDTH;
|
||||||
|
Tweener.addTween(this._cbox, { x: 0,
|
||||||
|
time: ANIMATION_TIME / 2,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._collapseComplete,
|
||||||
|
onCompleteScope: this });
|
||||||
|
},
|
||||||
|
|
||||||
|
_collapseComplete: function() {
|
||||||
|
this.state = this._widget.state = Widget.STATE_COLLAPSED;
|
||||||
|
},
|
||||||
|
|
||||||
|
_popEventHandler: function(actor, event) {
|
||||||
|
let type = event.type();
|
||||||
|
|
||||||
|
if (type == Clutter.EventType.ENTER) {
|
||||||
|
this._clearPopInTimeout();
|
||||||
|
if (this.state == Widget.STATE_COLLAPSED ||
|
||||||
|
this.state == Widget.STATE_COLLAPSING) {
|
||||||
|
this._popOut();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (type == Clutter.EventType.LEAVE &&
|
||||||
|
(this.state == Widget.STATE_POPPED_OUT ||
|
||||||
|
this.state == Widget.STATE_POPPING_OUT)) {
|
||||||
|
// If moving into another actor within this._hbox, let the
|
||||||
|
// event be propagated
|
||||||
|
let into = event.get_related();
|
||||||
|
while (into) {
|
||||||
|
if (into == this._hbox)
|
||||||
|
return false;
|
||||||
|
into = into.get_parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else, moving out of this._hbox
|
||||||
|
this._setPopInTimeout();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_activationHandler: function() {
|
||||||
|
if (this.state == Widget.STATE_POPPED_OUT)
|
||||||
|
this._popIn();
|
||||||
|
},
|
||||||
|
|
||||||
|
_popOut: function() {
|
||||||
|
if (this.state != Widget.STATE_COLLAPSED &&
|
||||||
|
this.state != Widget.STATE_COLLAPSING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._vline.show();
|
||||||
|
this._egroup.show();
|
||||||
|
this._ebox.x = -Widget.EXPANDED_WIDTH;
|
||||||
|
Tweener.addTween(this._ebox, { x: 0,
|
||||||
|
time: ANIMATION_TIME / 2,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._popOutComplete,
|
||||||
|
onCompleteScope: this });
|
||||||
|
this.state = this._widget.state = Widget.STATE_POPPING_OUT;
|
||||||
|
|
||||||
|
Main.chrome.addInputRegionActor(this._hbox);
|
||||||
|
},
|
||||||
|
|
||||||
|
_popOutComplete: function() {
|
||||||
|
this.state = this._widget.state = Widget.STATE_POPPED_OUT;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setPopInTimeout: function() {
|
||||||
|
this._clearPopInTimeout();
|
||||||
|
this._popInTimeout = Mainloop.timeout_add(POP_IN_LAG, Lang.bind(this, function () { this._popIn(); return false; }));
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearPopInTimeout: function() {
|
||||||
|
if (this._popInTimeout) {
|
||||||
|
Mainloop.source_remove(this._popInTimeout);
|
||||||
|
delete this._popInTimeout;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_popIn: function() {
|
||||||
|
this._clearPopInTimeout();
|
||||||
|
|
||||||
|
if (this.state != Widget.STATE_POPPED_OUT &&
|
||||||
|
this.state != Widget.STATE_POPPING_OUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Tweener.addTween(this._ebox, { x: -Widget.EXPANDED_WIDTH,
|
||||||
|
time: ANIMATION_TIME / 2,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._popInComplete,
|
||||||
|
onCompleteScope: this });
|
||||||
|
},
|
||||||
|
|
||||||
|
_popInComplete: function() {
|
||||||
|
this.state = this._widget.state = Widget.STATE_COLLAPSED;
|
||||||
|
this._vline.hide();
|
||||||
|
this._egroup.hide();
|
||||||
|
this._ebox.x = 0;
|
||||||
|
|
||||||
|
Main.chrome.removeInputRegionActor(this._hbox);
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
if (this._widget.destroy)
|
||||||
|
this._widget.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,109 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
|
|
||||||
function WindowAttentionHandler() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowAttentionHandler.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
let display = global.screen.get_display();
|
|
||||||
display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
|
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
|
||||||
this._startupIds = {};
|
|
||||||
tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onStartupSequenceChanged : function(tracker) {
|
|
||||||
let sequences = tracker.get_startup_sequences();
|
|
||||||
this._startupIds = {};
|
|
||||||
for(let i = 0; i < sequences.length; i++) {
|
|
||||||
this._startupIds[sequences[i].get_id()] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_sourceId : function(appId) {
|
|
||||||
return 'attention-' + appId;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getTitle : function(app, window) {
|
|
||||||
if (this._startupIds[window.get_startup_id()])
|
|
||||||
return app.get_name();
|
|
||||||
else
|
|
||||||
return window.title;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getBanner : function(app, window) {
|
|
||||||
if (this._startupIds[window.get_startup_id()])
|
|
||||||
return _("%s has finished starting").format(app.get_name());
|
|
||||||
else
|
|
||||||
return _("'%s' is ready").format(window.title);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onWindowDemandsAttention : function(display, window) {
|
|
||||||
// We don't want to show the notification when the window is already focused,
|
|
||||||
// because this is rather pointless.
|
|
||||||
// Some apps (like GIMP) do things like setting the urgency hint on the
|
|
||||||
// toolbar windows which would result into a notification even though GIMP itself is
|
|
||||||
// focused.
|
|
||||||
// We are just ignoring the hint on skip_taskbar windows for now.
|
|
||||||
// (Which is the same behaviour as with metacity + panel)
|
|
||||||
|
|
||||||
if (!window || window.has_focus() || window.is_skip_taskbar())
|
|
||||||
return;
|
|
||||||
|
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
|
||||||
let app = tracker.get_window_app(window);
|
|
||||||
|
|
||||||
let source = Main.messageTray.getSource(this._sourceId(app.get_id()));
|
|
||||||
if (source == null) {
|
|
||||||
source = new Source(this._sourceId(app.get_id()), app, window);
|
|
||||||
Main.messageTray.add(source);
|
|
||||||
source.connect('clicked', Lang.bind(this, function() { source.destroy(); }));
|
|
||||||
}
|
|
||||||
|
|
||||||
let notification = new MessageTray.Notification(window.get_startup_id(), source, this._getTitle(app, window), this._getBanner(app, window), true);
|
|
||||||
source.notify(notification);
|
|
||||||
|
|
||||||
window.connect('notify::title', Lang.bind(this, function(win) {
|
|
||||||
notification.update(this._getTitle(app, win), this._getBanner(app, win), false);
|
|
||||||
}));
|
|
||||||
window.connect('notify::demands-attention', Lang.bind(this, function() { source.destroy(); }));
|
|
||||||
window.connect('focus', Lang.bind(this, function() { source.destroy(); }));
|
|
||||||
window.connect('unmanaged', Lang.bind(this, function() { source.destroy(); }));
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Source(sourceId, app, window) {
|
|
||||||
this._init(sourceId, app, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
Source.prototype = {
|
|
||||||
__proto__ : MessageTray.Source.prototype,
|
|
||||||
|
|
||||||
_init: function(sourceId, app, window) {
|
|
||||||
MessageTray.Source.prototype._init.call(this, sourceId);
|
|
||||||
this._window = window;
|
|
||||||
this._app = app;
|
|
||||||
},
|
|
||||||
|
|
||||||
createIcon : function(size) {
|
|
||||||
return this._app.create_icon_texture(size);
|
|
||||||
},
|
|
||||||
|
|
||||||
clicked : function() {
|
|
||||||
Main.activateWindow(this._window);
|
|
||||||
MessageTray.Source.prototype.clicked.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
@ -5,10 +5,8 @@ const Lang = imports.lang;
|
|||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const AltTab = imports.ui.altTab;
|
const AltTab = imports.ui.altTab;
|
||||||
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
@ -20,9 +18,8 @@ function WindowManager() {
|
|||||||
|
|
||||||
WindowManager.prototype = {
|
WindowManager.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this._shellwm = global.window_manager;
|
let shellwm = global.window_manager;
|
||||||
|
|
||||||
this._keyBindingHandlers = [];
|
|
||||||
this._minimizing = [];
|
this._minimizing = [];
|
||||||
this._maximizing = [];
|
this._maximizing = [];
|
||||||
this._unmaximizing = [];
|
this._unmaximizing = [];
|
||||||
@ -30,35 +27,21 @@ WindowManager.prototype = {
|
|||||||
this._destroying = [];
|
this._destroying = [];
|
||||||
|
|
||||||
this._switchData = null;
|
this._switchData = null;
|
||||||
this._shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
|
shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
|
||||||
this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
||||||
this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
|
shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
|
||||||
this._shellwm.connect('kill-minimize', Lang.bind(this, this._minimizeWindowDone));
|
shellwm.connect('kill-minimize', Lang.bind(this, this._minimizeWindowDone));
|
||||||
this._shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
|
shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
|
||||||
this._shellwm.connect('kill-maximize', Lang.bind(this, this._maximizeWindowDone));
|
shellwm.connect('kill-maximize', Lang.bind(this, this._maximizeWindowDone));
|
||||||
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
||||||
this._shellwm.connect('kill-unmaximize', Lang.bind(this, this._unmaximizeWindowDone));
|
shellwm.connect('kill-unmaximize', Lang.bind(this, this._unmaximizeWindowDone));
|
||||||
this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
||||||
this._shellwm.connect('kill-map', Lang.bind(this, this._mapWindowDone));
|
shellwm.connect('kill-map', Lang.bind(this, this._mapWindowDone));
|
||||||
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
||||||
this._shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
|
shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
|
||||||
|
|
||||||
this._workspaceSwitcherPopup = null;
|
shellwm.takeover_keybinding('switch_windows');
|
||||||
this.setKeybindingHandler('switch_to_workspace_left', Lang.bind(this, this._showWorkspaceSwitcher));
|
shellwm.connect('keybinding::switch_windows', Lang.bind(this, this._startAppSwitcher));
|
||||||
this.setKeybindingHandler('switch_to_workspace_right', Lang.bind(this, this._showWorkspaceSwitcher));
|
|
||||||
this.setKeybindingHandler('switch_to_workspace_up', Lang.bind(this, this._showWorkspaceSwitcher));
|
|
||||||
this.setKeybindingHandler('switch_to_workspace_down', Lang.bind(this, this._showWorkspaceSwitcher));
|
|
||||||
this.setKeybindingHandler('switch_windows', Lang.bind(this, this._startAppSwitcher));
|
|
||||||
},
|
|
||||||
|
|
||||||
setKeybindingHandler: function(keybinding, handler){
|
|
||||||
if (this._keyBindingHandlers[keybinding])
|
|
||||||
this._shellwm.disconnect(this._keyBindingHandlers[keybinding]);
|
|
||||||
else
|
|
||||||
this._shellwm.takeover_keybinding(keybinding);
|
|
||||||
|
|
||||||
this._keyBindingHandlers[keybinding] =
|
|
||||||
this._shellwm.connect('keybinding::' + keybinding, handler);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_shouldAnimate : function(actor) {
|
_shouldAnimate : function(actor) {
|
||||||
@ -91,19 +74,11 @@ WindowManager.prototype = {
|
|||||||
* maybe TODO: get icon geometry passed through and move the window towards it?
|
* maybe TODO: get icon geometry passed through and move the window towards it?
|
||||||
*/
|
*/
|
||||||
this._minimizing.push(actor);
|
this._minimizing.push(actor);
|
||||||
|
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
let xDest = primary.x;
|
|
||||||
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
|
||||||
xDest += primary.width;
|
|
||||||
|
|
||||||
Tweener.addTween(actor,
|
Tweener.addTween(actor,
|
||||||
{ scale_x: 0.0,
|
{ scale_x: 0.0,
|
||||||
scale_y: 0.0,
|
scale_y: 0.0,
|
||||||
x: xDest,
|
|
||||||
y: 0,
|
|
||||||
time: WINDOW_ANIMATION_TIME,
|
time: WINDOW_ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad',
|
transition: "easeOutQuad",
|
||||||
onComplete: this._minimizeWindowDone,
|
onComplete: this._minimizeWindowDone,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [shellwm, actor],
|
onCompleteParams: [shellwm, actor],
|
||||||
@ -152,15 +127,17 @@ WindowManager.prototype = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.opacity = 0;
|
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
|
||||||
|
actor.set_scale(0.0, 0.0);
|
||||||
actor.show();
|
actor.show();
|
||||||
|
|
||||||
/* Fade window in */
|
/* scale window up from 0x0 to normal size */
|
||||||
this._mapping.push(actor);
|
this._mapping.push(actor);
|
||||||
Tweener.addTween(actor,
|
Tweener.addTween(actor,
|
||||||
{ opacity: 255,
|
{ scale_x: 1.0,
|
||||||
|
scale_y: 1.0,
|
||||||
time: WINDOW_ANIMATION_TIME,
|
time: WINDOW_ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad',
|
transition: "easeOutQuad",
|
||||||
onComplete: this._mapWindowDone,
|
onComplete: this._mapWindowDone,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [shellwm, actor],
|
onCompleteParams: [shellwm, actor],
|
||||||
@ -173,7 +150,8 @@ WindowManager.prototype = {
|
|||||||
_mapWindowDone : function(shellwm, actor) {
|
_mapWindowDone : function(shellwm, actor) {
|
||||||
if (this._removeEffect(this._mapping, actor)) {
|
if (this._removeEffect(this._mapping, actor)) {
|
||||||
Tweener.removeTweens(actor);
|
Tweener.removeTweens(actor);
|
||||||
actor.opacity = 255;
|
actor.set_scale(1.0, 1.0);
|
||||||
|
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||||
shellwm.completed_map(actor);
|
shellwm.completed_map(actor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -258,7 +236,7 @@ WindowManager.prototype = {
|
|||||||
{ x: xDest,
|
{ x: xDest,
|
||||||
y: yDest,
|
y: yDest,
|
||||||
time: WINDOW_ANIMATION_TIME,
|
time: WINDOW_ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad',
|
transition: "easeOutQuad",
|
||||||
onComplete: this._switchWorkspaceDone,
|
onComplete: this._switchWorkspaceDone,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [shellwm]
|
onCompleteParams: [shellwm]
|
||||||
@ -267,7 +245,7 @@ WindowManager.prototype = {
|
|||||||
{ x: 0,
|
{ x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
time: WINDOW_ANIMATION_TIME,
|
time: WINDOW_ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad'
|
transition: "easeOutQuad"
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -294,55 +272,9 @@ WindowManager.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_startAppSwitcher : function(shellwm, binding, window, backwards) {
|
_startAppSwitcher : function(shellwm, binding, window, backwards) {
|
||||||
/* prevent a corner case where both popups show up at once */
|
|
||||||
if (this._workspaceSwitcherPopup != null)
|
|
||||||
this._workspaceSwitcherPopup.actor.hide();
|
|
||||||
|
|
||||||
let tabPopup = new AltTab.AltTabPopup();
|
let tabPopup = new AltTab.AltTabPopup();
|
||||||
|
|
||||||
if (!tabPopup.show(backwards))
|
if (!tabPopup.show(backwards ? -1 : 1))
|
||||||
tabPopup.destroy();
|
tabPopup.destroy();
|
||||||
},
|
|
||||||
|
|
||||||
_showWorkspaceSwitcher : function(shellwm, binding, window, backwards) {
|
|
||||||
/* We don't support this kind of layout */
|
|
||||||
if (binding == 'switch_to_workspace_up' || binding == 'switch_to_workspace_down')
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (global.screen.n_workspaces == 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._workspaceSwitcherPopup == null)
|
|
||||||
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
|
|
||||||
|
|
||||||
if (binding == 'switch_to_workspace_left') {
|
|
||||||
this.actionMoveWorkspaceLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binding == 'switch_to_workspace_right') {
|
|
||||||
this.actionMoveWorkspaceRight();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
actionMoveWorkspaceLeft: function() {
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
if (activeWorkspaceIndex > 0) {
|
|
||||||
global.screen.get_workspace_by_index(activeWorkspaceIndex - 1).activate(global.get_current_time());
|
|
||||||
if (!Main.overview.visible)
|
|
||||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, activeWorkspaceIndex - 1);
|
|
||||||
} else if (!Main.overview.visible) {
|
|
||||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, activeWorkspaceIndex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
actionMoveWorkspaceRight: function() {
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
if (activeWorkspaceIndex < global.screen.n_workspaces - 1) {
|
|
||||||
global.screen.get_workspace_by_index(activeWorkspaceIndex + 1).activate(global.get_current_time());
|
|
||||||
if (!Main.overview.visible)
|
|
||||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, activeWorkspaceIndex + 1);
|
|
||||||
} else if (!Main.overview.visible) {
|
|
||||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, activeWorkspaceIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
|
|
||||||
const ANIMATION_TIME = 0.075;
|
|
||||||
const DISPLAY_TIMEOUT = 600;
|
|
||||||
|
|
||||||
const LEFT = -1;
|
|
||||||
const RIGHT = 1;
|
|
||||||
|
|
||||||
function WorkspaceSwitcherPopup() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkspaceSwitcherPopup.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
this.actor = new Clutter.Group({ reactive: true,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: global.screen_width,
|
|
||||||
height: global.screen_height });
|
|
||||||
Main.uiGroup.add_actor(this.actor);
|
|
||||||
|
|
||||||
this._scaleWidth = global.screen_width / global.screen_height;
|
|
||||||
|
|
||||||
this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' });
|
|
||||||
this._list = new St.BoxLayout({ style_class: 'workspace-switcher' });
|
|
||||||
|
|
||||||
this._container.add(this._list);
|
|
||||||
|
|
||||||
this.actor.add_actor(this._container);
|
|
||||||
|
|
||||||
this._redraw();
|
|
||||||
|
|
||||||
this._position();
|
|
||||||
|
|
||||||
this.actor.show();
|
|
||||||
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
|
|
||||||
},
|
|
||||||
|
|
||||||
_redraw : function(direction, activeWorkspaceIndex) {
|
|
||||||
this._list.destroy_children();
|
|
||||||
|
|
||||||
for (let i = 0; i < global.screen.n_workspaces; i++) {
|
|
||||||
let indicator = null;
|
|
||||||
|
|
||||||
if (i == activeWorkspaceIndex && direction == LEFT)
|
|
||||||
indicator = new St.Bin({ style_class: 'ws-switcher-active-left' });
|
|
||||||
else if(i == activeWorkspaceIndex && direction == RIGHT)
|
|
||||||
indicator = new St.Bin({ style_class: 'ws-switcher-active-right' });
|
|
||||||
else
|
|
||||||
indicator = new St.Bin({ style_class: 'ws-switcher-box' });
|
|
||||||
|
|
||||||
this._list.add(indicator);
|
|
||||||
indicator.set_width(Math.round(indicator.get_height() * this._scaleWidth));
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_position: function() {
|
|
||||||
let focus = global.get_focus_monitor();
|
|
||||||
this._container.x = focus.x + Math.floor((focus.width - this._container.width) / 2);
|
|
||||||
this._container.y = focus.y + Math.floor((focus.height - this._container.height) / 2);
|
|
||||||
},
|
|
||||||
|
|
||||||
_show : function() {
|
|
||||||
Tweener.addTween(this._container, { opacity: 255,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
this._position();
|
|
||||||
this.actor.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
display : function(direction, activeWorkspaceIndex) {
|
|
||||||
this._redraw(direction, activeWorkspaceIndex);
|
|
||||||
if (this._timeoutId != 0)
|
|
||||||
Mainloop.source_remove(this._timeoutId);
|
|
||||||
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
|
|
||||||
this._show();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTimeout : function() {
|
|
||||||
Mainloop.source_remove(this._timeoutId);
|
|
||||||
this._timeoutId = 0;
|
|
||||||
Tweener.addTween(this._container, { opacity: 0.0,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: function() { this.actor.hide(); },
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1 +0,0 @@
|
|||||||
dist_man_MANS = gnome-shell.1
|
|
@ -1,99 +0,0 @@
|
|||||||
.\" Copyright (c) 2009, Marcelo Jorge Vieira (metal) <metal@alucinados.com>
|
|
||||||
.\"
|
|
||||||
.\" This is free documentation; you can redistribute it and/or
|
|
||||||
.\" modify it under the terms of the GNU General Public License as
|
|
||||||
.\" published by the Free Software Foundation; either version 2 of
|
|
||||||
.\" the License, or (at your option) any later version.
|
|
||||||
.\"
|
|
||||||
.\" The GNU General Public License's references to "object code"
|
|
||||||
.\" and "executables" are to be interpreted as the output of any
|
|
||||||
.\" document formatting or typesetting system, including
|
|
||||||
.\" intermediate and printed output.
|
|
||||||
.\"
|
|
||||||
.\" This manual is distributed in the hope that it will be useful,
|
|
||||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
.\" GNU General Public License for more details.
|
|
||||||
.\"
|
|
||||||
.\" You should have received a copy of the GNU General Public
|
|
||||||
.\" License along with this manual; if not, write to the Free
|
|
||||||
.\" Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
.\" Boston, MA 02111-1301 USA.
|
|
||||||
.TH GNOME-SHELL 1
|
|
||||||
.SH NAME
|
|
||||||
gnome-shell \- Graphical shell for the GNOME desktop
|
|
||||||
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B gnome-shell [options]
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
GNOME Shell provides core user interface functions for the GNOME 3
|
|
||||||
desktop, like switching to windows and launching applications. GNOME
|
|
||||||
Shell takes advantage of the capabilities of modern graphics hardware
|
|
||||||
and introduces innovative user interface concepts to provide a
|
|
||||||
visually attractive and easy to use experience.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-r, \-\-replace
|
|
||||||
Replace the running metacity/gnome-panel
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-v, \-\-verbose
|
|
||||||
Shows details about the results of running `gnome-shell'.
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-g, \-\-debug
|
|
||||||
Run under a debugger
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-debug\-command
|
|
||||||
Command to use for debugging (defaults to 'gdb \-\-args')
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-sync
|
|
||||||
.br
|
|
||||||
Make X calls synchronously, useful when debugging down X errors
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-xephyr
|
|
||||||
Run a debugging instance inside Xephyr
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-geometry
|
|
||||||
Specify Xephyr screen geometry
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-w, \-\-wide
|
|
||||||
Use widescreen (1280x800) with Xephyr
|
|
||||||
.br
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-create\-extension
|
|
||||||
Create a new GNOME Shell extension
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-eval\-file
|
|
||||||
Evaluate the contents of the given JavaScript file
|
|
||||||
.br
|
|
||||||
|
|
||||||
.SH BUGS
|
|
||||||
The bug tracker can be reached by visiting the website
|
|
||||||
\fIhttps://bugzilla.gnome.org/buglist.cgi?product=gnome-shell\fR
|
|
||||||
|
|
||||||
Before sending a bug report, please verify that you have the latest
|
|
||||||
version of gnome-shell. Many bugs (major and minor) are fixed at each
|
|
||||||
release, and if yours is out of date, the problem may already have
|
|
||||||
been solved.
|
|
||||||
|
|
||||||
.SH ADDITIONAL INFORMATION
|
|
||||||
|
|
||||||
For further information, visit the website \fIhttp://live.gnome.org/GnomeShell\fR
|
|
10
po/LINGUAS
@ -1,17 +1,13 @@
|
|||||||
ar
|
ar
|
||||||
bg
|
|
||||||
ca
|
ca
|
||||||
cs
|
cs
|
||||||
da
|
da
|
||||||
de
|
de
|
||||||
el
|
|
||||||
en_GB
|
en_GB
|
||||||
es
|
es
|
||||||
fi
|
|
||||||
fr
|
fr
|
||||||
ga
|
ga
|
||||||
gl
|
gl
|
||||||
he
|
|
||||||
hu
|
hu
|
||||||
it
|
it
|
||||||
ko
|
ko
|
||||||
@ -20,13 +16,7 @@ nl
|
|||||||
pa
|
pa
|
||||||
pl
|
pl
|
||||||
pt_BR
|
pt_BR
|
||||||
ro
|
|
||||||
ru
|
|
||||||
sl
|
sl
|
||||||
sr
|
|
||||||
sr@latin
|
|
||||||
sv
|
sv
|
||||||
tr
|
tr
|
||||||
uk
|
|
||||||
vi
|
|
||||||
zh_CN
|
zh_CN
|
||||||
|
@ -1,18 +1,9 @@
|
|||||||
data/gnome-shell.desktop.in.in
|
data/gnome-shell.desktop.in.in
|
||||||
data/gnome-shell-clock-preferences.desktop.in.in
|
|
||||||
[type: gettext/glade]data/clock-preferences.ui
|
|
||||||
js/ui/appDisplay.js
|
|
||||||
js/ui/appFavorites.js
|
|
||||||
js/ui/dash.js
|
|
||||||
js/ui/docDisplay.js
|
|
||||||
js/ui/lookingGlass.js
|
|
||||||
js/ui/overview.js
|
|
||||||
js/ui/panel.js
|
js/ui/panel.js
|
||||||
js/ui/placeDisplay.js
|
js/ui/dash.js
|
||||||
|
js/ui/overview.js
|
||||||
js/ui/runDialog.js
|
js/ui/runDialog.js
|
||||||
js/ui/statusMenu.js
|
|
||||||
js/ui/windowAttentionHandler.js
|
|
||||||
js/ui/workspacesView.js
|
|
||||||
src/gdmuser/gdm-user.c
|
src/gdmuser/gdm-user.c
|
||||||
src/shell-global.c
|
src/shell-global.c
|
||||||
|
src/shell-status-menu.c
|
||||||
src/shell-uri-util.c
|
src/shell-uri-util.c
|
||||||
|
@ -1,2 +1 @@
|
|||||||
data/gnome-shell.desktop.in
|
data/gnome-shell.desktop.in
|
||||||
data/gnome-shell-clock-preferences.desktop.in
|
|
||||||
|
364
po/ar.po
@ -1,13 +1,13 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# SOME DESCRIPTIVE TITLE.
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
# Khaled Hosny <khaledhosny@eglug.org>, 2009, 2010.
|
# Khaled Hosny <khaledhosny@eglug.org>, 2009.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: HEAD\n"
|
"Project-Id-Version: HEAD\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2010-05-15 23:40+0300\n"
|
"POT-Creation-Date: 2009-09-25 04:22+0200\n"
|
||||||
"PO-Revision-Date: 2010-05-15 23:40+0300\n"
|
"PO-Revision-Date: 2009-09-25 04:21+0300\n"
|
||||||
"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
|
"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
|
||||||
"Language-Team: Arabic <doc@arabeyes.org>\n"
|
"Language-Team: Arabic <doc@arabeyes.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -15,8 +15,8 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Language: ar\n"
|
"Language: ar\n"
|
||||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
|
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
|
||||||
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
|
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||||
"X-Generator: Virtaal 0.6.0\n"
|
"X-Generator: Virtaal 0.4.0\n"
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
msgid "GNOME Shell"
|
msgid "GNOME Shell"
|
||||||
@ -26,237 +26,63 @@ msgstr "صدفة جنوم"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "إدارة النوافذ وإطلاق التطبيقات"
|
msgstr "إدارة النوافذ وإطلاق التطبيقات"
|
||||||
|
|
||||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:1
|
#. left side
|
||||||
msgid "Clock"
|
#: ../js/ui/panel.js:269
|
||||||
msgstr "الساعة"
|
msgid "Activities"
|
||||||
|
msgstr "الأنشطة"
|
||||||
|
|
||||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:2
|
#. Translators: This is a time format.
|
||||||
msgid "Customize the panel clock"
|
#: ../js/ui/panel.js:452
|
||||||
msgstr "طوّع ساعة اللوحة"
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%A %Ol:%OM %p"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:283
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "ابحث..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:400
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "استعرض"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(انظر الكل)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/appDisplay.js:306 ../js/ui/dash.js:850
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "التطبيقات"
|
msgstr "التطبيقات"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:338
|
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "التفضيلات"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:705
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "نافذة جديدة"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:709
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "أزِل من المفضّلة"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:710
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "أضِف إلى المفضّلة"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1037
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "اسحب إلى هنا ليضاف إلى المفضّلة"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "أضيف %s إلى مفضلتك."
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "أزيل %s من مفضّلتك."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:189
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "ابحث"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:505
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "يبحث..."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:519
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "لا نتائج مطابقة."
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:869 ../js/ui/placeDisplay.js:543
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES & DEVICES"
|
msgid "PLACES"
|
||||||
msgstr "الأماكن والأجهزة"
|
msgstr "الأماكن"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:876 ../js/ui/docDisplay.js:489
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
msgid "RECENT ITEMS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "العناصر الحديثة"
|
msgstr "المستندات الحديثة"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:354
|
#. **** Search Results ****
|
||||||
msgid "No extensions installed"
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
msgstr "لم تثبّت أية امتدادات"
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "نتائج البحث"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:391
|
#: ../js/ui/dash.js:814
|
||||||
msgid "Enabled"
|
msgid "PREFERENCES"
|
||||||
msgstr "مفعّل"
|
msgstr "التفضيلات"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:393
|
#: ../js/ui/runDialog.js:95
|
||||||
msgid "Disabled"
|
|
||||||
msgstr "معطّل"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:395
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "خطأ"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:397
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr "غير محدث"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:422
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "اعرض المصدر"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:428
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "صفحة الوب"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:161
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "تراجع"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:535
|
|
||||||
msgid "Quit"
|
|
||||||
msgstr "أنهِ"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:740
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "الأنشطة"
|
|
||||||
|
|
||||||
#. Translators: This is the time format with date used
|
|
||||||
#. in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:955
|
|
||||||
msgid "%a %b %e, %R:%S"
|
|
||||||
msgstr "%A %e %B، %R:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:956
|
|
||||||
msgid "%a %b %e, %R"
|
|
||||||
msgstr "%A %e %B، %R"
|
|
||||||
|
|
||||||
#. Translators: This is the time format without date used
|
|
||||||
#. in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:960
|
|
||||||
msgid "%a %R:%S"
|
|
||||||
msgstr "%A %R:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:961
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%A %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format with date used
|
|
||||||
#. for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:968
|
|
||||||
msgid "%a %b %e, %l:%M:%S %p"
|
|
||||||
msgstr "%A %e %B، %l:%M:%S %p"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:969
|
|
||||||
msgid "%a %b %e, %l:%M %p"
|
|
||||||
msgstr "%A %e %B، %l:%M %p"
|
|
||||||
|
|
||||||
#. Translators: This is a time format without date used
|
|
||||||
#. for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:973
|
|
||||||
msgid "%a %l:%M:%S %p"
|
|
||||||
msgstr "%A %l:%M:%S %p"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:974
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%A %Ol:%OM %p"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:108
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "فشل فصْل '%s'"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:111
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "أعد المحاولة"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:156
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "اتّصل ب..."
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:231
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "من فضلك اكتب أمرا:"
|
msgstr "من فضلك اكتب أمرا:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:375
|
#: ../src/shell-global.c:799
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "فشل تنفيذ '%s':"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:90
|
|
||||||
msgid "Available"
|
|
||||||
msgstr "متاح"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:94
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr "مشغول"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:98
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "خفي"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:105
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "معلومات الحساب..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:109
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "تفضيلات النظام..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:116
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "أوصد الشاشة"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:120
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "بدّل المستخدم"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:125
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "اخرج..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:129
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "أطفئ..."
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:47
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has finished starting"
|
|
||||||
msgstr "انتهى %s من البدء"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:49
|
|
||||||
#, c-format
|
|
||||||
msgid "'%s' is ready"
|
|
||||||
msgstr "'%s' جاهز"
|
|
||||||
|
|
||||||
#: ../js/ui/workspacesView.js:239
|
|
||||||
msgid ""
|
|
||||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
|
||||||
msgstr "تعذّر إضافة مساحة عمل جديدة، لتجاوز أقصى عدد من مساحات العمل."
|
|
||||||
|
|
||||||
#: ../js/ui/workspacesView.js:256
|
|
||||||
msgid "Can't remove the first workspace."
|
|
||||||
msgstr "لا يمكن حذف مساحة العمل الأولى."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:979
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "منذ أقل من دقيقة"
|
msgstr "منذ أقل من دقيقة"
|
||||||
|
|
||||||
#: ../src/shell-global.c:983
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
@ -267,7 +93,7 @@ msgstr[3] "منذ %d دقائق"
|
|||||||
msgstr[4] "منذ %d دقيقة"
|
msgstr[4] "منذ %d دقيقة"
|
||||||
msgstr[5] "منذ %d دقيقة"
|
msgstr[5] "منذ %d دقيقة"
|
||||||
|
|
||||||
#: ../src/shell-global.c:988
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
@ -278,7 +104,7 @@ msgstr[3] "منذ %d ساعات"
|
|||||||
msgstr[4] "منذ %d ساعة"
|
msgstr[4] "منذ %d ساعة"
|
||||||
msgstr[5] "منذ %d ساعة"
|
msgstr[5] "منذ %d ساعة"
|
||||||
|
|
||||||
#: ../src/shell-global.c:993
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
@ -289,7 +115,7 @@ msgstr[3] "منذ %d أيام"
|
|||||||
msgstr[4] "منذ %d يوما"
|
msgstr[4] "منذ %d يوما"
|
||||||
msgstr[5] "منذ %d يوم"
|
msgstr[5] "منذ %d يوم"
|
||||||
|
|
||||||
#: ../src/shell-global.c:998
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@ -300,17 +126,67 @@ msgstr[3] "منذ %d أسابيع"
|
|||||||
msgstr[4] "منذ %d أسبوعا"
|
msgstr[4] "منذ %d أسبوعا"
|
||||||
msgstr[5] "منذ %d أسبوع"
|
msgstr[5] "منذ %d أسبوع"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "مجهول"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "تعذّر إيصاد الشاشة: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "تعذّر ضبك حافظة الشاشة مؤقتا لتكون شاشة خالية: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "تعذّر الخروج: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "معلومات الحساب..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "الشريط الجانبي"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "تفضيلات النظام..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "أوصد الشاشة"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "بدّل المستخدم"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "اخرج..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "أطفئ..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "مجلد المنزل"
|
msgstr "مجلد المنزل"
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
#. Translators: this is the same string as the one found in
|
||||||
#. * nautilus
|
#. * nautilus
|
||||||
#: ../src/shell-uri-util.c:104
|
#: ../src/shell-uri-util.c:102
|
||||||
msgid "File System"
|
msgid "File System"
|
||||||
msgstr "نظام الملفات"
|
msgstr "نظام الملفات"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
#: ../src/shell-uri-util.c:248
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "ابحث"
|
msgstr "ابحث"
|
||||||
|
|
||||||
@ -319,49 +195,7 @@ msgstr "ابحث"
|
|||||||
#. * example, "Trash: some-directory". It means that the
|
#. * example, "Trash: some-directory". It means that the
|
||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:300
|
#: ../src/shell-uri-util.c:298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
#~ msgid "%H:%M"
|
|
||||||
#~ msgstr "%OH:%OM"
|
|
||||||
|
|
||||||
#~ msgid "Applications"
|
|
||||||
#~ msgstr "التطبيقات"
|
|
||||||
|
|
||||||
#~ msgid "Recent Documents"
|
|
||||||
#~ msgstr "المستندات الحديثة"
|
|
||||||
|
|
||||||
#~ msgid "Frequent"
|
|
||||||
#~ msgstr "متكرر"
|
|
||||||
|
|
||||||
#~ msgid "More"
|
|
||||||
#~ msgstr "المزيد"
|
|
||||||
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(انظر الكل)"
|
|
||||||
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "الأماكن"
|
|
||||||
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "نتائج البحث"
|
|
||||||
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "مجهول"
|
|
||||||
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "تعذّر إيصاد الشاشة: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr "تعذّر ضبك حافظة الشاشة مؤقتا لتكون شاشة خالية: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "تعذّر الخروج: %s"
|
|
||||||
|
|
||||||
#~ msgid "Sidebar"
|
|
||||||
#~ msgstr "الشريط الجانبي"
|
|
||||||
|
|
||||||
#~ msgid "Browse"
|
|
||||||
#~ msgstr "استعرض"
|
|
||||||
|
263
po/bg.po
@ -1,263 +0,0 @@
|
|||||||
# Bulgarian translation of gnome-shell po-file.
|
|
||||||
# Copyright (C) 2010 Free Software Foundation, Inc.
|
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
|
||||||
# Ivaylo Valkov <ivaylo@e-valkov.org>, 2010.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2010-03-18 13:09+0200\n"
|
|
||||||
"PO-Revision-Date: 2010-03-18 11:30+0200\n"
|
|
||||||
"Last-Translator: Ivaylo Valkov <ivaylo@e-valkov.org>\n"
|
|
||||||
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
|
||||||
msgid "GNOME Shell"
|
|
||||||
msgstr "Обвивка на GNOME"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
|
||||||
msgid "Window management and application launching"
|
|
||||||
msgstr "Управление на прозорци и стартиране на програми"
|
|
||||||
|
|
||||||
#. **** Applications ****
|
|
||||||
#: ../js/ui/appDisplay.js:311 ../js/ui/dash.js:852
|
|
||||||
msgid "APPLICATIONS"
|
|
||||||
msgstr "ПРОГРАМИ"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:343
|
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "ПРЕДПОЧИТАНИЯ"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:728
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "Нов прозорец"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:732
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Премахване от „Любими“"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:733
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Добавяне в „Любими“"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1085
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Довлачете до тук обектите за да ги добавите към „Любими“"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "Програмата „%s“ беше добавена в „Любими“"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "Програмата „%s“ беше премахната от „Любими“"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:194
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "Търсене"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:507
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "Търсене…"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:521
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "Няма съвпадения."
|
|
||||||
|
|
||||||
#. **** Places ****
|
|
||||||
#. Translators: This is in the sense of locations for documents,
|
|
||||||
#. network locations, etc.
|
|
||||||
#: ../js/ui/dash.js:871 ../js/ui/placeDisplay.js:536
|
|
||||||
msgid "PLACES & DEVICES"
|
|
||||||
msgstr "МЕСТА И УСТРОЙСТВА"
|
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:878 ../js/ui/docDisplay.js:488
|
|
||||||
msgid "RECENT ITEMS"
|
|
||||||
msgstr "СКОРО ОТВАРЯНИ"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:363
|
|
||||||
msgid "No extensions installed"
|
|
||||||
msgstr "Няма инсталирани разширения"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:400
|
|
||||||
msgid "Enabled"
|
|
||||||
msgstr "Включено"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:402
|
|
||||||
msgid "Disabled"
|
|
||||||
msgstr "Изключено"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:404
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "Грешка"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:406
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr "Остаряло"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:431
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "Преглед на програмния код"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:437
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "Домашна страница"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:182
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "Отмяна"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:385
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Дейности"
|
|
||||||
|
|
||||||
#. Translators: This is the time format used in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:616
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%a, %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format used for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:619
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a, %H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:103
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "Неуспех при демонтиране на „%s“"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:106
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "Повторен опит"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:151
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Свързване към…"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:221
|
|
||||||
msgid "Please enter a command:"
|
|
||||||
msgstr "Въведете команда:"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:344
|
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "Неуспешно изпълнение на „%s“:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:107
|
|
||||||
msgid "Available"
|
|
||||||
msgstr "Налично"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:112
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr "Заето"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:117
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "Невидимо"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:126
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Информация за настройките на потребителя…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:132
|
|
||||||
msgid "Sidebar"
|
|
||||||
msgstr "Странична лента"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:142
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "Системни настройки…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:151
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Заключване на екрана"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:156
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Смяна на потребител"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:162
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Изход…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:167
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Изключване на компютъра…"
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/widget.js:163
|
|
||||||
msgid "%H:%M"
|
|
||||||
msgstr "%H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:317
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Програми"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:339
|
|
||||||
msgid "Recent Documents"
|
|
||||||
msgstr "Скоро отваряни документи"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:967
|
|
||||||
msgid "Less than a minute ago"
|
|
||||||
msgstr "Преди по-малко от минута"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:971
|
|
||||||
#, c-format
|
|
||||||
msgid "%d minute ago"
|
|
||||||
msgid_plural "%d minutes ago"
|
|
||||||
msgstr[0] "преди %d минута"
|
|
||||||
msgstr[1] "преди %d минути"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:976
|
|
||||||
#, c-format
|
|
||||||
msgid "%d hour ago"
|
|
||||||
msgid_plural "%d hours ago"
|
|
||||||
msgstr[0] "преди %d час"
|
|
||||||
msgstr[1] "преди %d часа"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:981
|
|
||||||
#, c-format
|
|
||||||
msgid "%d day ago"
|
|
||||||
msgid_plural "%d days ago"
|
|
||||||
msgstr[0] "преди %d ден"
|
|
||||||
msgstr[1] "преди %d дни"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:986
|
|
||||||
#, c-format
|
|
||||||
msgid "%d week ago"
|
|
||||||
msgid_plural "%d weeks ago"
|
|
||||||
msgstr[0] "преди %d седмица"
|
|
||||||
msgstr[1] "преди %d седмици"
|
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
|
||||||
msgid "Home Folder"
|
|
||||||
msgstr "Домашна папка"
|
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
|
||||||
#. * nautilus
|
|
||||||
#: ../src/shell-uri-util.c:104
|
|
||||||
msgid "File System"
|
|
||||||
msgstr "Файлова система"
|
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
|
||||||
msgid "Search"
|
|
||||||
msgstr "Търсене"
|
|
||||||
|
|
||||||
#. Translators: the first string is the name of a gvfs
|
|
||||||
#. * method, and the second string is a path. For
|
|
||||||
#. * example, "Trash: some-directory". It means that the
|
|
||||||
#. * directory called "some-directory" is in the trash.
|
|
||||||
#.
|
|
||||||
#: ../src/shell-uri-util.c:300
|
|
||||||
#, c-format
|
|
||||||
msgid "%1$s: %2$s"
|
|
||||||
msgstr "%1$s: %2$s"
|
|
105
po/ca.po
@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: HEAD\n"
|
"Project-Id-Version: HEAD\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-10-10 20:19+0200\n"
|
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
|
||||||
"PO-Revision-Date: 2009-10-10 20:22+0100\n"
|
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
|
||||||
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
|
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -24,126 +24,82 @@ msgstr "GNOME Shell"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Gestió de finestres i execució d'aplicacions"
|
msgstr "Gestió de finestres i execució d'aplicacions"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:335
|
#. left side
|
||||||
msgid "Frequent"
|
#: ../js/ui/panel.js:271
|
||||||
msgstr "Freqüent"
|
msgid "Activities"
|
||||||
|
msgstr "Activitats"
|
||||||
|
|
||||||
#: ../js/ui/appIcon.js:462
|
#. Translators: This is a time format.
|
||||||
msgid "New Window"
|
#: ../js/ui/panel.js:454
|
||||||
msgstr "Finestra nova"
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
#: ../js/ui/appIcon.js:475
|
#: ../js/ui/dash.js:256
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Elimina dels preferits"
|
|
||||||
|
|
||||||
#: ../js/ui/appIcon.js:476
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Afegeix als preferits"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:283
|
|
||||||
msgid "Find..."
|
msgid "Find..."
|
||||||
msgstr "Cerca..."
|
msgstr "Cerca..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:400
|
#: ../js/ui/dash.js:374
|
||||||
msgid "More"
|
msgid "Browse"
|
||||||
msgstr "Més"
|
msgstr "Navega"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:543
|
#: ../js/ui/dash.js:451
|
||||||
msgid "(see all)"
|
msgid "(see all)"
|
||||||
msgstr "(mostra tot)"
|
msgstr "(mostra tot)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:763
|
#: ../js/ui/dash.js:633
|
||||||
#: ../js/ui/dash.js:825
|
#: ../js/ui/dash.js:681
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLICACIONS"
|
msgstr "APLICACIONS"
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:783
|
#: ../js/ui/dash.js:653
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "LLOCS"
|
msgstr "LLOCS"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:790
|
#: ../js/ui/dash.js:660
|
||||||
#: ../js/ui/dash.js:835
|
#: ../js/ui/dash.js:692
|
||||||
msgid "RECENT DOCUMENTS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "DOCUMENTS RECENTS"
|
msgstr "DOCUMENTS RECENTS"
|
||||||
|
|
||||||
#. **** Search Results ****
|
#. **** Search Results ****
|
||||||
#: ../js/ui/dash.js:815
|
#: ../js/ui/dash.js:679
|
||||||
#: ../js/ui/dash.js:955
|
|
||||||
msgid "SEARCH RESULTS"
|
msgid "SEARCH RESULTS"
|
||||||
msgstr "RESULTATS DE LA CERCA"
|
msgstr "RESULTATS DE LA CERCA"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:830
|
#: ../js/ui/runDialog.js:82
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "PREFERÈNCIES"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:272
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Activitats"
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/panel.js:464
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a %H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/places.js:178
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Connecta a..."
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:96
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Introduïu una ordre:"
|
msgstr "Introduïu una ordre:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:173
|
#: ../src/shell-global.c:840
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "No s'ha pogut executar «%s»:"
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/widget.js:162
|
|
||||||
msgid "%H:%M"
|
|
||||||
msgstr "%H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:316
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Aplicacions"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:341
|
|
||||||
msgid "Recent Documents"
|
|
||||||
msgstr "Documents recents"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:812
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Fa menys d'un minut"
|
msgstr "Fa menys d'un minut"
|
||||||
|
|
||||||
#: ../src/shell-global.c:815
|
#: ../src/shell-global.c:843
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "Fa %d minut"
|
msgstr[0] "Fa %d minut"
|
||||||
msgstr[1] "Fa %d minuts"
|
msgstr[1] "Fa %d minuts"
|
||||||
|
|
||||||
#: ../src/shell-global.c:818
|
#: ../src/shell-global.c:846
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "Fa %d hora"
|
msgstr[0] "Fa %d hora"
|
||||||
msgstr[1] "Fa %d hores"
|
msgstr[1] "Fa %d hores"
|
||||||
|
|
||||||
#: ../src/shell-global.c:821
|
#: ../src/shell-global.c:849
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "Fa %d dia"
|
msgstr[0] "Fa %d dia"
|
||||||
msgstr[1] "Fa %d dies"
|
msgstr[1] "Fa %d dies"
|
||||||
|
|
||||||
#: ../src/shell-global.c:824
|
#: ../src/shell-global.c:852
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@ -224,3 +180,10 @@ msgstr "Cerca"
|
|||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Cerca aplicacions o documents"
|
||||||
|
#~ msgid "Manager"
|
||||||
|
#~ msgstr "Gestor"
|
||||||
|
#~ msgid "The user manager object this user is controlled by."
|
||||||
|
#~ msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."
|
||||||
|
|
||||||
|
325
po/cs.po
@ -1,21 +1,20 @@
|
|||||||
# Czech translation of gnome-shell.
|
# Czech translation of gnome-shell.
|
||||||
# Copyright (C) 2009, 2010 the author(s) of gnome-shell.
|
# Copyright (C) 2009 the author(s) of gnome-shell.
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Andre Klapper <ak-47@gmx.net>, 2009.
|
# Andre Klapper <ak-47@gmx.net>, 2009.
|
||||||
# Petr Kovar <pknbe@volny.cz>, 2009, 2010.
|
# Petr Kovar <pknbe@volny.cz>, 2009.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell\n"
|
"Project-Id-Version: gnome-shell\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2010-03-29 00:49+0200\n"
|
"POT-Creation-Date: 2009-09-22 13:36+0200\n"
|
||||||
"PO-Revision-Date: 2010-03-29 00:49+0200\n"
|
"PO-Revision-Date: 2009-09-22 13:37+0200\n"
|
||||||
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
|
"Last-Translator: Andre Klapper <ak-47@gmx.net>, 2009\n"
|
||||||
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||||
"X-Generator: Lokalize 1.0\n"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
msgid "GNOME Shell"
|
msgid "GNOME Shell"
|
||||||
@ -25,205 +24,63 @@ msgstr "Prostředí GNOME Shell"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Správa oken a spouštění aplikací"
|
msgstr "Správa oken a spouštění aplikací"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:269
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "Činnosti"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:452
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a, %H:%M"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:283
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "Najít..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:400
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "Procházet"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(zobrazit vše)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/appDisplay.js:312 ../js/ui/dash.js:855
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLIKACE"
|
msgstr "APLIKACE"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:344
|
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "PŘEDVOLBY"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:756
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "Nové okno"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:760
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Odstranit z oblíbených"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:761
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Přidat mezi oblíbené"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1113
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Oblíbené přidáte přetažením sem"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "%s byl přidán mezi oblíbené."
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "%s byl odstraněn z oblíbených."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:194
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "Najít"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:510
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "Hledá se..."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:524
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "Neodpovídá ani jeden z výsledků."
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:874 ../js/ui/placeDisplay.js:582
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES & DEVICES"
|
msgid "PLACES"
|
||||||
msgstr "MÍSTA A ZAŘÍZENÍ"
|
msgstr "MÍSTA"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:881 ../js/ui/docDisplay.js:488
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
msgid "RECENT ITEMS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "NEDÁVNÉ POLOŽKY"
|
msgstr "NEDÁVNÉ DOKUMENTY"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:363
|
#. **** Search Results ****
|
||||||
msgid "No extensions installed"
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
msgstr "Nejsou nainstalována žádná rozšíření"
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "VÝSLEDKY HLEDÁNÍ"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:400
|
#: ../js/ui/dash.js:814
|
||||||
msgid "Enabled"
|
msgid "PREFERENCES"
|
||||||
msgstr "Povoleno"
|
msgstr "NASTAVENÍ"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:402
|
#: ../js/ui/runDialog.js:101
|
||||||
msgid "Disabled"
|
|
||||||
msgstr "Zakázáno"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:404
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "Chyba"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:406
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr "Neaktuální"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:431
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "Zobrazit zdroj"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:437
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "Webová stránka"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:182
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "Zpět"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:385
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Činnosti"
|
|
||||||
|
|
||||||
# Not sure whether we've enough space for it, but anyway, looks more aesthetically with "%A".
|
|
||||||
#. Translators: This is the time format used in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:616
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%A, %R"
|
|
||||||
|
|
||||||
# Not sure whether we've enough space for it, but anyway, looks more aesthetically with "%A".
|
|
||||||
#. Translators: This is a time format used for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:619
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%A, %l:%M %p"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:108
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "Nelze odpojit \"%s\""
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:111
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "Opakovat"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:156
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Připojit se k..."
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:232
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Zadejte prosím příkaz:"
|
msgstr "Zadejte prosím příkaz:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:376
|
#: ../src/shell-global.c:799
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "Vykonání \"%s\" selhalo:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:107
|
|
||||||
msgid "Available"
|
|
||||||
msgstr "Přítomen"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:112
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr "Zaneprázdněn"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:117
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "Neviditelný"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:126
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Informace o účtu..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:132
|
|
||||||
msgid "Sidebar"
|
|
||||||
msgstr "Postranní lišta"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:142
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "Předvolby systému..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:151
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Uzamknout obrazovku"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:156
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Přepnout uživatele"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:162
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Odhlásit..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:167
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Vypnout..."
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/widget.js:163
|
|
||||||
msgid "%H:%M"
|
|
||||||
msgstr "%H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:317
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Aplikace"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:339
|
|
||||||
msgid "Recent Documents"
|
|
||||||
msgstr "Nedávné dokumenty"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:47
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has finished starting"
|
|
||||||
msgstr "Spouštění %s dokončeno"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:49
|
|
||||||
#, c-format
|
|
||||||
msgid "'%s' is ready"
|
|
||||||
msgstr "Připraveno \"%s\""
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:967
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Před méně než minutou"
|
msgstr "Před méně než minutou"
|
||||||
|
|
||||||
#: ../src/shell-global.c:971
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
@ -231,7 +88,7 @@ msgstr[0] "Před %d minutou"
|
|||||||
msgstr[1] "Před %d minutami"
|
msgstr[1] "Před %d minutami"
|
||||||
msgstr[2] "Před %d minutami"
|
msgstr[2] "Před %d minutami"
|
||||||
|
|
||||||
#: ../src/shell-global.c:976
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
@ -239,7 +96,7 @@ msgstr[0] "Před %d hodinou"
|
|||||||
msgstr[1] "Před %d hodinami"
|
msgstr[1] "Před %d hodinami"
|
||||||
msgstr[2] "Před %d hodinami"
|
msgstr[2] "Před %d hodinami"
|
||||||
|
|
||||||
#: ../src/shell-global.c:981
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
@ -247,7 +104,7 @@ msgstr[0] "Před %d dnem"
|
|||||||
msgstr[1] "Před %d dny"
|
msgstr[1] "Před %d dny"
|
||||||
msgstr[2] "Před %d dny"
|
msgstr[2] "Před %d dny"
|
||||||
|
|
||||||
#: ../src/shell-global.c:986
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@ -255,17 +112,67 @@ msgstr[0] "Před %d týdnem"
|
|||||||
msgstr[1] "Před %d týdny"
|
msgstr[1] "Před %d týdny"
|
||||||
msgstr[2] "Před %d týdny"
|
msgstr[2] "Před %d týdny"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Neznámé"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Nelze uzamknout obrazovku: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "Šetřič obrazovky nelze dočasně nastavit na prázdnou obrazovku: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Nelze se odhlásit: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Informace o účtu..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Postranní lišta"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Předvolby systému..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Uzamknout obrazovku"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Přepnout uživatele"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Odhlásit..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Vypnout..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "Domovská složka"
|
msgstr "Domovská složka"
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
#. Translators: this is the same string as the one found in
|
||||||
#. * nautilus
|
#. * nautilus
|
||||||
#: ../src/shell-uri-util.c:104
|
#: ../src/shell-uri-util.c:102
|
||||||
msgid "File System"
|
msgid "File System"
|
||||||
msgstr "Systém souborů"
|
msgstr "Systém souborů"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
#: ../src/shell-uri-util.c:248
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Hledat"
|
msgstr "Hledat"
|
||||||
|
|
||||||
@ -274,41 +181,11 @@ msgstr "Hledat"
|
|||||||
#. * example, "Trash: some-directory". It means that the
|
#. * example, "Trash: some-directory". It means that the
|
||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:300
|
#: ../src/shell-uri-util.c:298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
#~ msgid "Frequent"
|
|
||||||
#~ msgstr "Časté"
|
|
||||||
|
|
||||||
#~ msgid "More"
|
|
||||||
#~ msgstr "Více"
|
|
||||||
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(zobrazit vše)"
|
|
||||||
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "MÍSTA"
|
|
||||||
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "VÝSLEDKY HLEDÁNÍ"
|
|
||||||
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "Neznámé"
|
|
||||||
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "Nelze uzamknout obrazovku: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr "Šetřič obrazovky nelze dočasně nastavit na prázdnou obrazovku: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "Nelze se odhlásit: %s"
|
|
||||||
|
|
||||||
#~ msgid "Browse"
|
|
||||||
#~ msgstr "Procházet"
|
|
||||||
|
|
||||||
#~ msgid "Manager"
|
#~ msgid "Manager"
|
||||||
#~ msgstr "Správce"
|
#~ msgstr "Správce"
|
||||||
|
|
||||||
|
293
po/da.po
@ -1,14 +1,14 @@
|
|||||||
# Danish translation of gnome-shell
|
# Danish translation of gnome-shell
|
||||||
# Copyright (C) 2010 gnome-shell
|
# Copyright (C) 2009 gnome-shell
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Kris Thomsen <lakristho@gmail.com>, 2009, 2010.
|
# Kris Thomsen <lakristho@gmail.com>, 2009.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell\n"
|
"Project-Id-Version: gnome-shell\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2010-02-23 22:07+0100\n"
|
"POT-Creation-Date: 2009-09-04 01:26+0200\n"
|
||||||
"PO-Revision-Date: 2010-02-11 22:32+0200\n"
|
"PO-Revision-Date: 2009-09-01 21:48+0200\n"
|
||||||
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
||||||
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
|
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -24,222 +24,147 @@ msgstr "Skal til GNOME"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Vinduehåndtering og åbning af programmer"
|
msgstr "Vinduehåndtering og åbning af programmer"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. left side
|
||||||
#: ../js/ui/appDisplay.js:180 ../js/ui/dash.js:881
|
#: ../js/ui/panel.js:271
|
||||||
msgid "APPLICATIONS"
|
msgid "Activities"
|
||||||
msgstr "PROGRAMMER"
|
msgstr "Aktiviteter"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:204
|
#. Translators: This is a time format.
|
||||||
msgid "PREFERENCES"
|
#: ../js/ui/panel.js:454
|
||||||
msgstr "INDSTILLINGER"
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:582
|
#: ../js/ui/dash.js:256
|
||||||
msgid "New Window"
|
|
||||||
msgstr "Nyt vindue"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:586
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Fjern fra favoritter"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:587
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Tilføj til favoritter"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:939
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Træk hertil for at tilføje til favoritter"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, fuzzy, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "Fjern fra favoritter"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:235
|
|
||||||
msgid "Find..."
|
msgid "Find..."
|
||||||
msgstr "Find..."
|
msgstr "Find..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:505
|
#: ../js/ui/dash.js:374
|
||||||
msgid "Searching..."
|
msgid "Browse"
|
||||||
msgstr "Søger..."
|
msgstr "Gennemse"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:519
|
#: ../js/ui/dash.js:511
|
||||||
msgid "No matching results."
|
msgid "(see all)"
|
||||||
msgstr "Ingen matchende resultater."
|
msgstr "(se alle)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "PROGRAMMER"
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
|
#: ../js/ui/dash.js:725
|
||||||
msgid "PLACES & DEVICES"
|
msgid "PLACES"
|
||||||
msgstr "STEDER & ENHEDER"
|
msgstr "STEDER"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
|
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||||
msgid "RECENT ITEMS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "SENESTE ELEMENTER"
|
msgstr "SENESTE DOKUMENTER"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:356
|
#. **** Search Results ****
|
||||||
msgid "No extensions installed"
|
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||||
msgstr ""
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "SØGERESULTATER"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:393
|
#: ../js/ui/runDialog.js:82
|
||||||
msgid "Enabled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:395
|
|
||||||
msgid "Disabled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:397
|
|
||||||
msgid "Error"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:399
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:424
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:430
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:92
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:336
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Aktiviteter"
|
|
||||||
|
|
||||||
#. Translators: This is the time format used in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:560
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%a %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format used for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:563
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a %H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:144
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Forbind til..."
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:245
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Indtast en kommando:"
|
msgstr "Indtast en kommando:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:361
|
#: ../src/shell-global.c:840
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "Kørsel af \"%s\" mislykkedes:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:107
|
|
||||||
msgid "Available"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:112
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:117
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:126
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Kontoinformation..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:132
|
|
||||||
msgid "Sidebar"
|
|
||||||
msgstr "Sidebjælke"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:142
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "Systemindstillinger..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:151
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Lås skærm"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:156
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Skift bruger"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:162
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Log ud..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:167
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Luk ned..."
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/widget.js:163
|
|
||||||
msgid "%H:%M"
|
|
||||||
msgstr "%H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:317
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Programmer"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:339
|
|
||||||
msgid "Recent Documents"
|
|
||||||
msgstr "Seneste dokumenter"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:954
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Mindre end et minut siden"
|
msgstr "Mindre end et minut siden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:958
|
#: ../src/shell-global.c:843
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minut siden"
|
msgstr[0] "%d minut siden"
|
||||||
msgstr[1] "%d minutter siden"
|
msgstr[1] "%d minutter siden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:963
|
#: ../src/shell-global.c:846
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d time siden"
|
msgstr[0] "%d time siden"
|
||||||
msgstr[1] "%d timer siden"
|
msgstr[1] "%d timer siden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:968
|
#: ../src/shell-global.c:849
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d dag siden"
|
msgstr[0] "%d dag siden"
|
||||||
msgstr[1] "%d dage siden"
|
msgstr[1] "%d dage siden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:973
|
#: ../src/shell-global.c:852
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
msgstr[0] "%d uge siden"
|
msgstr[0] "%d uge siden"
|
||||||
msgstr[1] "%d uger siden"
|
msgstr[1] "%d uger siden"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Ukendt"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Kan ikke låse skærm: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "Kan ikke midlertidigt sætte pauseskærm til blank skærm: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Kan ikke logge ud: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Kontoinformation..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Sidebjælke"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Systemindstillinger..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Lås skærm"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Skift bruger"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Log ud..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Luk ned..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "Hjemmemappe"
|
msgstr "Hjemmemappe"
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
#. Translators: this is the same string as the one found in
|
||||||
#. * nautilus
|
#. * nautilus
|
||||||
#: ../src/shell-uri-util.c:104
|
#: ../src/shell-uri-util.c:102
|
||||||
msgid "File System"
|
msgid "File System"
|
||||||
msgstr "Filsystem"
|
msgstr "Filsystem"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
#: ../src/shell-uri-util.c:248
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Søg"
|
msgstr "Søg"
|
||||||
|
|
||||||
@ -248,41 +173,11 @@ msgstr "Søg"
|
|||||||
#. * example, "Trash: some-directory". It means that the
|
#. * example, "Trash: some-directory". It means that the
|
||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:300
|
#: ../src/shell-uri-util.c:298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
#~ msgid "Frequent"
|
|
||||||
#~ msgstr "Ofte"
|
|
||||||
|
|
||||||
#~ msgid "More"
|
|
||||||
#~ msgstr "Mere"
|
|
||||||
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(se alle)"
|
|
||||||
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "STEDER"
|
|
||||||
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "SØGERESULTATER"
|
|
||||||
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "Ukendt"
|
|
||||||
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "Kan ikke låse skærm: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr "Kan ikke midlertidigt sætte pauseskærm til blank skærm: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "Kan ikke logge ud: %s"
|
|
||||||
|
|
||||||
#~ msgid "Browse"
|
|
||||||
#~ msgstr "Gennemse"
|
|
||||||
|
|
||||||
#~ msgid "Find apps or documents"
|
#~ msgid "Find apps or documents"
|
||||||
#~ msgstr "Find programmer eller dokumenter"
|
#~ msgstr "Find programmer eller dokumenter"
|
||||||
|
|
||||||
|
411
po/de.po
@ -2,28 +2,21 @@
|
|||||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
#
|
#
|
||||||
# workspace - Arbeitsfläche
|
|
||||||
#
|
|
||||||
# Hendrik Brandt <heb@gnome-de.org>, 2009.
|
# Hendrik Brandt <heb@gnome-de.org>, 2009.
|
||||||
# Hendrik Richter <hendrikr@gnome.org>, 2009.
|
# Hendrik Richter <hendrikr@gnome.org>, 2009.
|
||||||
# Mario Blättermann <mariobl@gnome.org>, 2009, 2010.
|
|
||||||
# Christian Kirbach <Christian.Kirbach@googlemail.com>, 2009, 2010.
|
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: HEAD\n"
|
||||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"shell&component=general\n"
|
"POT-Creation-Date: 2009-08-20 16:47+0200\n"
|
||||||
"POT-Creation-Date: 2010-05-17 18:24+0000\n"
|
"PO-Revision-Date: 2009-08-20 16:49+0200\n"
|
||||||
"PO-Revision-Date: 2010-05-18 22:06+0100\n"
|
"Last-Translator: Hendrik Richter <hendrikr@gnome.org>\n"
|
||||||
"Last-Translator: Mario Blättermann <mariobl@gnome.org>\n"
|
|
||||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: UTF-8\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Poedit-Language: German\n"
|
|
||||||
"X-Poedit-Country: GERMANY\n"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
msgid "GNOME Shell"
|
msgid "GNOME Shell"
|
||||||
@ -33,307 +26,148 @@ msgstr "GNOME-Shell"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Fenster verwalten und Anwendungen starten"
|
msgstr "Fenster verwalten und Anwendungen starten"
|
||||||
|
|
||||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:1
|
#. left side
|
||||||
msgid "Clock"
|
#: ../js/ui/panel.js:266
|
||||||
msgstr "Uhr"
|
msgid "Activities"
|
||||||
|
msgstr "Aktivitäten"
|
||||||
|
|
||||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:2
|
#. Translators: This is a time format.
|
||||||
msgid "Customize the panel clock"
|
#: ../js/ui/panel.js:433
|
||||||
msgstr "Die Uhr im Panel anpassen"
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:1
|
#: ../js/ui/dash.js:251
|
||||||
#| msgid "<b>Clock Format</b>"
|
msgid "Find apps or documents"
|
||||||
msgid "Clock Format"
|
msgstr "Anwendungen oder Dokumente suchen"
|
||||||
msgstr "Uhr-Format"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:2
|
#: ../js/ui/dash.js:369
|
||||||
msgid "Clock Preferences"
|
msgid "Browse"
|
||||||
msgstr "Uhr-Einstellungen"
|
msgstr "Durchsuchen"
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:3
|
|
||||||
#| msgid "<b>Panel Display</b>"
|
|
||||||
msgid "Panel Display"
|
|
||||||
msgstr "Panel-Anzeige"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:4
|
|
||||||
msgid "Show seco_nds"
|
|
||||||
msgstr "_Sekunden anzeigen"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:5
|
|
||||||
msgid "Show the _date"
|
|
||||||
msgstr "_Datum anzeigen"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:6
|
|
||||||
msgid "_12 hour format"
|
|
||||||
msgstr "_12-Stunden-Format"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:7
|
|
||||||
msgid "_24 hour format"
|
|
||||||
msgstr "_24-Stunden-Format"
|
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/appDisplay.js:306 ../js/ui/dash.js:850
|
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "ANWENDUNGEN"
|
msgstr "ANWENDUNGEN"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:338
|
#. **** Documents ****
|
||||||
msgid "PREFERENCES"
|
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
||||||
msgstr "EINSTELLUNGEN"
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
|
||||||
#: ../js/ui/appDisplay.js:705
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "Neues Fenster"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:709
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Aus Favoriten entfernen"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:710
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Zu Favoriten hinzufügen"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1037
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Hier ablegen, um zu Favoriten hinzuzufügen"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "%s wurde zu Ihren Favoriten hinzugefügt"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "%s wurde aus Ihren Favoriten entfernt"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:189
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "Suchen"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:505
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "Suche läuft …"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:519
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "Keine passenden Ergebnisse."
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:869 ../js/ui/placeDisplay.js:543
|
#: ../js/ui/dash.js:598
|
||||||
msgid "PLACES & DEVICES"
|
msgid "PLACES"
|
||||||
msgstr "ORTE UND GERÄTE"
|
msgstr "ORTE"
|
||||||
|
|
||||||
#. **** Documents ****
|
#: ../js/ui/runDialog.js:75
|
||||||
#: ../js/ui/dash.js:876 ../js/ui/docDisplay.js:489
|
|
||||||
msgid "RECENT ITEMS"
|
|
||||||
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:466
|
|
||||||
msgid "No extensions installed"
|
|
||||||
msgstr "Keine Erweiterungen installiert"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:503
|
|
||||||
msgid "Enabled"
|
|
||||||
msgstr "Aktiviert"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:505
|
|
||||||
msgid "Disabled"
|
|
||||||
msgstr "Deaktiviert"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:507
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "Fehler"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:509
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr "Veraltet"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:534
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "Quelle zeigen"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:540
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "Webseite"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:161
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "Rückgängig"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:535
|
|
||||||
msgid "Quit"
|
|
||||||
msgstr "Beenden"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:740
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Aktivitäten"
|
|
||||||
|
|
||||||
#. Translators: This is the time format with date used
|
|
||||||
#. in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:955
|
|
||||||
msgid "%a %b %e, %R:%S"
|
|
||||||
msgstr "%a, %e. %b, %R:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:956
|
|
||||||
msgid "%a %b %e, %R"
|
|
||||||
msgstr "%a, %e. %b, %R"
|
|
||||||
|
|
||||||
#. Translators: This is the time format without date used
|
|
||||||
#. in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:960
|
|
||||||
msgid "%a %R:%S"
|
|
||||||
msgstr "%a %R:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:961
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%a %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format with date used
|
|
||||||
#. for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:968
|
|
||||||
msgid "%a %b %e, %l:%M:%S %p"
|
|
||||||
msgstr "%a, %e. %b, %H:%M:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:969
|
|
||||||
msgid "%a %b %e, %l:%M %p"
|
|
||||||
msgstr "%a, %e. %b, %H:%M"
|
|
||||||
|
|
||||||
#. Translators: This is a time format without date used
|
|
||||||
#. for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:973
|
|
||||||
msgid "%a %l:%M:%S %p"
|
|
||||||
msgstr "%a %H:%M:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:974
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a %H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:108
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "»%s« konnte nicht ausgehängt werden"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:111
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "Erneut versuchen"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:156
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Verbinden mit …"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:231
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Bitte geben Sie einen Befehl ein:"
|
msgstr "Bitte geben Sie einen Befehl ein:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:375
|
#: ../src/gdmuser/gdm-user.c:243
|
||||||
#, c-format
|
msgid "Manager"
|
||||||
msgid "Execution of '%s' failed:"
|
msgstr "Verwaltung"
|
||||||
msgstr "Ausführung von »%s« ist gescheitert:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:90
|
#: ../src/gdmuser/gdm-user.c:244
|
||||||
msgid "Available"
|
msgid "The user manager object this user is controlled by."
|
||||||
msgstr "Verfügbar"
|
msgstr "Das Benutzerverwaltungsobjekt welches diesen Benutzer überwacht."
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:94
|
#: ../src/shell-global.c:841
|
||||||
msgid "Busy"
|
|
||||||
msgstr "Beschäftigt"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:98
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "Unsichtbar"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:105
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Benutzerinformationen …"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:109
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "Systemeinstellungen …"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:116
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Bildschirm sperren"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:120
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Benutzer wechseln"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:125
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Abmelden …"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:129
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Ausschalten …"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:47
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has finished starting"
|
|
||||||
msgstr "Start von %s ist abgeschlossen"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:49
|
|
||||||
#, c-format
|
|
||||||
msgid "'%s' is ready"
|
|
||||||
msgstr "»%s« ist bereit"
|
|
||||||
|
|
||||||
#: ../js/ui/workspacesView.js:239
|
|
||||||
msgid ""
|
|
||||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
|
||||||
msgstr ""
|
|
||||||
"Es kann keine weitere Arbeitsfläche hinzugefügt werden, weil das Maximum an "
|
|
||||||
"Arbeitsflächen erreicht worden ist."
|
|
||||||
|
|
||||||
#: ../js/ui/workspacesView.js:256
|
|
||||||
msgid "Can't remove the first workspace."
|
|
||||||
msgstr "Die erste Arbeitsfläche kann nicht entfernt werden."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:976
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Vor weniger als einer Minute"
|
msgstr "Vor weniger als einer Minute"
|
||||||
|
|
||||||
#: ../src/shell-global.c:980
|
#: ../src/shell-global.c:844
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "Vor %d Minute"
|
msgstr[0] "Vor %d Minute"
|
||||||
msgstr[1] "Vor %d Minuten"
|
msgstr[1] "Vor %d Minuten"
|
||||||
|
|
||||||
#: ../src/shell-global.c:985
|
#: ../src/shell-global.c:847
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "Vor %d Stunde"
|
msgstr[0] "Vor %d Stunde"
|
||||||
msgstr[1] "Vor %d Stunden"
|
msgstr[1] "Vor %d Stunden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:990
|
#: ../src/shell-global.c:850
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "Vor %d Tag"
|
msgstr[0] "Vor %d Tag"
|
||||||
msgstr[1] "Vor %d Tagen"
|
msgstr[1] "Vor %d Tagen"
|
||||||
|
|
||||||
#: ../src/shell-global.c:995
|
#: ../src/shell-global.c:853
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
msgstr[0] "Vor %d Woche"
|
msgstr[0] "Vor %d Woche"
|
||||||
msgstr[1] "Vor %d Wochen"
|
msgstr[1] "Vor %d Wochen"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Unbekannt"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Bildschirm kann nicht gesperrt werden: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr ""
|
||||||
|
"Der Bildschirmschoner kann vorübergehend nicht auf einen leeren Schirm "
|
||||||
|
"gesetzt werden: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Abmelden ist nicht möglich: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Benutzerinformationen …"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Seitenleiste"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Systemeinstellungen …"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Bildschirm sperren"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Benutzer wechseln"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Abmelden …"
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Ausschalten …"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "Persönlicher Ordner"
|
msgstr "Persönlicher Ordner"
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
#. Translators: this is the same string as the one found in
|
||||||
#. * nautilus
|
#. * nautilus
|
||||||
#: ../src/shell-uri-util.c:104
|
#: ../src/shell-uri-util.c:102
|
||||||
msgid "File System"
|
msgid "File System"
|
||||||
msgstr "Dateisystem"
|
msgstr "Dateisystem"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
#: ../src/shell-uri-util.c:248
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Suchen"
|
msgstr "Suchen"
|
||||||
|
|
||||||
@ -342,60 +176,7 @@ msgstr "Suchen"
|
|||||||
#. * example, "Trash: some-directory". It means that the
|
#. * example, "Trash: some-directory". It means that the
|
||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:300
|
#: ../src/shell-uri-util.c:298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
#~ msgid "Sidebar"
|
|
||||||
#~ msgstr "Seitenleiste"
|
|
||||||
|
|
||||||
#~ msgid "%H:%M"
|
|
||||||
#~ msgstr "%H:%M"
|
|
||||||
|
|
||||||
#~ msgid "Applications"
|
|
||||||
#~ msgstr "Anwendungen"
|
|
||||||
|
|
||||||
#~ msgid "Recent Documents"
|
|
||||||
#~ msgstr "Zuletzt geöffnete Dokumente"
|
|
||||||
|
|
||||||
#~ msgid "Frequent"
|
|
||||||
#~ msgstr "Häufig"
|
|
||||||
|
|
||||||
#~ msgid "More"
|
|
||||||
#~ msgstr "Mehr"
|
|
||||||
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(alle sehen)"
|
|
||||||
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "ORTE"
|
|
||||||
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "SUCHERGEBNISSE"
|
|
||||||
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "Unbekannt"
|
|
||||||
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "Bildschirm kann nicht gesperrt werden: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "Der Bildschirmschoner kann vorübergehend nicht auf einen leeren Schirm "
|
|
||||||
#~ "gesetzt werden: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "Abmelden ist nicht möglich: %s"
|
|
||||||
|
|
||||||
#~ msgid "Find apps or documents"
|
|
||||||
#~ msgstr "Anwendungen oder Dokumente suchen"
|
|
||||||
|
|
||||||
#~ msgid "Browse"
|
|
||||||
#~ msgstr "Durchsuchen"
|
|
||||||
|
|
||||||
#~ msgid "Manager"
|
|
||||||
#~ msgstr "Verwaltung"
|
|
||||||
|
|
||||||
#~ msgid "The user manager object this user is controlled by."
|
|
||||||
#~ msgstr "Das Benutzerverwaltungsobjekt welches diesen Benutzer überwacht."
|
|
||||||
|
298
po/el.po
@ -1,298 +0,0 @@
|
|||||||
# translation of gnome-shell.po.master.po to Greek
|
|
||||||
# Greek translation for gnome-shell.
|
|
||||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
|
||||||
#
|
|
||||||
# Jennie Petoumenou <epetoumenou@gmail.com>, 2009.
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: gnome-shell.po.master\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2010-03-28 10:46+0300\n"
|
|
||||||
"PO-Revision-Date: 2010-03-28 10:53+0200\n"
|
|
||||||
"Last-Translator: Kostas Papadimas <pkst@gnome.org>\n"
|
|
||||||
"Language-Team: Greek <<team AT BLOCKSPAM gnome DOT gr>>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
"X-Generator: KBabel 1.11.4\n"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
|
||||||
msgid "GNOME Shell"
|
|
||||||
msgstr "Κέλυφος GNOME"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
|
||||||
msgid "Window management and application launching"
|
|
||||||
msgstr "Διαχείριση παραθύρων και εκκίνηση εφαρμογών"
|
|
||||||
|
|
||||||
#. **** Applications ****
|
|
||||||
#: ../js/ui/appDisplay.js:312
|
|
||||||
#: ../js/ui/dash.js:855
|
|
||||||
msgid "APPLICATIONS"
|
|
||||||
msgstr "ΕΦΑΡΜΟΓΕΣ"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:344
|
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "ΠΡΟΤΙΜΗΣΕΙΣ"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:756
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "Νέο παράθυρο"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:760
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Αφαίρεση από τα αγαπημένα"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:761
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Προσθήκη στα αγαπημένα"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1113
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Σύρετε εδώ για να προσθέσετε αγαπημένα"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "%s προστέθηκε στα αγαπημένα σας"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "%s αφαιρέθηκε από τα αγαπημένα σας"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:194
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "Εύρεση"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:510
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "Αναζήτηση..."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:524
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "Δεν βρέθηκαν ταιριάσματα."
|
|
||||||
|
|
||||||
#. **** Places ****
|
|
||||||
#. Translators: This is in the sense of locations for documents,
|
|
||||||
#. network locations, etc.
|
|
||||||
#: ../js/ui/dash.js:874
|
|
||||||
#: ../js/ui/placeDisplay.js:582
|
|
||||||
msgid "PLACES & DEVICES"
|
|
||||||
msgstr "ΤΟΠΟΘΕΣΙΕΣ $ ΣΥΣΚΕΥΕΣ"
|
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:881
|
|
||||||
#: ../js/ui/docDisplay.js:488
|
|
||||||
msgid "RECENT ITEMS"
|
|
||||||
msgstr "ΠΡΟΣΦΑΤΑ ΑΝΤΙΚΕΙΜΕΝΑ"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:363
|
|
||||||
msgid "No extensions installed"
|
|
||||||
msgstr "Δεν υπάρχουν εγκατεστημένες επεκτάσεις"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:400
|
|
||||||
msgid "Enabled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:402
|
|
||||||
msgid "Disabled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:404
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "Σφάλμα"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:406
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:431
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "Προβολή πηγής"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:437
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "Ιστοσελίδα"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:182
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "Αναίρεση"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:385
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Δραστηριότητες"
|
|
||||||
|
|
||||||
#. Translators: This is the time format used in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:616
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%a %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format used for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:619
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a %l:%M %p"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:108
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "Αποτυχία αποπροσάρτησης '%s'"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:111
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "Προσπάθεια ξανά"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:156
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Σύνδεση σε..."
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:232
|
|
||||||
msgid "Please enter a command:"
|
|
||||||
msgstr "Παρακαλώ εισάγετε μία εντολή:"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:376
|
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "Η εκτέλεση του '%s' απέτυχε:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:107
|
|
||||||
msgid "Available"
|
|
||||||
msgstr "Διαθέσιμος"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:112
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr "Απασχολημένος"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:117
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "Αόρατος"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:126
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Πληροφορίες λογαριασμού..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:132
|
|
||||||
msgid "Sidebar"
|
|
||||||
msgstr "Πλευρική στήλη"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:142
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "Προστιμήσεις συστήματος..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:151
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Κλείδωμα οθόνης"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:156
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Αλλαγή χρήστη"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:162
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Αποσύνδεση..."
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:167
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Τερματισμός..."
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/widget.js:163
|
|
||||||
msgid "%H:%M"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:317
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Εφαρμογές"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:339
|
|
||||||
msgid "Recent Documents"
|
|
||||||
msgstr "Πρόσφατα έγγραφα"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:47
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has finished starting"
|
|
||||||
msgstr "%s ολοκλήρωσε την εκκίνηση "
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:49
|
|
||||||
#, c-format
|
|
||||||
msgid "'%s' is ready"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:967
|
|
||||||
msgid "Less than a minute ago"
|
|
||||||
msgstr "Λιγότερο από ένα λεπτό πριν"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:971
|
|
||||||
#, c-format
|
|
||||||
msgid "%d minute ago"
|
|
||||||
msgid_plural "%d minutes ago"
|
|
||||||
msgstr[0] "%d λεπτό πριν"
|
|
||||||
msgstr[1] "%d λεπτά πριν"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:976
|
|
||||||
#, c-format
|
|
||||||
msgid "%d hour ago"
|
|
||||||
msgid_plural "%d hours ago"
|
|
||||||
msgstr[0] "%d ώρα πριν"
|
|
||||||
msgstr[1] "%d ώρες πριν"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:981
|
|
||||||
#, c-format
|
|
||||||
msgid "%d day ago"
|
|
||||||
msgid_plural "%d days ago"
|
|
||||||
msgstr[0] "%d ημέρα πριν"
|
|
||||||
msgstr[1] "%d ημέρες πριν"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:986
|
|
||||||
#, c-format
|
|
||||||
msgid "%d week ago"
|
|
||||||
msgid_plural "%d weeks ago"
|
|
||||||
msgstr[0] "%d εβδομάδα πριν"
|
|
||||||
msgstr[1] "%d εβδομάδες πριν"
|
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
|
||||||
msgid "Home Folder"
|
|
||||||
msgstr "Προσωπικός φάκελος"
|
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
|
||||||
#. * nautilus
|
|
||||||
#: ../src/shell-uri-util.c:104
|
|
||||||
msgid "File System"
|
|
||||||
msgstr "Σύστημα αρχείων"
|
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
|
||||||
msgid "Search"
|
|
||||||
msgstr "Αναζήτηση"
|
|
||||||
|
|
||||||
#. Translators: the first string is the name of a gvfs
|
|
||||||
#. * method, and the second string is a path. For
|
|
||||||
#. * example, "Trash: some-directory". It means that the
|
|
||||||
#. * directory called "some-directory" is in the trash.
|
|
||||||
#.
|
|
||||||
#: ../src/shell-uri-util.c:300
|
|
||||||
#, c-format
|
|
||||||
msgid "%1$s: %2$s"
|
|
||||||
msgstr "%1$s: %2$s"
|
|
||||||
|
|
||||||
#~ msgid "More"
|
|
||||||
#~ msgstr "Περισσότερα"
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(εμφάνιση όλων)"
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "ΤΟΠΟΘΕΣΙΕΣ"
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "ΑΠΟΤΕΛΕΣΜΑΤΑ ΑΝΑΖΗΤΗΣΗΣ"
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "Άγνωστο"
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "Αδύνατο το κλείδωμα της οθόνης: %s"
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "Δεν είναι δυνατή η προσωρινή ρύθμιση της προστασίας οθόνης σε κενή οθόνη: "
|
|
||||||
#~ "%s"
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "Αδύνατη η αποσύνδεση: %s"
|
|
||||||
|
|
308
po/en_GB.po
@ -2,22 +2,20 @@
|
|||||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Philip Withnall <philip@tecnocode.co.uk>, 2009.
|
# Philip Withnall <philip@tecnocode.co.uk>, 2009.
|
||||||
# Bruce Cowan <bcowan@fastmail.co.uk>, 2010.
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
"shell&component=general\n"
|
"shell&component=general\n"
|
||||||
"POT-Creation-Date: 2010-03-20 22:31+0000\n"
|
"POT-Creation-Date: 2009-09-12 12:41+0000\n"
|
||||||
"PO-Revision-Date: 2010-03-20 22:32+0100\n"
|
"PO-Revision-Date: 2009-09-12 12:41+0000\n"
|
||||||
"Last-Translator: Bruce Cowan <bcowan@fastmail.co.uk>\n"
|
"Last-Translator: Philip Withnall <philip@tecnocode.co.uk>\n"
|
||||||
"Language-Team: British English <en@li.org>\n"
|
"Language-Team: British English <en_GB@li.org>\n"
|
||||||
"Language: en_GB\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Generator: Virtaal 0.5.2\n"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
msgid "GNOME Shell"
|
msgid "GNOME Shell"
|
||||||
@ -27,231 +25,151 @@ msgstr "GNOME Shell"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Window management and application launching"
|
msgstr "Window management and application launching"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:269
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "Activities"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:452
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %l:%M %p"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:283
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "Find…"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:400
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "Browse"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(see all)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/appDisplay.js:311 ../js/ui/dash.js:852
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APPLICATIONS"
|
msgstr "APPLICATIONS"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:343
|
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "PREFERENCES"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:728
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "New Window"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:732
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Remove from Favourites"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:733
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Add to Favourites"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1085
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Drag here to add favourites"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "%s has been added to your favourites."
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "%s has been removed from your favourites."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:194
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "Find"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:507
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "Searching…"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:521
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "No matching results."
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:871 ../js/ui/placeDisplay.js:579
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES & DEVICES"
|
msgid "PLACES"
|
||||||
msgstr "PLACES & DEVICES"
|
msgstr "PLACES"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:878 ../js/ui/docDisplay.js:488
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
msgid "RECENT ITEMS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "RECENT ITEMS"
|
msgstr "RECENT DOCUMENTS"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:363
|
#. **** Search Results ****
|
||||||
msgid "No extensions installed"
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
msgstr "No extensions installed"
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "SEARCH RESULTS"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:400
|
#: ../js/ui/dash.js:814
|
||||||
msgid "Enabled"
|
msgid "PREFERENCES"
|
||||||
msgstr "Enabled"
|
msgstr "PREFERENCES"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:402
|
#: ../js/ui/runDialog.js:90
|
||||||
msgid "Disabled"
|
|
||||||
msgstr "Disabled"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:404
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "Error"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:406
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr "Out of date"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:431
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "View Source"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:437
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "Web Page"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:182
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "Undo"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:385
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Activities"
|
|
||||||
|
|
||||||
#. Translators: This is the time format used in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:616
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%a %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format used for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:619
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a %l:%M %p"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:103
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "Failed to unmount '%s'"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:106
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "Retry"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:151
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Connect to…"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:232
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Please enter a command:"
|
msgstr "Please enter a command:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:374
|
#: ../src/shell-global.c:799
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "Execution of '%s' failed:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:107
|
|
||||||
msgid "Available"
|
|
||||||
msgstr "Available"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:112
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr "Busy"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:117
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "Invisible"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:126
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Account Information…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:132
|
|
||||||
msgid "Sidebar"
|
|
||||||
msgstr "Sidebar"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:142
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "System Preferences…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:151
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Lock Screen"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:156
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Switch User"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:162
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Log Out…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:167
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Shut Down…"
|
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
|
||||||
#: ../js/ui/widget.js:163
|
|
||||||
msgid "%H:%M"
|
|
||||||
msgstr "%H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:317
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Applications"
|
|
||||||
|
|
||||||
#: ../js/ui/widget.js:339
|
|
||||||
msgid "Recent Documents"
|
|
||||||
msgstr "Recent Documents"
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:967
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Less than a minute ago"
|
msgstr "Less than a minute ago"
|
||||||
|
|
||||||
#: ../src/shell-global.c:971
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minute ago"
|
msgstr[0] "%d minute ago"
|
||||||
msgstr[1] "%d minutes ago"
|
msgstr[1] "%d minutes ago"
|
||||||
|
|
||||||
#: ../src/shell-global.c:976
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d hour ago"
|
msgstr[0] "%d hour ago"
|
||||||
msgstr[1] "%d hours ago"
|
msgstr[1] "%d hours ago"
|
||||||
|
|
||||||
#: ../src/shell-global.c:981
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d day ago"
|
msgstr[0] "%d day ago"
|
||||||
msgstr[1] "%d days ago"
|
msgstr[1] "%d days ago"
|
||||||
|
|
||||||
#: ../src/shell-global.c:986
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
msgstr[0] "%d week ago"
|
msgstr[0] "%d week ago"
|
||||||
msgstr[1] "%d weeks ago"
|
msgstr[1] "%d weeks ago"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Unknown"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Can't lock screen: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Can't logout: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Account Information…"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Sidebar"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "System Preferences…"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Lock Screen"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Switch User"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Log Out…"
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Shut Down…"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "Home Folder"
|
msgstr "Home Folder"
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
#. Translators: this is the same string as the one found in
|
||||||
#. * nautilus
|
#. * nautilus
|
||||||
#: ../src/shell-uri-util.c:104
|
#: ../src/shell-uri-util.c:102
|
||||||
msgid "File System"
|
msgid "File System"
|
||||||
msgstr "File System"
|
msgstr "File System"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
#: ../src/shell-uri-util.c:248
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Search"
|
msgstr "Search"
|
||||||
|
|
||||||
@ -260,31 +178,7 @@ msgstr "Search"
|
|||||||
#. * example, "Trash: some-directory". It means that the
|
#. * example, "Trash: some-directory". It means that the
|
||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:300
|
#: ../src/shell-uri-util.c:298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
#~ msgid "Browse"
|
|
||||||
#~ msgstr "Browse"
|
|
||||||
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(see all)"
|
|
||||||
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "PLACES"
|
|
||||||
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "SEARCH RESULTS"
|
|
||||||
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "Unknown"
|
|
||||||
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "Can't lock screen: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "Can't logout: %s"
|
|
||||||
|
388
po/es.po
@ -1,20 +1,20 @@
|
|||||||
# Spanish translation of gnome-shell.
|
# Spanish translation of gnome-shell.
|
||||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Jorge González <jorgegonz@svn.gnome.org>, 2009, 2010.
|
|
||||||
#
|
#
|
||||||
|
# Jorge González <jorgegonz@svn.gnome.org>, 2009.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
"shell&component=general\n"
|
"shell&component=general\n"
|
||||||
"POT-Creation-Date: 2010-05-19 16:31+0000\n"
|
"POT-Creation-Date: 2009-09-27 16:05+0000\n"
|
||||||
"PO-Revision-Date: 2010-05-25 18:28+0200\n"
|
"PO-Revision-Date: 2009-09-28 21:58+0200\n"
|
||||||
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
|
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
|
||||||
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: UTF-8\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
@ -25,303 +25,153 @@ msgstr "GNOME Shell"
|
|||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Gestión de ventanas e inicio de aplicaciones"
|
msgstr "Gestión de ventanas e inicio de aplicaciones"
|
||||||
|
|
||||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:1
|
#. left side
|
||||||
msgid "Clock"
|
#: ../js/ui/panel.js:269
|
||||||
msgstr "Reloj"
|
msgid "Activities"
|
||||||
|
msgstr "Actividades"
|
||||||
|
|
||||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:2
|
#. Translators: This is a time format.
|
||||||
msgid "Customize the panel clock"
|
#: ../js/ui/panel.js:452
|
||||||
msgstr "Personalizar el reloj del panel"
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:1
|
#: ../js/ui/dash.js:283
|
||||||
#| msgid "<b>Clock Format</b>"
|
msgid "Find..."
|
||||||
msgid "Clock Format"
|
msgstr "Buscar…"
|
||||||
msgstr "Formato del reloj"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:2
|
#: ../js/ui/dash.js:400
|
||||||
msgid "Clock Preferences"
|
msgid "More"
|
||||||
msgstr "Preferencias del reloj"
|
msgstr "Más"
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:3
|
#: ../js/ui/dash.js:543
|
||||||
#| msgid "<b>Panel Display</b>"
|
msgid "(see all)"
|
||||||
msgid "Panel Display"
|
msgstr "(ver todo)"
|
||||||
msgstr "Panel de visualización"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:4
|
|
||||||
msgid "Show seco_nds"
|
|
||||||
msgstr "Mostrar los segu_ndos"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:5
|
|
||||||
msgid "Show the _date"
|
|
||||||
msgstr "Mostrar la _fecha"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:6
|
|
||||||
msgid "_12 hour format"
|
|
||||||
msgstr "Formato _12 horas"
|
|
||||||
|
|
||||||
#: ../data/clock-preferences.ui.h:7
|
|
||||||
msgid "_24 hour format"
|
|
||||||
msgstr "Formato _24 horas"
|
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/appDisplay.js:306 ../js/ui/dash.js:850
|
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLICACIONES"
|
msgstr "APLICACIONES"
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:338
|
|
||||||
msgid "PREFERENCES"
|
|
||||||
msgstr "PREFERENCIAS"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:705
|
|
||||||
msgid "New Window"
|
|
||||||
msgstr "Ventana nueva"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:709
|
|
||||||
msgid "Remove from Favorites"
|
|
||||||
msgstr "Quitar de los favoritos"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:710
|
|
||||||
msgid "Add to Favorites"
|
|
||||||
msgstr "Añadir a los favoritos"
|
|
||||||
|
|
||||||
#: ../js/ui/appDisplay.js:1037
|
|
||||||
msgid "Drag here to add favorites"
|
|
||||||
msgstr "Arrastrar aquí para añadir a los favoritos"
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:89
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been added to your favorites."
|
|
||||||
msgstr "Se ha añadido %s a sus favoritos."
|
|
||||||
|
|
||||||
#: ../js/ui/appFavorites.js:107
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has been removed from your favorites."
|
|
||||||
msgstr "Se ha quitado %s de sus favoritos."
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:189
|
|
||||||
msgid "Find"
|
|
||||||
msgstr "Buscar"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:505
|
|
||||||
msgid "Searching..."
|
|
||||||
msgstr "Buscando…"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:519
|
|
||||||
msgid "No matching results."
|
|
||||||
msgstr "No se encontró ningún resultado coincidente."
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:869 ../js/ui/placeDisplay.js:543
|
#: ../js/ui/dash.js:783
|
||||||
msgid "PLACES & DEVICES"
|
msgid "PLACES"
|
||||||
msgstr "LUGARES Y DISPOSITIVOS"
|
msgstr "LUGARES"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:876 ../js/ui/docDisplay.js:489
|
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
|
||||||
msgid "RECENT ITEMS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "ELEMENTOS RECIENTES"
|
msgstr "DOCUMENTOS RECIENTES"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:466
|
#. **** Search Results ****
|
||||||
msgid "No extensions installed"
|
#: ../js/ui/dash.js:815 ../js/ui/dash.js:958
|
||||||
msgstr "No hay extensiones instaladas"
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "RESULTADOS DE LA BÚSQUEDA"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:503
|
#: ../js/ui/dash.js:830
|
||||||
msgid "Enabled"
|
msgid "PREFERENCES"
|
||||||
msgstr "Activado"
|
msgstr "PREFERENCIAS"
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:505
|
#: ../js/ui/runDialog.js:94
|
||||||
msgid "Disabled"
|
|
||||||
msgstr "Desactivado"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:507
|
|
||||||
msgid "Error"
|
|
||||||
msgstr "Error"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:509
|
|
||||||
msgid "Out of date"
|
|
||||||
msgstr "Caducado"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:534
|
|
||||||
msgid "View Source"
|
|
||||||
msgstr "Ver fuente"
|
|
||||||
|
|
||||||
#: ../js/ui/lookingGlass.js:540
|
|
||||||
msgid "Web Page"
|
|
||||||
msgstr "Página web"
|
|
||||||
|
|
||||||
#: ../js/ui/overview.js:161
|
|
||||||
msgid "Undo"
|
|
||||||
msgstr "Deshacer"
|
|
||||||
|
|
||||||
#. Button on the left side of the panel.
|
|
||||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
|
||||||
#: ../js/ui/panel.js:774
|
|
||||||
msgid "Activities"
|
|
||||||
msgstr "Actividades"
|
|
||||||
|
|
||||||
#. Translators: This is the time format with date used
|
|
||||||
#. in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:989
|
|
||||||
msgid "%a %b %e, %R:%S"
|
|
||||||
msgstr "%a %e de %b, %R:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:990
|
|
||||||
msgid "%a %b %e, %R"
|
|
||||||
msgstr "%a %e de %b, %R"
|
|
||||||
|
|
||||||
#. Translators: This is the time format without date used
|
|
||||||
#. in 24-hour mode.
|
|
||||||
#: ../js/ui/panel.js:994
|
|
||||||
msgid "%a %R:%S"
|
|
||||||
msgstr "%a %R:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:995
|
|
||||||
msgid "%a %R"
|
|
||||||
msgstr "%a %R"
|
|
||||||
|
|
||||||
#. Translators: This is a time format with date used
|
|
||||||
#. for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:1002
|
|
||||||
msgid "%a %b %e, %l:%M:%S %p"
|
|
||||||
msgstr "%a %e de %b, %H:%M:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:1003
|
|
||||||
msgid "%a %b %e, %l:%M %p"
|
|
||||||
msgstr "%a %e de %b, %H:%M"
|
|
||||||
|
|
||||||
#. Translators: This is a time format without date used
|
|
||||||
#. for AM/PM.
|
|
||||||
#: ../js/ui/panel.js:1007
|
|
||||||
msgid "%a %l:%M:%S %p"
|
|
||||||
msgstr "%a %H:%M:%S"
|
|
||||||
|
|
||||||
#: ../js/ui/panel.js:1008
|
|
||||||
msgid "%a %l:%M %p"
|
|
||||||
msgstr "%a %H:%M"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:108
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to unmount '%s'"
|
|
||||||
msgstr "Falló al desmontar «%s»"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:111
|
|
||||||
msgid "Retry"
|
|
||||||
msgstr "Reintentar"
|
|
||||||
|
|
||||||
#: ../js/ui/placeDisplay.js:156
|
|
||||||
msgid "Connect to..."
|
|
||||||
msgstr "Conectar a…"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:231
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Introduzca un comando:"
|
msgstr "Introduzca un comando:"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:375
|
#: ../src/shell-global.c:799
|
||||||
#, c-format
|
|
||||||
msgid "Execution of '%s' failed:"
|
|
||||||
msgstr "Falló la ejecución de «%s»:"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:90
|
|
||||||
msgid "Available"
|
|
||||||
msgstr "Disponible"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:94
|
|
||||||
msgid "Busy"
|
|
||||||
msgstr "Ocupado"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:98
|
|
||||||
msgid "Invisible"
|
|
||||||
msgstr "Invisible"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:105
|
|
||||||
msgid "Account Information..."
|
|
||||||
msgstr "Información de la cuenta…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:109
|
|
||||||
msgid "System Preferences..."
|
|
||||||
msgstr "Preferencias del sistema…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:116
|
|
||||||
msgid "Lock Screen"
|
|
||||||
msgstr "Bloquear la pantalla"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:120
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Cambiar de usuario"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:125
|
|
||||||
msgid "Log Out..."
|
|
||||||
msgstr "Salir…"
|
|
||||||
|
|
||||||
#: ../js/ui/statusMenu.js:129
|
|
||||||
msgid "Shut Down..."
|
|
||||||
msgstr "Apagar…"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:47
|
|
||||||
#, c-format
|
|
||||||
msgid "%s has finished starting"
|
|
||||||
msgstr "%s finalizó su lanzamiento"
|
|
||||||
|
|
||||||
#: ../js/ui/windowAttentionHandler.js:49
|
|
||||||
#, c-format
|
|
||||||
msgid "'%s' is ready"
|
|
||||||
msgstr "«%s» está preparado"
|
|
||||||
|
|
||||||
#: ../js/ui/workspacesView.js:239
|
|
||||||
msgid ""
|
|
||||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
|
||||||
msgstr ""
|
|
||||||
"No se puede añadir un área de trabajo nueva porque se ha llegado al límite "
|
|
||||||
"de áreas de trabajo."
|
|
||||||
|
|
||||||
#: ../js/ui/workspacesView.js:256
|
|
||||||
msgid "Can't remove the first workspace."
|
|
||||||
msgstr "No se puede quitar el primer área de trabajo."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:976
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Hace menos de un minuto"
|
msgstr "Hace menos de un minuto"
|
||||||
|
|
||||||
#: ../src/shell-global.c:980
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "Hace %d minuto"
|
msgstr[0] "Hace %d minuto"
|
||||||
msgstr[1] "Hace %d minutos"
|
msgstr[1] "Hace %d minutos"
|
||||||
|
|
||||||
#: ../src/shell-global.c:985
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "Hace %d hora"
|
msgstr[0] "Hace %d hora"
|
||||||
msgstr[1] "Hace %d horas"
|
msgstr[1] "Hace %d horas"
|
||||||
|
|
||||||
#: ../src/shell-global.c:990
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "Hace %d día"
|
msgstr[0] "Hace %d día"
|
||||||
msgstr[1] "Hace %d días"
|
msgstr[1] "Hace %d días"
|
||||||
|
|
||||||
#: ../src/shell-global.c:995
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
msgstr[0] "Hace %d semana"
|
msgstr[0] "Hace %d semana"
|
||||||
msgstr[1] "Hace %d semanas"
|
msgstr[1] "Hace %d semanas"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:89
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Desconocido"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "No se puede bloquear la pantalla: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr ""
|
||||||
|
"No se puede establecer temporalmente el salvapantallas a oscurecer pantalla: "
|
||||||
|
"%s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "No se puede salir de la sesión: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Información de la cuenta…"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Barra lateral"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Preferencias del sistema…"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Bloquear la pantalla"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Cambiar de usuario"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Salir…"
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Apagar…"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "Carpeta personal"
|
msgstr "Carpeta personal"
|
||||||
|
|
||||||
#. Translators: this is the same string as the one found in
|
#. Translators: this is the same string as the one found in
|
||||||
#. * nautilus
|
#. * nautilus
|
||||||
#: ../src/shell-uri-util.c:104
|
#: ../src/shell-uri-util.c:102
|
||||||
msgid "File System"
|
msgid "File System"
|
||||||
msgstr "Sistema de archivos"
|
msgstr "Sistema de archivos"
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:250
|
#: ../src/shell-uri-util.c:248
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Buscar"
|
msgstr "Buscar"
|
||||||
|
|
||||||
@ -330,55 +180,11 @@ msgstr "Buscar"
|
|||||||
#. * example, "Trash: some-directory". It means that the
|
#. * example, "Trash: some-directory". It means that the
|
||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:300
|
#: ../src/shell-uri-util.c:298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
#~ msgid "Quit"
|
|
||||||
#~ msgstr "Salir"
|
|
||||||
|
|
||||||
#~ msgid "Sidebar"
|
|
||||||
#~ msgstr "Barra lateral"
|
|
||||||
|
|
||||||
#~ msgid "%H:%M"
|
|
||||||
#~ msgstr "%H:%M"
|
|
||||||
|
|
||||||
#~ msgid "Applications"
|
|
||||||
#~ msgstr "Aplicaciones"
|
|
||||||
|
|
||||||
#~ msgid "Recent Documents"
|
|
||||||
#~ msgstr "Documentos recientes"
|
|
||||||
|
|
||||||
#~ msgid "PLACES"
|
|
||||||
#~ msgstr "LUGARES"
|
|
||||||
|
|
||||||
#~ msgid "Frequent"
|
|
||||||
#~ msgstr "Frecuentes"
|
|
||||||
|
|
||||||
#~ msgid "More"
|
|
||||||
#~ msgstr "Más"
|
|
||||||
|
|
||||||
#~ msgid "(see all)"
|
|
||||||
#~ msgstr "(ver todo)"
|
|
||||||
|
|
||||||
#~ msgid "SEARCH RESULTS"
|
|
||||||
#~ msgstr "RESULTADOS DE LA BÚSQUEDA"
|
|
||||||
|
|
||||||
#~ msgid "Unknown"
|
|
||||||
#~ msgstr "Desconocido"
|
|
||||||
|
|
||||||
#~ msgid "Can't lock screen: %s"
|
|
||||||
#~ msgstr "No se puede bloquear la pantalla: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "No se puede establecer temporalmente el salvapantallas a oscurecer "
|
|
||||||
#~ "pantalla: %s"
|
|
||||||
|
|
||||||
#~ msgid "Can't logout: %s"
|
|
||||||
#~ msgstr "No se puede salir de la sesión: %s"
|
|
||||||
|
|
||||||
#~ msgid "Browse"
|
#~ msgid "Browse"
|
||||||
#~ msgstr "Examine"
|
#~ msgstr "Examine"
|
||||||
|
|
||||||
|