Compare commits
403 Commits
overlay-de
...
nbtk-intro
Author | SHA1 | Date | |
---|---|---|---|
4f070317d2 | |||
661100abe8 | |||
3e90b11cfb | |||
4b4a1be420 | |||
1a4861ec4f | |||
2ac82da232 | |||
8f7e6f8117 | |||
d2b98701be | |||
faeda5dc8b | |||
70cb8e180b | |||
2232a92ba8 | |||
4743a8e750 | |||
e1390c7dd5 | |||
49ba54820c | |||
8ffa161a7f | |||
0eca3efcb0 | |||
9c3af62dc4 | |||
db0c2b5959 | |||
98215f497d | |||
9dbafe156e | |||
277dd7106a | |||
431f299756 | |||
d8d7f5f711 | |||
a07af9fb14 | |||
f1f11f1e76 | |||
c60a6a49de | |||
6687054474 | |||
60819b3a79 | |||
3e265b4bc6 | |||
e2aa2a00f0 | |||
1edc88a2bd | |||
271e4ca07e | |||
9f79296276 | |||
471006ba67 | |||
98bd590a5d | |||
9d88a13d3c | |||
159690b2d3 | |||
8a2bfd0e55 | |||
2ddc7cf00f | |||
04f10ceb4e | |||
ceefc5eea4 | |||
9feda69888 | |||
33f9895d71 | |||
2812c21322 | |||
7ac9fb2dd0 | |||
05c99241d6 | |||
9fb8dad80c | |||
004ad86e9d | |||
02c65fab8d | |||
dfe16f4af6 | |||
e52cb3c213 | |||
6e31e59b57 | |||
458778bcfd | |||
d8cabbee0b | |||
3029a4086b | |||
5598de6543 | |||
913aeae166 | |||
dddad9e1b5 | |||
4bfa68d209 | |||
42e3a93c20 | |||
05812ef7f9 | |||
a0df412deb | |||
678a88dbdb | |||
5e944c9a3b | |||
b28b60b47b | |||
16caa74386 | |||
470c65d046 | |||
ef6ea078dd | |||
37ee16b34d | |||
5880b3b0ed | |||
80a5f78eb2 | |||
4b727ef40d | |||
d0d79c5b3e | |||
0882da0a71 | |||
25410a730e | |||
22c445cffc | |||
42bf91fdc4 | |||
7f88e02a26 | |||
d540af847a | |||
2f78907aeb | |||
d471541495 | |||
fa5fb6b8a8 | |||
0a29cf6195 | |||
b7b4c54ab5 | |||
52abf266c0 | |||
11872cfb79 | |||
21309aa28f | |||
38d21c8edf | |||
090908439b | |||
0a17a28608 | |||
926643b025 | |||
1a834f7d8b | |||
3e54087e42 | |||
304b377dae | |||
ac4bcee050 | |||
553503dace | |||
90381ceea2 | |||
687814b6c6 | |||
6153094057 | |||
0245a0cd0e | |||
bcc3dc0711 | |||
3d499219da | |||
94b26888cf | |||
156fdf1fa3 | |||
2a3f9e8f83 | |||
849ce371ff | |||
a76ac5501c | |||
5803aa7e65 | |||
0fd6bc5172 | |||
0e3cea41e0 | |||
45c600cd25 | |||
7fb8e2d0ef | |||
2d5d54f3cd | |||
949359db5d | |||
5bd2695863 | |||
dfbbf9b436 | |||
a230ad9225 | |||
7a87474bcd | |||
479acf2d18 | |||
943c5e2edc | |||
1340413740 | |||
3adec65e20 | |||
d116f707c5 | |||
6f94b8cffe | |||
14a7e310fc | |||
bf680fdc7c | |||
851bf18265 | |||
452e98e3bc | |||
3cb54f6707 | |||
ed7881d6c9 | |||
ea1a45a878 | |||
003807334b | |||
24a5c3c19a | |||
62b2d69c2b | |||
cdbb7f8f5f | |||
ecc1f964c9 | |||
0f4e9189c5 | |||
799f56fe87 | |||
af9ab5dbb6 | |||
3486fcc89a | |||
1e2018d1b7 | |||
fb46bad665 | |||
e2d912c037 | |||
2879d9cdef | |||
300cefd66a | |||
72b4d2a234 | |||
02e438b1f8 | |||
58690c210e | |||
61f19a6c22 | |||
7465338ea1 | |||
9dff05a394 | |||
9f5a5ad635 | |||
2dcd0511c4 | |||
dd1a309cb6 | |||
9563515e97 | |||
ba77c51ee0 | |||
2e83b95484 | |||
756374b2e4 | |||
527ff6fb1d | |||
fb4fc496da | |||
8d9bd87c22 | |||
36acb0a63d | |||
3e0f5aec0c | |||
4f5c3b4b74 | |||
a4bf54e465 | |||
d94606587b | |||
74ea9f9305 | |||
4dc04d8c53 | |||
6e298759a4 | |||
3b320de8d7 | |||
30d3c1fe72 | |||
7469a2626a | |||
d534597589 | |||
ec3c8464d3 | |||
6319f649c2 | |||
44d34aba19 | |||
4245c573df | |||
c27b6493d6 | |||
7200207009 | |||
9ba66fd800 | |||
e4552fca40 | |||
b7d892e4c6 | |||
5b096be68b | |||
e843d11566 | |||
9c7803030e | |||
67ef36ef8e | |||
4c1614f6a5 | |||
3766784799 | |||
56e16ef712 | |||
559c313fc7 | |||
5e10d56d89 | |||
d289ce6aca | |||
c68e69bd6e | |||
a6f312cfd3 | |||
ca51a8c926 | |||
ec95a1c2d3 | |||
a418558b73 | |||
f097304f3b | |||
ea4ea4a9b2 | |||
b94452ee42 | |||
51db34d223 | |||
059c330d95 | |||
557f9ceb97 | |||
4aae57c274 | |||
fb0ca1ba9d | |||
51723bb93b | |||
1e41f869de | |||
28517e4c34 | |||
619066780f | |||
1636e6c187 | |||
d17c94f9b9 | |||
4b47803162 | |||
15a3f39f65 | |||
f7d85e618c | |||
f00500d3d5 | |||
25a5da074c | |||
43d737c663 | |||
789e24b59a | |||
b51bcf3e2b | |||
babb13f603 | |||
21ef33df65 | |||
83b1cedb86 | |||
36ee36283a | |||
74eac21870 | |||
e330c5ea17 | |||
e6644b7feb | |||
47af454115 | |||
1f31e80c47 | |||
b0c7dac56b | |||
e5aa67421d | |||
fdd50f09dd | |||
26a074588b | |||
00cc32d95a | |||
df8f727bba | |||
de8084ed40 | |||
9fa88caded | |||
06d17e08c0 | |||
4830808d2f | |||
02ee6f69b3 | |||
5d0808e1c0 | |||
1f864fba7f | |||
cc83aee401 | |||
185ccecec1 | |||
f96193dc8c | |||
205c57d6af | |||
5c97d21889 | |||
e323593f4a | |||
3bae3fa203 | |||
9bd22dc033 | |||
5064d873bb | |||
4495f98dce | |||
5a75b44f71 | |||
ebd6f4bc8f | |||
687a87d3d0 | |||
464842ea36 | |||
91911da302 | |||
3c87d76741 | |||
ccafa53bd6 | |||
4e23f4cfc9 | |||
544a80fc6e | |||
4d52c10958 | |||
c23b9ee192 | |||
296e0c2054 | |||
5527fa2bc3 | |||
59532ab0c7 | |||
ad5a9d8f8b | |||
d243634602 | |||
e89d3c7b07 | |||
354112fb41 | |||
f7746ec3f6 | |||
03e0fe1e95 | |||
22c98e6240 | |||
90979faedd | |||
21858d928a | |||
be95ca553a | |||
c4b4248707 | |||
91353c6d60 | |||
31851cbc32 | |||
41f6e8ef86 | |||
85b4b97b7b | |||
2726fdb831 | |||
b1150eb147 | |||
898d76af53 | |||
7c26303b25 | |||
902956ca0d | |||
3429abff40 | |||
61b28c5c7d | |||
e84e842c1e | |||
0792f8d4a3 | |||
52ae75d4b8 | |||
224538c885 | |||
45dc34bfa2 | |||
0b801a0d2d | |||
d7f5fd5d24 | |||
026f014d32 | |||
a439a58f13 | |||
29ffa46d08 | |||
0a1aac862f | |||
f7fff83647 | |||
66e48da7cb | |||
93ea4b07c1 | |||
77c92d75d5 | |||
119516424d | |||
f3efbf432f | |||
04538c65b5 | |||
efcf8bae9d | |||
adfb419ceb | |||
09948ce033 | |||
ff6ee2c0c2 | |||
96cf9c739e | |||
9f4ccb83e3 | |||
978ab8a4dd | |||
2cc650e389 | |||
f24169735a | |||
75c875f073 | |||
6ea2822fa3 | |||
b4cf178cc5 | |||
a7c1ff3729 | |||
fdd9b85448 | |||
e12587619b | |||
8d9fc28872 | |||
2c5d520395 | |||
9e85d197fd | |||
2aea9c59a4 | |||
001af72727 | |||
9d594d7f26 | |||
2161e90cda | |||
f7a82d6400 | |||
10e30f7dc7 | |||
177edc5444 | |||
b45cd0a4eb | |||
8a56b990dd | |||
f353283a40 | |||
5d067ec718 | |||
1cb6fc004b | |||
3b603ef7e0 | |||
0971ba54b8 | |||
c136acc879 | |||
cc2d3fd56d | |||
72e6e7839f | |||
732573331a | |||
00407d6971 | |||
db630b2945 | |||
a15ee28177 | |||
92e9bc85a1 | |||
70c51beeeb | |||
9890887126 | |||
203ec385c5 | |||
5a0d8eca9f | |||
ae779c7f20 | |||
3852176e80 | |||
7a0ce6c57b | |||
15e862f974 | |||
a1908d9db1 | |||
8ee740e425 | |||
f44b3e0553 | |||
bddcb40237 | |||
66ea19fbfb | |||
e9966b4aff | |||
a71ae65f8b | |||
96a2747e0b | |||
8ef48ca33c | |||
8a0cebccdc | |||
5ae6239344 | |||
aaeb980688 | |||
77c325772a | |||
2eb0d20221 | |||
454ca09575 | |||
8f0bf5deae | |||
09d9d91297 | |||
a5e3227b64 | |||
8a790e1c38 | |||
db52e024e8 | |||
79c166c38d | |||
04fbaf4f27 | |||
b92263e80c | |||
12f78a08cd | |||
88c9a23866 | |||
94f92072c2 | |||
5ca4b41063 | |||
45c97862e5 | |||
3a7447dacc | |||
dc7b2b03e1 | |||
8b15724c2a | |||
587f04f807 | |||
9faf161aae | |||
3b56807e78 | |||
d5882c0cd3 | |||
c92268a615 | |||
e1fa61cd58 | |||
98c5f35324 | |||
3841e8da74 | |||
e3291aa5ba | |||
fab13dbb89 | |||
c0c79e59fc | |||
90b7d9a7fa | |||
662c995515 | |||
3c54893656 | |||
580794f3fb | |||
1154a1e8d7 | |||
837683004d | |||
14bb73220b | |||
f1a9ada5f0 |
13
.gitignore
vendored
@ -16,7 +16,17 @@ config.log
|
||||
config.status
|
||||
config
|
||||
configure
|
||||
data/gnome-shell.desktop
|
||||
data/gnome-shell.desktop.in
|
||||
intltool-extract.in
|
||||
intltool-merge.in
|
||||
intltool-update.in
|
||||
libtool
|
||||
omf.make
|
||||
po/*.gmo
|
||||
po/Makefile.in.in
|
||||
po/POTFILES
|
||||
po/stamp-it
|
||||
scripts/launcher.pyc
|
||||
src/*.gir
|
||||
src/*.typelib
|
||||
@ -28,4 +38,7 @@ src/gnomeshell-taskpanel
|
||||
src/gnome-shell
|
||||
src/test-recorder
|
||||
src/test-recorder.ogg
|
||||
src/test-theme
|
||||
stamp-h1
|
||||
tests/run-test.sh
|
||||
xmldocs.make
|
||||
|
17
Makefile.am
@ -1,13 +1,22 @@
|
||||
SUBDIRS = data js src
|
||||
SUBDIRS = data js src tests po
|
||||
|
||||
EXTRA_DIST = \
|
||||
.project \
|
||||
.settings
|
||||
.settings \
|
||||
autogen.sh
|
||||
|
||||
# These are files checked into Git that we don't want to distribute
|
||||
DIST_EXCLUDE = \
|
||||
.gitignore \
|
||||
gnome-shell.doap \
|
||||
MAINTAINERS \
|
||||
tools/build/*
|
||||
|
||||
distcheck-hook:
|
||||
@echo "Checking disted javascript against files in git"
|
||||
@echo "Checking disted files against files in git"
|
||||
@failed=false; \
|
||||
for f in `cd $(srcdir) && git-ls-files js` ; do \
|
||||
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 ; \
|
||||
|
20
README
@ -0,0 +1,20 @@
|
||||
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.
|
||||
|
||||
For more information about GNOME Shell, including instructions on how
|
||||
to build GNOME Shell from source and how to get involved with the project,
|
||||
see:
|
||||
|
||||
http://live.gnome.org/GnomeShell
|
||||
|
||||
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
|
||||
product.
|
||||
|
||||
License
|
||||
=======
|
||||
GNOME Shell is distributed under the terms of the GNU General Public License,
|
||||
version 2 or later. See the COPYING file for details.
|
||||
|
||||
|
28
autogen.sh
@ -1,8 +1,22 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
|
||||
(cd `dirname $0`;
|
||||
touch ChangeLog NEWS &&
|
||||
autoreconf --install --symlink &&
|
||||
autoreconf &&
|
||||
./configure --enable-maintainer-mode $@
|
||||
)
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="gnome-shell"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
|
||||
echo " top-level gnome-shell directory"
|
||||
exit 1
|
||||
}
|
||||
|
||||
which gnome-autogen.sh || {
|
||||
echo "You need to install gnome-common from GNOME Subversion (or from"
|
||||
echo "your OS vendor's package manager)."
|
||||
exit 1
|
||||
}
|
||||
USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh
|
||||
|
70
configure.ac
@ -1,10 +1,12 @@
|
||||
AC_INIT(gnome-shell, 0.0.1)
|
||||
AC_INIT(gnome-shell, 2.27.3)
|
||||
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip])
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
AC_DISABLE_STATIC
|
||||
@ -20,8 +22,16 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
||||
|
||||
PKG_PROG_PKG_CONFIG(0.16)
|
||||
|
||||
IT_PROG_INTLTOOL(0.26)
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
||||
AM_GCONF_SOURCE_2
|
||||
|
||||
# Get a value to substitute into gnome-shell.in
|
||||
AM_PATH_PYTHON([2.5])
|
||||
AC_SUBST(PYTHON)
|
||||
|
||||
# We need at least this, since gst_plugin_register_static() was added
|
||||
# in 0.10.16, but nothing older than 0.10.21 has been tested.
|
||||
GSTREAMER_MIN_VERSION=0.10.16
|
||||
@ -33,23 +43,25 @@ if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
build_recorder=true
|
||||
recorder_modules="gstreamer-0.10 gstreamer-base-0.10 xfixes"
|
||||
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-0.9)
|
||||
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 dbus-glib-1 mutter-plugins gjs-gi-1.0 xscrnsaver libgnome-menu $recorder_modules gconf-2.0 gdk-x11-2.0 clutter-x11-0.9 clutter-glx-0.9)
|
||||
PKG_CHECK_MODULES(TIDY, clutter-0.9)
|
||||
PKG_CHECK_MODULES(BIG, clutter-0.9 gtk+-2.0 librsvg-2.0)
|
||||
# Collect more than 20 libraries for a prize!
|
||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins
|
||||
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
|
||||
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
|
||||
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
||||
gobject-introspection-1.0 >= 0.6.5)
|
||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||
PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1)
|
||||
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(TOOLKIT, clutter-1.0 libcroco-0.6)
|
||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||
PKG_CHECK_MODULES(TASKPANEL, libwnck-1.0 dbus-glib-1)
|
||||
# We require libgnomeui for generating thumbnails for recent files with GnomeThumbnailFactory.
|
||||
# We'll switch to using GnomeDesktopThumbnailFactory once the branch of gnome-desktop that contains
|
||||
# it becomes stable.
|
||||
PKG_CHECK_MODULES(LIBGNOMEUI, libgnomeui-2.0)
|
||||
|
||||
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
|
||||
# FIXME: metacity-plugins.pc should point directly to its .gir file
|
||||
@ -80,17 +92,31 @@ AC_SUBST(GIRDIR)
|
||||
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
|
||||
AC_SUBST(TYPELIBDIR)
|
||||
|
||||
changequote(,)dnl
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
# Stay command-line compatible with the gnome-common configure option. Here
|
||||
# minimum/yes/maximum are the same, however.
|
||||
AC_ARG_ENABLE(compile_warnings,
|
||||
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
|
||||
[Turn on compiler warnings]),,
|
||||
enable_compile_warnings=error)
|
||||
|
||||
case " $OBJCFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) OBJCFLAGS="$OBJCFLAGS -Wall" ;;
|
||||
esac
|
||||
changequote(,)dnl
|
||||
if test "$enable_compile_warnings" != no ; then
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
if test "$enable_compile_warnings" = error ; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Werror[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Werror" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
@ -104,4 +130,6 @@ AC_OUTPUT([
|
||||
js/misc/Makefile
|
||||
js/ui/Makefile
|
||||
src/Makefile
|
||||
tests/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
|
@ -1,14 +1,48 @@
|
||||
imagedir = $(pkgdatadir)/images
|
||||
desktopdir=$(datadir)/applications
|
||||
desktop_DATA = gnome-shell.desktop
|
||||
|
||||
dist_image_DATA = \
|
||||
add-workspace.svg \
|
||||
# We substitute in bindir so it works as an autostart
|
||||
# file when built in a non-system prefix
|
||||
gnome-shell.desktop.in: gnome-shell.desktop.in.in
|
||||
$(AM_V_GEN) sed -e "s|@bindir[@]|$(bindir)|" \
|
||||
-e "s|@VERSION[@]|$(VERSION)|" \
|
||||
$< > $@ || rm $@
|
||||
|
||||
# Placeholder until we add intltool
|
||||
gnome-shell.desktop: gnome-shell.desktop.in
|
||||
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
||||
|
||||
imagesdir = $(pkgdatadir)/images
|
||||
dist_images_DATA = \
|
||||
add-workspace.svg \
|
||||
app-well-glow.png \
|
||||
back.svg \
|
||||
close.svg \
|
||||
close-black.svg \
|
||||
info.svg \
|
||||
magnifier.svg \
|
||||
remove-workspace.svg
|
||||
|
||||
themedir = $(pkgdatadir)/theme
|
||||
dist_theme_DATA = \
|
||||
theme/gnome-shell.css \
|
||||
theme/scroll-button-down.png \
|
||||
theme/scroll-button-down-hover.png \
|
||||
theme/scroll-button-up.png \
|
||||
theme/scroll-button-up-hover.png \
|
||||
theme/scroll-vhandle.png
|
||||
|
||||
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||
schema_DATA = gnome-shell.schemas
|
||||
|
||||
install-data-local:
|
||||
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(top_builddir)/data/$(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 \
|
||||
$(schema_DATA)
|
||||
|
||||
CLEANFILES = \
|
||||
gnome-shell.desktop.in \
|
||||
$(desktop_DATA)
|
||||
|
||||
|
BIN
data/app-well-glow.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
7
data/back.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?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="12" height="16" viewBox="0 0 12 16" enable-background="new 0 0 29 18" xml:space="preserve" sodipodi:version="0.32" inkscape:version="0.46+devel" sodipodi:docname="back.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata id="metadata16"><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="defs14"><inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 9 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="29 : 9 : 1" inkscape:persp3d-origin="14.5 : 6 : 1" id="perspective18"/></defs><sodipodi:namedview inkscape:window-height="728" inkscape:window-width="1103" 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="true" inkscape:zoom="27.260185" inkscape:cx="12.592456" inkscape:cy="8.2696842" inkscape:window-x="145" inkscape:window-y="38" inkscape:current-layer="Foreground" inkscape:snap-global="true" showguides="false"><inkscape:grid type="xygrid" id="grid2391" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true"/></sodipodi:namedview>
|
||||
|
||||
|
||||
|
||||
<path style="fill: rgb(255, 255, 255); fill-opacity: 1; stroke: none;" d="M 10,2 10,14 2,8 10,2 z" id="path43"/></svg>
|
After Width: | Height: | Size: 1.9 KiB |
66
data/close-black.svg
Normal file
@ -0,0 +1,66 @@
|
||||
<?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.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+devel"
|
||||
sodipodi:docname="close-black.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></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="811"
|
||||
inkscape:window-width="1272"
|
||||
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="10.440056"
|
||||
inkscape:window-x="40"
|
||||
inkscape:window-y="40"
|
||||
inkscape:current-layer="Foreground" />
|
||||
<path
|
||||
fill-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"
|
||||
id="path2394"
|
||||
style="fill-opacity:1;fill:#000000" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
74
data/close.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="x_circle_16.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" /></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" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3173"
|
||||
id="linearGradient3179"
|
||||
x1="7.844358"
|
||||
y1="16"
|
||||
x2="7.7198443"
|
||||
y2="-0.062256809"
|
||||
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
|
||||
inkscape:window-height="713"
|
||||
inkscape:window-width="1197"
|
||||
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"
|
||||
inkscape:window-x="40"
|
||||
inkscape:window-y="40"
|
||||
inkscape:current-layer="Foreground" />
|
||||
<path
|
||||
fill-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"
|
||||
id="path2394"
|
||||
style="fill-opacity:1;fill:url(#linearGradient3179)" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
15
data/gnome-shell.desktop.in.in
Normal file
@ -0,0 +1,15 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
_Name=GNOME Shell
|
||||
_Comment=Window management and application launching
|
||||
Exec=@bindir@/gnome-shell
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=gnome-shell
|
||||
X-GNOME-Bugzilla-Component=general
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
Categories=GNOME;GTK;Utility;Core;
|
||||
OnlyShowIn=GNOME;
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-Phase=WindowManager
|
||||
X-GNOME-Provides=panel;windowmanager;
|
||||
X-GNOME-Autostart-Notify=true
|
@ -1,6 +1,21 @@
|
||||
<gconfschemafile>
|
||||
<schemalist>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/development_tools</key>
|
||||
<applyto>/desktop/gnome/shell/development_tools</applyto>
|
||||
<owner>gnome-shell</owner>
|
||||
<type>bool</type>
|
||||
<default>true</default>
|
||||
<locale name="C">
|
||||
<short>Enable internal tools useful for developers and testers from Alt-F2</short>
|
||||
<long>
|
||||
Allows access to internal debugging and monitoring tools using
|
||||
the Alt-F2 dialog.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/app_monitor/enable_monitoring</key>
|
||||
<applyto>/desktop/gnome/shell/app_monitor/enable_monitoring</applyto>
|
||||
@ -15,6 +30,64 @@
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/favorite_apps</key>
|
||||
<applyto>/desktop/gnome/shell/favorite_apps</applyto>
|
||||
<owner>gnome-shell</owner>
|
||||
<type>list</type>
|
||||
<list_type>string</list_type>
|
||||
<default>[mozilla-firefox.desktop,evolution.desktop,openoffice.org-writer.desktop]</default>
|
||||
<locale name="C">
|
||||
<short>List of desktop file IDs for favorite applications</short>
|
||||
<long>
|
||||
The applications corresponding to these identifiers will be displayed in the favorites area.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/sidebar/visible</key>
|
||||
<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>
|
||||
<type>list</type>
|
||||
<list_type>string</list_type>
|
||||
<default>[imports.ui.widget.ClockWidget,imports.ui.widget.AppsWidget,imports.ui.widget.RecentDocsWidget]</default>
|
||||
<locale name="C">
|
||||
<short>The widgets to display in the sidebar</short>
|
||||
<long>
|
||||
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.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
</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 |
80
data/magnifier.svg
Normal file
@ -0,0 +1,80 @@
|
||||
<?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="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
enable-background="new 0 0 29 18"
|
||||
xml:space="preserve"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46+devel"
|
||||
sodipodi:docname="magnifier.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||
id="metadata16"><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="defs14"><inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 9 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="29 : 9 : 1"
|
||||
inkscape:persp3d-origin="14.5 : 6 : 1"
|
||||
id="perspective18" /></defs><sodipodi:namedview
|
||||
inkscape:window-height="728"
|
||||
inkscape:window-width="1103"
|
||||
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="true"
|
||||
inkscape:zoom="27.260185"
|
||||
inkscape:cx="9.5844061"
|
||||
inkscape:cy="9.4435574"
|
||||
inkscape:window-x="142"
|
||||
inkscape:window-y="26"
|
||||
inkscape:current-layer="Foreground"
|
||||
inkscape:snap-global="true"
|
||||
showguides="false"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2391"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" /></sodipodi:namedview>
|
||||
|
||||
<g
|
||||
id="g5"
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
transform="translate(-4,-0.023114)">
|
||||
<path
|
||||
d="m 6.246,13.98 c -0.319,-0.319 -0.319,-0.837 0,-1.157 L 9.963,9.106 c 0.319,-0.319 0.837,-0.319 1.157,0 l 0.786,0.787 c 0.32,0.319 0.32,0.837 0,1.157 l -3.717,3.717 c -0.32,0.319 -0.838,0.319 -1.157,0 l -0.786,-0.787 0,0 z"
|
||||
id="path7"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
<path
|
||||
d="M 9.076,11.937"
|
||||
id="path9"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="m 7.25,7.476886 c 0,-1.243 1.007,-2.25 2.2499998,-2.25 1.2430002,0 2.2500002,1.007 2.2500002,2.25 0,1.243 -1.007,2.25 -2.2500002,2.25 C 8.257,9.726886 7.25,8.719886 7.25,7.476886 z m -2.25,0 c 0,-2.485 2.015,-4.5 4.4999998,-4.5 2.4850002,0 4.5000002,2.015 4.5000002,4.5 0,2.4849998 -2.015,4.5 -4.5000002,4.5 C 7.015,11.976886 5,9.9618858 5,7.476886 z"
|
||||
id="path11"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
97
data/theme/gnome-shell.css
Normal file
@ -0,0 +1,97 @@
|
||||
/* Copyright 2009, Red Hat, Inc.
|
||||
*
|
||||
* Portions adapted from NBTK's data/style/default.css
|
||||
* Copyright 2009 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
NbtkScrollBar
|
||||
{
|
||||
background-color: #354761;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
NbtkScrollView
|
||||
{
|
||||
scrollbar-width: 16px;
|
||||
scrollbar-height: 16px;
|
||||
}
|
||||
|
||||
NbtkButton#up-stepper
|
||||
{
|
||||
border-image: url("scroll-button-up.png") 5;
|
||||
}
|
||||
|
||||
NbtkButton#up-stepper:hover,
|
||||
NbtkButton#up-stepper:active
|
||||
{
|
||||
border-image: url("scroll-button-up-hover.png") 5;
|
||||
}
|
||||
|
||||
NbtkButton#down-stepper
|
||||
{
|
||||
border-image: url("scroll-button-down.png") 5;
|
||||
}
|
||||
|
||||
NbtkButton#down-stepper:hover,
|
||||
NbtkButton#down-stepper:active
|
||||
{
|
||||
border-image: url("scroll-button-down-hover.png") 5;
|
||||
}
|
||||
|
||||
NbtkScrollBar NbtkButton#vhandle
|
||||
{
|
||||
border-image: url("scroll-vhandle.png") 5;
|
||||
}
|
||||
|
||||
NbtkScrollBar NbtkButton#vhandle:hover
|
||||
{
|
||||
border-image: url("scroll-vhandle.png") 5;
|
||||
}
|
||||
|
||||
/* LookingGlass */
|
||||
|
||||
#LookingGlassDialog
|
||||
{
|
||||
background-color: rgba(0,0,0,0.85);
|
||||
spacing: 4px;
|
||||
padding: 4px;
|
||||
border: 1px solid rgba(0,0,172,0.85);
|
||||
border-radius: 4px;
|
||||
|
||||
color: #88ff66;
|
||||
}
|
||||
|
||||
#LookingGlassDialog > #Toolbar
|
||||
{
|
||||
border: 1px solid grey;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#LookingGlassDialog NbtkLabel
|
||||
{
|
||||
color: #88ff66;
|
||||
}
|
||||
|
||||
#LookingGlassDialog NbtkEntry
|
||||
{
|
||||
color: #88ff66;
|
||||
}
|
||||
|
||||
#LookingGlassDialog NbtkBoxLayout#EvalBox
|
||||
{
|
||||
padding: 4px;
|
||||
spacing: 4px;
|
||||
}
|
BIN
data/theme/scroll-button-down-hover.png
Normal file
After Width: | Height: | Size: 225 B |
BIN
data/theme/scroll-button-down.png
Normal file
After Width: | Height: | Size: 225 B |
BIN
data/theme/scroll-button-up-hover.png
Normal file
After Width: | Height: | Size: 211 B |
BIN
data/theme/scroll-button-up.png
Normal file
After Width: | Height: | Size: 211 B |
BIN
data/theme/scroll-vhandle.png
Normal file
After Width: | Height: | Size: 323 B |
53
gnome-shell.doap
Normal file
@ -0,0 +1,53 @@
|
||||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||
xmlns="http://usefulinc.com/ns/doap#">
|
||||
|
||||
<name xml:lang="en">GNOME Shell</name>
|
||||
<shortdesc xml:lang="en">Next generation GNOME desktop shell</shortdesc>
|
||||
<!--
|
||||
<homepage rdf:resource="http://live.gnome.org/GnomeShell" />
|
||||
-->
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>William Jon McCann</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
|
||||
<gnome:userid>mccann</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Owen Taylor</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
|
||||
<gnome:userid>otaylor</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Colin Walters</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
|
||||
<gnome:userid>cwalters</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Dan Winship</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:danw@gnome.org" />
|
||||
<gnome:userid>danw</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Marina Zhurakhinskaya</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
|
||||
<gnome:userid>marinaz</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
</Project>
|
@ -1,5 +1,4 @@
|
||||
jsmiscdir = $(pkgdatadir)/js/misc
|
||||
|
||||
dist_jsmisc_DATA = \
|
||||
appInfo.js \
|
||||
docInfo.js
|
||||
|
@ -1,135 +0,0 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
// TODO - move this into GConf once we're not a plugin anymore
|
||||
// but have taken over metacity
|
||||
// This list is taken from GNOME Online popular applications
|
||||
// http://online.gnome.org/applications
|
||||
// but with nautilus removed (since it should already be running)
|
||||
// and evince, totem, and gnome-file-roller removed (since they're
|
||||
// usually started by opening documents, not by opening the app
|
||||
// directly)
|
||||
const DEFAULT_APPLICATIONS = [
|
||||
'mozilla-firefox.desktop',
|
||||
'gnome-terminal.desktop',
|
||||
'evolution.desktop',
|
||||
'gedit.desktop',
|
||||
'mozilla-thunderbird.desktop',
|
||||
'rhythmbox.desktop',
|
||||
'epiphany.desktop',
|
||||
'xchat.desktop',
|
||||
'openoffice.org-1.9-writer.desktop',
|
||||
'emacs.desktop',
|
||||
'gnome-system-monitor.desktop',
|
||||
'openoffice.org-1.9-calc.desktop',
|
||||
'eclipse.desktop',
|
||||
'openoffice.org-1.9-impress.desktop',
|
||||
'vncviewer.desktop'
|
||||
];
|
||||
|
||||
function AppInfo(appId) {
|
||||
this._init(appId);
|
||||
}
|
||||
|
||||
AppInfo.prototype = {
|
||||
_init : function(appId) {
|
||||
this.appId = appId;
|
||||
this._gAppInfo = Gio.DesktopAppInfo.new(appId);
|
||||
if (!this._gAppInfo)
|
||||
throw new Error('Unknown appId ' + appId);
|
||||
|
||||
this.id = this._gAppInfo.get_id();
|
||||
this.name = this._gAppInfo.get_name();
|
||||
this.description = this._gAppInfo.get_description();
|
||||
this.executable = this._gAppInfo.get_executable();
|
||||
|
||||
this._gicon = this._gAppInfo.get_icon();
|
||||
},
|
||||
|
||||
getIcon : function(size) {
|
||||
if (this._gicon)
|
||||
return Shell.TextureCache.get_default().load_gicon(this._gicon, size);
|
||||
else
|
||||
return new Clutter.Texture({ width: size, height: size });
|
||||
},
|
||||
|
||||
getIconPath : function(size) {
|
||||
if (this._gicon) {
|
||||
let iconTheme = Gtk.IconTheme.get_default();
|
||||
let previewIconInfo = iconTheme.lookup_by_gicon(this._gicon, size, 0);
|
||||
if (previewIconInfo)
|
||||
return previewIconInfo.get_filename();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
launch : function() {
|
||||
this._gAppInfo.launch([], Main.createAppLaunchContext());
|
||||
}
|
||||
};
|
||||
|
||||
var _infos = {};
|
||||
|
||||
// getAppInfo:
|
||||
// @appId: an appId
|
||||
//
|
||||
// Gets an #AppInfo for @appId. This is preferable to calling
|
||||
// new AppInfo() directly, because it caches #AppInfos.
|
||||
//
|
||||
// Return value: the new or cached #AppInfo, or %null if @appId
|
||||
// doesn't point to a valid .desktop file
|
||||
function getAppInfo(appId) {
|
||||
let info = _infos[appId];
|
||||
if (info === undefined) {
|
||||
try {
|
||||
info = _infos[appId] = new AppInfo(appId);
|
||||
} catch (e) {
|
||||
info = _infos[appId] = null;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
// getMostUsedApps:
|
||||
// @count: maximum number of apps to retrieve
|
||||
//
|
||||
// Gets a list of #AppInfos for the @count most-frequently-used
|
||||
// applications
|
||||
//
|
||||
// Return value: the list of #AppInfo
|
||||
function getMostUsedApps(count) {
|
||||
let appMonitor = Shell.AppMonitor.get_default();
|
||||
|
||||
// Ask for more apps than we need, since the list of recently used
|
||||
// apps might contain an app we don't have a desktop file for
|
||||
let apps = appMonitor.get_most_used_apps (0, Math.round(count * 1.5));
|
||||
let matches = [], alreadyAdded = {};
|
||||
|
||||
for (let i = 0; i < apps.length && matches.length <= count; i++) {
|
||||
let appId = apps[i] + ".desktop";
|
||||
let appInfo = getAppInfo(appId);
|
||||
if (appInfo) {
|
||||
matches.push(appInfo);
|
||||
alreadyAdded[appId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the list with default applications it's not full yet
|
||||
for (let i = 0; i < DEFAULT_APPLICATIONS.length && matches.length <= count; i++) {
|
||||
let appId = DEFAULT_APPLICATIONS[i];
|
||||
if (alreadyAdded[appId])
|
||||
continue;
|
||||
|
||||
let appInfo = getAppInfo(appId);
|
||||
if (appInfo)
|
||||
matches.push(appInfo);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
@ -5,6 +5,8 @@ const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const THUMBNAIL_ICON_MARGIN = 2;
|
||||
@ -16,40 +18,17 @@ function DocInfo(recentInfo) {
|
||||
DocInfo.prototype = {
|
||||
_init : function(recentInfo) {
|
||||
this._recentInfo = recentInfo;
|
||||
// We actually used get_modified() instead of get_visited()
|
||||
// here, as GtkRecentInfo doesn't updated get_visited()
|
||||
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
|
||||
this.timestamp = recentInfo.get_modified().getTime() / 1000;
|
||||
this.name = recentInfo.get_display_name();
|
||||
this.uri = recentInfo.get_uri();
|
||||
this.mimeType = recentInfo.get_mime_type();
|
||||
},
|
||||
|
||||
getIcon : function(size) {
|
||||
let icon = new Clutter.Texture();
|
||||
let iconPixbuf;
|
||||
|
||||
if (this.uri.match("^file://"))
|
||||
iconPixbuf = Shell.get_thumbnail(this.uri, this.mimeType);
|
||||
|
||||
if (iconPixbuf) {
|
||||
// We calculate the width and height of the texture so as
|
||||
// to preserve the aspect ratio of the thumbnail. Because
|
||||
// the images generated based on thumbnails don't have an
|
||||
// internal padding like system icons do, we create a
|
||||
// slightly smaller texture and then create a group around
|
||||
// it for padding purposes
|
||||
|
||||
let scalingFactor = (size - THUMBNAIL_ICON_MARGIN * 2) / Math.max(iconPixbuf.get_width(), iconPixbuf.get_height());
|
||||
icon.set_width(Math.ceil(iconPixbuf.get_width() * scalingFactor));
|
||||
icon.set_height(Math.ceil(iconPixbuf.get_height() * scalingFactor));
|
||||
Shell.clutter_texture_set_from_pixbuf(icon, iconPixbuf);
|
||||
|
||||
let group = new Clutter.Group({ width: size,
|
||||
height: size });
|
||||
group.add_actor(icon);
|
||||
icon.set_position(THUMBNAIL_ICON_MARGIN, THUMBNAIL_ICON_MARGIN);
|
||||
return group;
|
||||
} else {
|
||||
Shell.clutter_texture_set_from_pixbuf(icon, this._recentInfo.get_icon(size));
|
||||
return icon;
|
||||
}
|
||||
createIcon : function(size) {
|
||||
return Shell.TextureCache.get_default().load_recent_thumbnail(size, this._recentInfo);
|
||||
},
|
||||
|
||||
launch : function() {
|
||||
@ -63,7 +42,7 @@ DocInfo.prototype = {
|
||||
if (appInfo != null) {
|
||||
appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
|
||||
} else {
|
||||
log("Failed to get default application info for mime type " + mimeType +
|
||||
log("Failed to get default application info for mime type " + this.mimeType +
|
||||
". Will try to use the last application that registered the document.");
|
||||
let appName = this._recentInfo.last_application();
|
||||
let [success, appExec, count, time] = this._recentInfo.get_application_info(appName);
|
||||
@ -101,14 +80,62 @@ DocInfo.prototype = {
|
||||
|
||||
exists : function() {
|
||||
return this._recentInfo.exists();
|
||||
},
|
||||
|
||||
lastVisited : function() {
|
||||
// We actually used get_modified() instead of get_visited()
|
||||
// here, as GtkRecentInfo doesn't updated get_visited()
|
||||
// correctly. See
|
||||
// http://bugzilla.gnome.org/show_bug.cgi?id=567094
|
||||
|
||||
return this._recentInfo.get_modified();
|
||||
}
|
||||
};
|
||||
|
||||
var docManagerInstance = null;
|
||||
|
||||
function getDocManager() {
|
||||
if (docManagerInstance == null)
|
||||
docManagerInstance = new DocManager();
|
||||
return docManagerInstance;
|
||||
}
|
||||
|
||||
function DocManager() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DocManager.prototype = {
|
||||
_init: function() {
|
||||
this._recentManager = Gtk.RecentManager.get_default();
|
||||
this._items = {};
|
||||
this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
|
||||
this._reload();
|
||||
this.emit('changed');
|
||||
}));
|
||||
this._reload();
|
||||
},
|
||||
|
||||
_reload: function() {
|
||||
let docs = this._recentManager.get_items();
|
||||
let newItems = {};
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
let recentInfo = docs[i];
|
||||
if (!recentInfo.exists())
|
||||
continue;
|
||||
|
||||
let docInfo = new DocInfo(recentInfo);
|
||||
|
||||
// we use GtkRecentInfo URI as an item Id
|
||||
newItems[docInfo.uri] = docInfo;
|
||||
}
|
||||
let deleted = {};
|
||||
for (var uri in this._items) {
|
||||
if (!(uri in newItems))
|
||||
deleted[uri] = this._items[uri];
|
||||
}
|
||||
/* 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);
|
||||
|
@ -3,15 +3,20 @@ jsuidir = $(pkgdatadir)/js/ui
|
||||
dist_jsui_DATA = \
|
||||
altTab.js \
|
||||
appDisplay.js \
|
||||
appIcon.js \
|
||||
button.js \
|
||||
chrome.js \
|
||||
dash.js \
|
||||
dnd.js \
|
||||
docDisplay.js \
|
||||
environment.js \
|
||||
genericDisplay.js \
|
||||
link.js \
|
||||
lookingGlass.js \
|
||||
main.js \
|
||||
overlay.js \
|
||||
overview.js \
|
||||
panel.js \
|
||||
places.js \
|
||||
runDialog.js \
|
||||
sidebar.js \
|
||||
tweener.js \
|
||||
|
@ -36,38 +36,34 @@ function AltTabPopup() {
|
||||
|
||||
AltTabPopup.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
|
||||
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
|
||||
corner_radius: POPUP_GRID_SPACING,
|
||||
padding: POPUP_GRID_SPACING,
|
||||
spacing: POPUP_GRID_SPACING,
|
||||
orientation: Big.BoxOrientation.VERTICAL });
|
||||
|
||||
// Icon grid. It would be nice to use Tidy.Grid for the this,
|
||||
// but Tidy.Grid is lame in various ways. (Eg, it seems to
|
||||
// have a minimum size of 200x200.) So we create a vertical
|
||||
// Big.Box containing multiple horizontal Big.Boxes.
|
||||
this._grid = new Big.Box({ spacing: POPUP_GRID_SPACING,
|
||||
// Icon grid. TODO: Investigate Nbtk.Grid once that lands. Currently
|
||||
// just implemented using a chain of Big.Box.
|
||||
this._grid = new Big.Box({ spacing: POPUP_GRID_SPACING,
|
||||
orientation: Big.BoxOrientation.VERTICAL });
|
||||
let gcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
x_align: Big.BoxAlignment.CENTER });
|
||||
gcenterbox.append(this._grid, Big.BoxPackFlags.NONE);
|
||||
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
|
||||
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
|
||||
|
||||
// Selected-window label
|
||||
this._label = new Clutter.Text({ font_name: "Sans 16px",
|
||||
this._label = new Clutter.Text({ font_name: "Sans 16px",
|
||||
ellipsize: Pango.EllipsizeMode.END });
|
||||
|
||||
let labelbox = new Big.Box({ background_color: POPUP_INDICATOR_COLOR,
|
||||
corner_radius: POPUP_GRID_SPACING / 2,
|
||||
padding: POPUP_GRID_SPACING / 2 });
|
||||
labelbox.append(this._label, Big.BoxPackFlags.EXPAND);
|
||||
labelbox.append(this._label, Big.BoxPackFlags.NONE);
|
||||
let lcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
width: POPUP_LABEL_MAX_WIDTH + POPUP_GRID_SPACING });
|
||||
lcenterbox.append(labelbox, Big.BoxPackFlags.NONE);
|
||||
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
|
||||
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
|
||||
|
||||
// Indicator around selected icon
|
||||
this._indicator = new Big.Rectangle({ border_width: POPUP_INDICATOR_WIDTH,
|
||||
@ -76,10 +72,10 @@ AltTabPopup.prototype = {
|
||||
color: POPUP_TRANSPARENT });
|
||||
this.actor.append(this._indicator, Big.BoxPackFlags.FIXED);
|
||||
|
||||
this._items = [];
|
||||
this._items = [];
|
||||
this._toplevels = global.window_group.get_children();
|
||||
|
||||
global.stage.add_actor(this.actor);
|
||||
global.stage.add_actor(this.actor);
|
||||
|
||||
// Dark translucent window used to cover all but the
|
||||
// currently-selected window while Alt-Tabbing. Actually
|
||||
@ -142,10 +138,6 @@ AltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
show : function(initialSelection) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
Main.startModal();
|
||||
|
||||
global.window_group.add_actor(this._overlay);
|
||||
this._overlay.raise_top();
|
||||
this._overlay.show();
|
||||
@ -154,18 +146,16 @@ AltTabPopup.prototype = {
|
||||
time: SHOW_TIME,
|
||||
transition: "easeOutQuad" });
|
||||
|
||||
this.actor.show_all();
|
||||
this.actor.x = (global.screen_width - this.actor.width) / 2;
|
||||
this.actor.y = (global.screen_height - this.actor.height) / 2;
|
||||
this.actor.show_all();
|
||||
this.actor.x = Math.floor((global.screen_width - this.actor.width) / 2);
|
||||
this.actor.y = Math.floor((global.screen_height - this.actor.height) / 2);
|
||||
|
||||
this.select(initialSelection);
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this.actor.destroy();
|
||||
this.actor.destroy();
|
||||
this._overlay.destroy();
|
||||
|
||||
Main.endModal();
|
||||
},
|
||||
|
||||
select : function(n) {
|
||||
@ -240,8 +230,6 @@ AltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
_adjust_overlay : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
if (this._selected && this._selected.icon_rect) {
|
||||
// We want to highlight a specific rectangle within the
|
||||
// task bar, so rearrange the pieces of the overlay to
|
||||
|
1067
js/ui/appDisplay.js
133
js/ui/appIcon.js
Normal file
@ -0,0 +1,133 @@
|
||||
/* -*- 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 Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const GLOW_COLOR = new Clutter.Color();
|
||||
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
||||
const GLOW_PADDING_HORIZONTAL = 3;
|
||||
const GLOW_PADDING_VERTICAL = 3;
|
||||
|
||||
const APP_ICON_SIZE = 48;
|
||||
|
||||
function AppIcon(appInfo) {
|
||||
this._init(appInfo);
|
||||
}
|
||||
|
||||
AppIcon.prototype = {
|
||||
_init : function(appInfo) {
|
||||
this.appInfo = appInfo;
|
||||
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 = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
corner_radius: 2,
|
||||
padding: 1,
|
||||
reactive: true });
|
||||
|
||||
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this.icon = appInfo.create_icon_texture(APP_ICON_SIZE);
|
||||
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
||||
|
||||
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 timeA = a.get_user_time();
|
||||
let timeB = b.get_user_time();
|
||||
if (timeA == timeB)
|
||||
return 0;
|
||||
else if (timeA > timeB)
|
||||
return -1;
|
||||
return 1;
|
||||
});
|
||||
},
|
||||
|
||||
getDragActor: function() {
|
||||
return this.appInfo.create_icon_texture(APP_ICON_SIZE);
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this.icon;
|
||||
}
|
||||
};
|
211
js/ui/button.js
@ -2,6 +2,11 @@
|
||||
|
||||
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);
|
||||
@ -9,14 +14,20 @@ DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
|
||||
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
|
||||
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaa66);
|
||||
|
||||
function Button(widget, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
|
||||
this._init(widget, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight);
|
||||
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, staysPressed, minWidth, minHeight) {
|
||||
let me = this;
|
||||
|
||||
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
|
||||
this._buttonColor = buttonColor
|
||||
if (buttonColor == null)
|
||||
this._buttonColor = DEFAULT_BUTTON_COLOR;
|
||||
@ -25,90 +36,138 @@ Button.prototype = {
|
||||
if (pressedButtonColor == null)
|
||||
this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
|
||||
|
||||
this._staysPressed = staysPressed
|
||||
if (staysPressed == null)
|
||||
this._staysPressed = false;
|
||||
this._textColor = textColor;
|
||||
if (textColor == null)
|
||||
this._textColor = DEFAULT_TEXT_COLOR;
|
||||
|
||||
if (minWidth == null)
|
||||
minWidth = 0;
|
||||
if (minHeight == null)
|
||||
minHeight = 0;
|
||||
this._font = font;
|
||||
if (font == null)
|
||||
this._font = DEFAULT_FONT;
|
||||
|
||||
// if this._staysPressed is true, this._active will be true past the first release of a button, until a subsequent one (the button
|
||||
// is unpressed) or until release() is called explicitly
|
||||
this._active = false;
|
||||
this._isBetweenPressAndRelease = false;
|
||||
this._mouseIsOverButton = false;
|
||||
|
||||
this.button = new Big.Box({ reactive: true,
|
||||
corner_radius: 5,
|
||||
padding_left: 4,
|
||||
padding_right: 4,
|
||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER
|
||||
});
|
||||
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: "Sans Bold 16px",
|
||||
this._widget = new Clutter.Text({ font_name: this._font,
|
||||
color: this._textColor,
|
||||
text: widgetOrText });
|
||||
} else {
|
||||
this._widget = widgetOrText;
|
||||
}
|
||||
|
||||
this.button.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._minWidth = minWidth;
|
||||
this._minHeight = minHeight;
|
||||
|
||||
this.button.connect('button-press-event',
|
||||
function(o, event) {
|
||||
me._isBetweenPressAndRelease = true;
|
||||
me.button.backgroundColor = me._pressedButtonColor;
|
||||
return false;
|
||||
});
|
||||
this.button.connect('button-release-event',
|
||||
function(o, event) {
|
||||
me._isBetweenPressAndRelease = false;
|
||||
if (!me._staysPressed || me._active) {
|
||||
me.release();
|
||||
} else {
|
||||
me._active = true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.button.connect('enter-event',
|
||||
function(o, event) {
|
||||
me._mouseIsOverButton = true;
|
||||
if (!me._active) {
|
||||
me.button.backgroundColor = me._buttonColor;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.button.connect('leave-event',
|
||||
function(o, event) {
|
||||
me._isBetweenPressAndRelease = false;
|
||||
me._mouseIsOverButton = false;
|
||||
if (!me._active) {
|
||||
me.button.backgroundColor = null;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
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));
|
||||
},
|
||||
|
||||
pressIn : function() {
|
||||
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
||||
this._active = true;
|
||||
this.button.backgroundColor = this._pressedButtonColor;
|
||||
}
|
||||
},
|
||||
|
||||
release : function() {
|
||||
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
||||
this._active = false;
|
||||
if (this._mouseIsOverButton) {
|
||||
this.button.backgroundColor = this._buttonColor;
|
||||
} else {
|
||||
this.button.backgroundColor = null;
|
||||
}
|
||||
}
|
||||
_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" });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9,7 +9,7 @@ const Shell = imports.gi.Shell;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
// This manages the shell "chrome"; the UI that's visible in the
|
||||
// normal mode (ie, outside the overlay), that surrounds the main
|
||||
// normal mode (ie, outside the Overview), that surrounds the main
|
||||
// workspace content.
|
||||
|
||||
function Chrome() {
|
||||
@ -18,13 +18,11 @@ function Chrome() {
|
||||
|
||||
Chrome.prototype = {
|
||||
_init: function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// The group itself has zero size so it doesn't interfere with DND
|
||||
this.actor = new Clutter.Group({ width: 0, height: 0 });
|
||||
global.stage.add_actor(this.actor);
|
||||
this.nonOverlayActor = new Clutter.Group();
|
||||
this.actor.add_actor(this.nonOverlayActor);
|
||||
this.nonOverviewActor = new Clutter.Group();
|
||||
this.actor.add_actor(this.nonOverviewActor);
|
||||
|
||||
this._obscuredByFullscreen = false;
|
||||
|
||||
@ -37,10 +35,10 @@ Chrome.prototype = {
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
Lang.bind(this, this._queueUpdateRegions));
|
||||
|
||||
Main.overlay.connect('showing',
|
||||
Lang.bind(this, this._overlayShowing));
|
||||
Main.overlay.connect('hidden',
|
||||
Lang.bind(this, this._overlayHidden));
|
||||
Main.overview.connect('showing',
|
||||
Lang.bind(this, this._overviewShowing));
|
||||
Main.overview.connect('hidden',
|
||||
Lang.bind(this, this._overviewHidden));
|
||||
|
||||
this._queueUpdateRegions();
|
||||
},
|
||||
@ -78,27 +76,27 @@ Chrome.prototype = {
|
||||
else if (shapeActor && !this._verifyAncestry(shapeActor, actor))
|
||||
throw new Error('shapeActor is not a descendent of actor');
|
||||
|
||||
this.nonOverlayActor.add_actor(actor);
|
||||
this.nonOverviewActor.add_actor(actor);
|
||||
|
||||
if (shapeActor)
|
||||
this._trackActor(shapeActor, true, true);
|
||||
},
|
||||
|
||||
// setVisibleInOverlay:
|
||||
// setVisibleInOverview:
|
||||
// @actor: an actor in the chrome layer
|
||||
// @visible: overlay visibility
|
||||
// @visible: Overview visibility
|
||||
//
|
||||
// By default, actors in the chrome layer are automatically hidden
|
||||
// when the overlay is shown. This can be used to override that
|
||||
// when the Overview is shown. This can be used to override that
|
||||
// behavior
|
||||
setVisibleInOverlay: function(actor, visible) {
|
||||
setVisibleInOverview: function(actor, visible) {
|
||||
if (!this._verifyAncestry(actor, this.actor))
|
||||
throw new Error('actor is not a descendent of the chrome layer');
|
||||
|
||||
if (visible)
|
||||
actor.reparent(this.actor);
|
||||
else
|
||||
actor.reparent(this.nonOverlayActor);
|
||||
actor.reparent(this.nonOverviewActor);
|
||||
},
|
||||
|
||||
// addInputRegionActor:
|
||||
@ -126,9 +124,11 @@ Chrome.prototype = {
|
||||
//
|
||||
// Removes @actor from the chrome layer
|
||||
removeActor: function(actor) {
|
||||
this.actor.remove_actor(actor);
|
||||
// We don't have to do anything else; the parent-set handlers
|
||||
// will do the rest.
|
||||
if (actor.get_parent() == this.nonOverviewActor)
|
||||
this.nonOverviewActor.remove_actor(actor);
|
||||
else
|
||||
this.actor.remove_actor(actor);
|
||||
this._untrackActor(actor, true, true);
|
||||
},
|
||||
|
||||
_findActor: function(actor) {
|
||||
@ -170,7 +170,7 @@ Chrome.prototype = {
|
||||
this._trackedActors.push(actorData);
|
||||
|
||||
actor = actor.get_parent();
|
||||
if (actor != this.actor)
|
||||
if (actor != this.actor && actor != this.nonOverviewActor)
|
||||
this._trackActor(actor, false, false);
|
||||
|
||||
if (inputRegion || strut)
|
||||
@ -198,7 +198,7 @@ Chrome.prototype = {
|
||||
actor.disconnect(actorData.parentSetId);
|
||||
|
||||
actor = actor.get_parent();
|
||||
if (actor && actor != this.actor)
|
||||
if (actor && actor != this.actor && actor != this.nonOverviewActor)
|
||||
this._untrackActor(actor, false, false);
|
||||
}
|
||||
|
||||
@ -209,33 +209,33 @@ Chrome.prototype = {
|
||||
_actorReparented: function(actor, oldParent) {
|
||||
if (this._verifyAncestry(actor, this.actor)) {
|
||||
let newParent = actor.get_parent();
|
||||
if (newParent != this.actor)
|
||||
if (newParent != this.actor && newParent != this.nonOverviewActor)
|
||||
this._trackActor(newParent, false, false);
|
||||
}
|
||||
if (oldParent != this.actor)
|
||||
if (oldParent != this.actor && oldParent != this.nonOverviewActor)
|
||||
this._untrackActor(oldParent, false, false);
|
||||
},
|
||||
|
||||
_overlayShowing: function() {
|
||||
_overviewShowing: function() {
|
||||
this.actor.show();
|
||||
this.nonOverlayActor.hide();
|
||||
this.nonOverviewActor.hide();
|
||||
this._queueUpdateRegions();
|
||||
},
|
||||
|
||||
_overlayHidden: function() {
|
||||
_overviewHidden: function() {
|
||||
if (this._obscuredByFullscreen)
|
||||
this.actor.hide();
|
||||
this.nonOverlayActor.show();
|
||||
this.nonOverviewActor.show();
|
||||
this._queueUpdateRegions();
|
||||
},
|
||||
|
||||
_queueUpdateRegions: function() {
|
||||
if (!this._updateRegionIdle)
|
||||
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions));
|
||||
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions),
|
||||
Meta.PRIORITY_BEFORE_REDRAW);
|
||||
},
|
||||
|
||||
_windowsRestacked: function() {
|
||||
let global = Shell.Global.get();
|
||||
let windows = global.get_windows();
|
||||
|
||||
// The chrome layer should be visible unless there is a window
|
||||
@ -269,7 +269,7 @@ Chrome.prototype = {
|
||||
break;
|
||||
}
|
||||
|
||||
let shouldBeVisible = !this._obscuredByFullscreen || Main.overlay.visible;
|
||||
let shouldBeVisible = !this._obscuredByFullscreen || Main.overview.visible;
|
||||
if (this.actor.visible != shouldBeVisible) {
|
||||
this.actor.visible = shouldBeVisible;
|
||||
this._queueUpdateRegions();
|
||||
@ -277,7 +277,6 @@ Chrome.prototype = {
|
||||
},
|
||||
|
||||
_updateRegions: function() {
|
||||
let global = Shell.Global.get();
|
||||
let rects = [], struts = [], i;
|
||||
|
||||
delete this._updateRegionIdle;
|
||||
|
963
js/ui/dash.js
Normal file
@ -0,0 +1,963 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Big = imports.gi.Big;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const DocDisplay = imports.ui.docDisplay;
|
||||
const Places = imports.ui.places;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Button = imports.ui.button;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const DEFAULT_PADDING = 4;
|
||||
const DEFAULT_SPACING = 4;
|
||||
const DASH_SECTION_PADDING = 6;
|
||||
const DASH_SECTION_SPACING = 40;
|
||||
const DASH_CORNER_RADIUS = 5;
|
||||
const DASH_PADDING_SIDE = 14;
|
||||
|
||||
const BACKGROUND_COLOR = new Clutter.Color();
|
||||
BACKGROUND_COLOR.from_pixel(0x000000c0);
|
||||
|
||||
const PRELIGHT_COLOR = new Clutter.Color();
|
||||
PRELIGHT_COLOR.from_pixel(0x4f6fadaa);
|
||||
|
||||
const TEXT_COLOR = new Clutter.Color();
|
||||
TEXT_COLOR.from_pixel(0x5f5f5fff);
|
||||
const BRIGHTER_TEXT_COLOR = new Clutter.Color();
|
||||
BRIGHTER_TEXT_COLOR.from_pixel(0xbbbbbbff);
|
||||
const BRIGHT_TEXT_COLOR = new Clutter.Color();
|
||||
BRIGHT_TEXT_COLOR.from_pixel(0xffffffff);
|
||||
const SEARCH_TEXT_COLOR = new Clutter.Color();
|
||||
SEARCH_TEXT_COLOR.from_pixel(0x333333ff);
|
||||
|
||||
const SEARCH_CURSOR_COLOR = BRIGHT_TEXT_COLOR;
|
||||
const HIGHLIGHTED_SEARCH_CURSOR_COLOR = SEARCH_TEXT_COLOR;
|
||||
|
||||
const HIGHLIGHTED_SEARCH_BACKGROUND_COLOR = new Clutter.Color();
|
||||
HIGHLIGHTED_SEARCH_BACKGROUND_COLOR.from_pixel(0xc4c4c4ff);
|
||||
|
||||
const SEARCH_BORDER_BOTTOM_COLOR = new Clutter.Color();
|
||||
SEARCH_BORDER_BOTTOM_COLOR.from_pixel(0x191919ff);
|
||||
|
||||
const SECTION_BORDER_COLOR = new Clutter.Color();
|
||||
SECTION_BORDER_COLOR.from_pixel(0x262626ff);
|
||||
const SECTION_BORDER = 1;
|
||||
const SECTION_INNER_BORDER_COLOR = new Clutter.Color();
|
||||
SECTION_INNER_BORDER_COLOR.from_pixel(0x000000ff);
|
||||
const SECTION_BACKGROUND_TOP_COLOR = new Clutter.Color();
|
||||
SECTION_BACKGROUND_TOP_COLOR.from_pixel(0x161616ff);
|
||||
const SECTION_BACKGROUND_BOTTOM_COLOR = new Clutter.Color();
|
||||
SECTION_BACKGROUND_BOTTOM_COLOR.from_pixel(0x000000ff);
|
||||
const SECTION_INNER_SPACING = 8;
|
||||
|
||||
const BROWSE_ACTIVATED_BG = new Clutter.Color();
|
||||
BROWSE_ACTIVATED_BG.from_pixel(0x303030f0);
|
||||
|
||||
const PANE_BORDER_COLOR = new Clutter.Color();
|
||||
PANE_BORDER_COLOR.from_pixel(0x101d3cfa);
|
||||
const PANE_BORDER_WIDTH = 2;
|
||||
|
||||
const PANE_BACKGROUND_COLOR = new Clutter.Color();
|
||||
PANE_BACKGROUND_COLOR.from_pixel(0x000000f4);
|
||||
|
||||
const APPS = "apps";
|
||||
const PREFS = "prefs";
|
||||
const DOCS = "docs";
|
||||
|
||||
/*
|
||||
* Returns the index in an array of a given length that is obtained
|
||||
* if the provided index is incremented by an increment and the array
|
||||
* is wrapped in if necessary.
|
||||
*
|
||||
* index: prior index, expects 0 <= index < length
|
||||
* increment: the change in index, expects abs(increment) <= length
|
||||
* length: the length of the array
|
||||
*/
|
||||
function _getIndexWrapped(index, increment, length) {
|
||||
return (index + increment + length) % length;
|
||||
}
|
||||
|
||||
function _createDisplay(displayType) {
|
||||
if (displayType == APPS)
|
||||
return new AppDisplay.AppDisplay();
|
||||
else if (displayType == PREFS)
|
||||
return new AppDisplay.AppDisplay(true);
|
||||
else if (displayType == DOCS)
|
||||
return new DocDisplay.DocDisplay();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function Pane() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Pane.prototype = {
|
||||
_init: function () {
|
||||
this._open = false;
|
||||
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
background_color: PANE_BACKGROUND_COLOR,
|
||||
border: PANE_BORDER_WIDTH,
|
||||
border_color: PANE_BORDER_COLOR,
|
||||
padding: DEFAULT_PADDING,
|
||||
reactive: true });
|
||||
this.actor.connect('button-press-event', Lang.bind(this, function (a, e) {
|
||||
// Eat button press events so they don't go through and close the pane
|
||||
return true;
|
||||
}));
|
||||
|
||||
let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: 6 });
|
||||
|
||||
let closeIconUri = "file://" + global.imagedir + "close.svg";
|
||||
let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
closeIconUri,
|
||||
16,
|
||||
16);
|
||||
closeIcon.reactive = true;
|
||||
closeIcon.connect('button-press-event', Lang.bind(this, function (b, e) {
|
||||
this.close();
|
||||
return true;
|
||||
}));
|
||||
chromeTop.append(closeIcon, Big.BoxPackFlags.END);
|
||||
this.actor.append(chromeTop, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.content = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
spacing: DEFAULT_PADDING });
|
||||
this.actor.append(this.content, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
// Hidden by default
|
||||
this.actor.hide();
|
||||
},
|
||||
|
||||
open: function () {
|
||||
if (this._open)
|
||||
return;
|
||||
this._open = true;
|
||||
this.actor.show();
|
||||
this.emit('open-state-changed', this._open);
|
||||
},
|
||||
|
||||
close: function () {
|
||||
if (!this._open)
|
||||
return;
|
||||
this._open = false;
|
||||
this.actor.hide();
|
||||
this.emit('open-state-changed', this._open);
|
||||
},
|
||||
|
||||
destroyContent: function() {
|
||||
let children = this.content.get_children();
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
children[i].destroy();
|
||||
}
|
||||
},
|
||||
|
||||
toggle: function () {
|
||||
if (this._open)
|
||||
this.close();
|
||||
else
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
Signals.addSignalMethods(Pane.prototype);
|
||||
|
||||
function ResultArea(displayType, enableNavigation) {
|
||||
this._init(displayType, enableNavigation);
|
||||
}
|
||||
|
||||
ResultArea.prototype = {
|
||||
_init : function(displayType, enableNavigation) {
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
||||
this.resultsContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: DEFAULT_PADDING
|
||||
});
|
||||
this.actor.append(this.resultsContainer, Big.BoxPackFlags.EXPAND);
|
||||
this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
||||
this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.display = _createDisplay(displayType);
|
||||
|
||||
this.navArea = this.display.getNavigationArea();
|
||||
if (enableNavigation && this.navArea)
|
||||
this.navContainer.append(this.navArea, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.resultsContainer.append(this.display.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.controlBox = new Big.Box({ x_align: Big.BoxAlignment.CENTER });
|
||||
this.controlBox.append(this.display.displayControl, Big.BoxPackFlags.NONE);
|
||||
this.actor.append(this.controlBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.display.load();
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function shared between ResultPane and the DocDisplay in the main dash.
|
||||
// Connects to the detail signal of the display, and on-demand creates a new
|
||||
// pane.
|
||||
function createPaneForDetails(dash, display) {
|
||||
let detailPane = null;
|
||||
display.connect('show-details', Lang.bind(this, function(display, index) {
|
||||
if (detailPane == null) {
|
||||
detailPane = new Pane();
|
||||
detailPane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
|
||||
if (!isOpen) {
|
||||
/* Ensure we don't keep around large preview textures */
|
||||
detailPane.destroyContent();
|
||||
}
|
||||
}));
|
||||
dash._addPane(detailPane);
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
detailPane.destroyContent();
|
||||
let details = display.createDetailsForIndex(index);
|
||||
detailPane.content.append(details, Big.BoxPackFlags.EXPAND);
|
||||
detailPane.open();
|
||||
} else {
|
||||
detailPane.close();
|
||||
}
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
|
||||
function ResultPane(dash) {
|
||||
this._init(dash);
|
||||
}
|
||||
|
||||
ResultPane.prototype = {
|
||||
__proto__: Pane.prototype,
|
||||
|
||||
_init: function(dash) {
|
||||
Pane.prototype._init.call(this);
|
||||
this._dash = dash;
|
||||
},
|
||||
|
||||
// Create a display of displayType and pack it into this pane's
|
||||
// content area. Return the display.
|
||||
packResults: function(displayType, enableNavigation) {
|
||||
let resultArea = new ResultArea(displayType, enableNavigation);
|
||||
|
||||
createPaneForDetails(this._dash, resultArea.display);
|
||||
|
||||
this.content.append(resultArea.actor, Big.BoxPackFlags.EXPAND);
|
||||
this.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
|
||||
resultArea.display.resetState();
|
||||
}));
|
||||
return resultArea.display;
|
||||
}
|
||||
}
|
||||
|
||||
function SearchEntry() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
SearchEntry.prototype = {
|
||||
_init : function() {
|
||||
this.actor = new Big.Box({ padding: DEFAULT_PADDING,
|
||||
border_bottom: SECTION_BORDER,
|
||||
border_color: SEARCH_BORDER_BOTTOM_COLOR,
|
||||
corner_radius: DASH_CORNER_RADIUS,
|
||||
reactive: true });
|
||||
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this.actor.append(box, Big.BoxPackFlags.EXPAND);
|
||||
this.actor.connect('button-press-event', Lang.bind(this, function () {
|
||||
this._resetTextState(true);
|
||||
return false;
|
||||
}));
|
||||
|
||||
this.pane = null;
|
||||
|
||||
this._defaultText = _("Find...");
|
||||
|
||||
let textProperties = { font_name: "Sans 16px" };
|
||||
let entryProperties = { editable: true,
|
||||
activatable: true,
|
||||
single_line_mode: true,
|
||||
color: SEARCH_TEXT_COLOR,
|
||||
cursor_color: SEARCH_CURSOR_COLOR };
|
||||
Lang.copyProperties(textProperties, entryProperties);
|
||||
this.entry = new Clutter.Text(entryProperties);
|
||||
|
||||
this.entry.connect('notify::text', Lang.bind(this, function () {
|
||||
this._resetTextState(false);
|
||||
}));
|
||||
box.append(this.entry, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
// Mark as editable just to get a cursor
|
||||
let defaultTextProperties = { ellipsize: Pango.EllipsizeMode.END,
|
||||
text: this._defaultText,
|
||||
editable: true,
|
||||
color: TEXT_COLOR,
|
||||
cursor_visible: false,
|
||||
single_line_mode: true };
|
||||
Lang.copyProperties(textProperties, defaultTextProperties);
|
||||
this._defaultText = new Clutter.Text(defaultTextProperties);
|
||||
box.add_actor(this._defaultText);
|
||||
this.entry.connect('notify::allocation', Lang.bind(this, function () {
|
||||
this._repositionDefaultText();
|
||||
}));
|
||||
|
||||
this._iconBox = new Big.Box({ x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
padding_right: 4 });
|
||||
box.append(this._iconBox, Big.BoxPackFlags.END);
|
||||
|
||||
let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
|
||||
this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
magnifierUri, 18, 18);
|
||||
let closeUri = "file://" + global.imagedir + "close-black.svg";
|
||||
this._closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
closeUri, 18, 18);
|
||||
this._closeIcon.reactive = true;
|
||||
this._closeIcon.connect('button-press-event', Lang.bind(this, function () {
|
||||
// Resetting this.entry.text will trigger notify::text signal which will
|
||||
// result in this._resetTextState() being called, but we should not rely
|
||||
// on that not short-circuiting if the text was already empty, so we call
|
||||
// this._resetTextState() explicitly in that case.
|
||||
if (this.entry.text == '')
|
||||
this._resetTextState(false);
|
||||
else
|
||||
this.entry.text = '';
|
||||
|
||||
// Return true to stop the signal emission, so that this.actor doesn't get
|
||||
// the button-press-event and re-highlight itself.
|
||||
return true;
|
||||
}));
|
||||
this._repositionDefaultText();
|
||||
this._resetTextState();
|
||||
},
|
||||
|
||||
setPane: function (pane) {
|
||||
this._pane = pane;
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
this.entry.text = '';
|
||||
},
|
||||
|
||||
getText: function () {
|
||||
return this.entry.text;
|
||||
},
|
||||
|
||||
_resetTextState: function (searchEntryClicked) {
|
||||
let text = this.getText();
|
||||
this._iconBox.remove_all();
|
||||
// We highlight the search box if the user starts typing in it
|
||||
// or just clicks in it to indicate that the search is active.
|
||||
if (text != '' || searchEntryClicked) {
|
||||
if (!searchEntryClicked)
|
||||
this._defaultText.hide();
|
||||
this._iconBox.append(this._closeIcon, Big.BoxPackFlags.NONE);
|
||||
this.actor.background_color = HIGHLIGHTED_SEARCH_BACKGROUND_COLOR;
|
||||
this.entry.cursor_color = HIGHLIGHTED_SEARCH_CURSOR_COLOR;
|
||||
} else {
|
||||
this._defaultText.show();
|
||||
this._iconBox.append(this._magnifierIcon, Big.BoxPackFlags.NONE);
|
||||
this.actor.background_color = BACKGROUND_COLOR;
|
||||
this.entry.cursor_color = SEARCH_CURSOR_COLOR;
|
||||
}
|
||||
},
|
||||
|
||||
_repositionDefaultText: function () {
|
||||
// Offset a little to show the cursor
|
||||
this._defaultText.set_position(this.entry.x + 4, this.entry.y);
|
||||
this._defaultText.set_size(this.entry.width, this.entry.height);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(SearchEntry.prototype);
|
||||
|
||||
function MoreLink() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
MoreLink.prototype = {
|
||||
_init : function () {
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_right: DEFAULT_PADDING,
|
||||
padding_left: DEFAULT_PADDING,
|
||||
reactive: true,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
border_left: SECTION_BORDER,
|
||||
border_color: SECTION_BORDER_COLOR });
|
||||
this.pane = null;
|
||||
|
||||
let text = new Clutter.Text({ font_name: "Sans 12px",
|
||||
color: BRIGHT_TEXT_COLOR,
|
||||
text: _("Browse") });
|
||||
this.actor.append(text, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.actor.connect('button-press-event', Lang.bind(this, function (b, e) {
|
||||
if (this.pane == null) {
|
||||
// Ensure the pane is created; the activated handler will call setPane
|
||||
this.emit('activated');
|
||||
}
|
||||
this._pane.toggle();
|
||||
return true;
|
||||
}));
|
||||
},
|
||||
|
||||
setPane: function (pane) {
|
||||
this._pane = pane;
|
||||
this._pane.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(MoreLink.prototype);
|
||||
|
||||
function BackLink() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
BackLink.prototype = {
|
||||
_init : function () {
|
||||
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_right: DEFAULT_PADDING,
|
||||
padding_left: DEFAULT_PADDING,
|
||||
reactive: true,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
border_right: SECTION_BORDER,
|
||||
border_color: SECTION_BORDER_COLOR });
|
||||
|
||||
let backIconUri = "file://" + global.imagedir + "back.svg";
|
||||
let backIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
backIconUri,
|
||||
12,
|
||||
16);
|
||||
this.actor.append(backIcon, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
function SectionHeader(title, suppressBrowse) {
|
||||
this._init(title, suppressBrowse);
|
||||
}
|
||||
|
||||
SectionHeader.prototype = {
|
||||
_init : function (title, suppressBrowse) {
|
||||
this.actor = new Big.Box({ border: SECTION_BORDER,
|
||||
border_color: SECTION_BORDER_COLOR });
|
||||
this._innerBox = new Big.Box({ border: SECTION_BORDER,
|
||||
border_color: SECTION_INNER_BORDER_COLOR,
|
||||
padding_left: DEFAULT_PADDING,
|
||||
padding_right: DEFAULT_PADDING,
|
||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: DEFAULT_SPACING });
|
||||
this.actor.append(this._innerBox, Big.BoxPackFlags.EXPAND);
|
||||
let backgroundGradient = Shell.create_vertical_gradient(SECTION_BACKGROUND_TOP_COLOR,
|
||||
SECTION_BACKGROUND_BOTTOM_COLOR);
|
||||
this._innerBox.add_actor(backgroundGradient);
|
||||
this._innerBox.connect('notify::allocation', Lang.bind(this, function (actor) {
|
||||
let [width, height] = actor.get_size();
|
||||
backgroundGradient.set_size(width, height);
|
||||
}));
|
||||
|
||||
this.backLink = new BackLink();
|
||||
this._innerBox.append(this.backLink.actor, Big.BoxPackFlags.NONE);
|
||||
this.backLink.actor.hide();
|
||||
|
||||
this.backLink.actor.connect('activate', Lang.bind(this, function (actor) {
|
||||
this.emit('back-link-activated');
|
||||
}));
|
||||
|
||||
let textBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_top: DEFAULT_PADDING,
|
||||
padding_bottom: DEFAULT_PADDING });
|
||||
this.text = new Clutter.Text({ color: TEXT_COLOR,
|
||||
font_name: "Sans Bold 12px",
|
||||
text: title });
|
||||
textBox.append(this.text, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.countText = new Clutter.Text({ color: TEXT_COLOR,
|
||||
font_name: 'Sans Bold 14px' });
|
||||
textBox.append(this.countText, Big.BoxPackFlags.END);
|
||||
this.countText.hide();
|
||||
|
||||
this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
if (!suppressBrowse) {
|
||||
this.moreLink = new MoreLink();
|
||||
this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END);
|
||||
}
|
||||
},
|
||||
|
||||
setTitle : function(title) {
|
||||
this.text.text = title;
|
||||
},
|
||||
|
||||
setBackLinkVisible : function(visible) {
|
||||
if (visible)
|
||||
this.backLink.actor.show();
|
||||
else
|
||||
this.backLink.actor.hide();
|
||||
},
|
||||
|
||||
setCountText : function(countText) {
|
||||
if (countText == "") {
|
||||
this.countText.hide();
|
||||
} else {
|
||||
this.countText.show();
|
||||
this.countText.text = countText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(SectionHeader.prototype);
|
||||
|
||||
function SearchSectionHeader(title, onClick) {
|
||||
this._init(title, onClick);
|
||||
}
|
||||
|
||||
SearchSectionHeader.prototype = {
|
||||
_init : function(title, onClick) {
|
||||
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_top: DASH_SECTION_PADDING,
|
||||
padding_bottom: DASH_SECTION_PADDING,
|
||||
spacing: DEFAULT_SPACING });
|
||||
let titleText = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR,
|
||||
font_name: 'Sans Bold 12px',
|
||||
text: title });
|
||||
this.tooltip = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR,
|
||||
font_name: 'Sans 12px',
|
||||
text: _("(see all)") });
|
||||
this.countText = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR,
|
||||
font_name: 'Sans Bold 14px' });
|
||||
|
||||
box.append(titleText, Big.BoxPackFlags.NONE);
|
||||
box.append(this.tooltip, Big.BoxPackFlags.NONE);
|
||||
box.append(this.countText, Big.BoxPackFlags.END);
|
||||
|
||||
this.tooltip.hide();
|
||||
|
||||
let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR,
|
||||
TEXT_COLOR);
|
||||
button.actor.height = box.height;
|
||||
button.actor.padding_left = DEFAULT_PADDING;
|
||||
button.actor.padding_right = DEFAULT_PADDING;
|
||||
|
||||
button.actor.connect('activate', onClick);
|
||||
button.actor.connect('notify::hover', Lang.bind(this, this._updateTooltip));
|
||||
this.actor = button.actor;
|
||||
},
|
||||
|
||||
_updateTooltip : function(actor) {
|
||||
if (actor.hover)
|
||||
this.tooltip.show();
|
||||
else
|
||||
this.tooltip.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function Section(titleString, suppressBrowse) {
|
||||
this._init(titleString, suppressBrowse);
|
||||
}
|
||||
|
||||
Section.prototype = {
|
||||
_init: function(titleString, suppressBrowse) {
|
||||
this.actor = new Big.Box({ spacing: SECTION_INNER_SPACING });
|
||||
this.header = new SectionHeader(titleString, suppressBrowse);
|
||||
this.actor.append(this.header.actor, Big.BoxPackFlags.NONE);
|
||||
this.content = new Big.Box({spacing: SECTION_INNER_SPACING });
|
||||
this.actor.append(this.content, Big.BoxPackFlags.EXPAND);
|
||||
}
|
||||
}
|
||||
|
||||
function Dash() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Dash.prototype = {
|
||||
_init : function() {
|
||||
// dash and the popup panes need to be reactive so that the clicks in unoccupied places on them
|
||||
// are not passed to the transparent background underneath them. This background is used for the workspaces area when
|
||||
// the additional dash panes are being shown and it handles clicks by closing the additional panes, so that the user
|
||||
// can interact with the workspaces. However, this behavior is not desirable when the click is actually over a pane.
|
||||
//
|
||||
// We have to make the individual panes reactive instead of making the whole dash actor reactive because the width
|
||||
// of the Group actor ends up including the width of its hidden children, so we were getting a reactive object as
|
||||
// wide as the details pane that was blocking the clicks to the workspaces underneath it even when the details pane
|
||||
// was actually hidden.
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
background_color: BACKGROUND_COLOR,
|
||||
corner_radius: DASH_CORNER_RADIUS,
|
||||
padding_left: DASH_PADDING_SIDE,
|
||||
padding_right: DASH_PADDING_SIDE,
|
||||
reactive: true });
|
||||
|
||||
// Size for this one explicitly set from overlay.js
|
||||
this.searchArea = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||
|
||||
this.sectionArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
spacing: DASH_SECTION_SPACING });
|
||||
|
||||
this.actor.append(this.searchArea, Big.BoxPackFlags.NONE);
|
||||
this.actor.append(this.sectionArea, Big.BoxPackFlags.NONE);
|
||||
|
||||
// The currently active popup display
|
||||
this._activePane = null;
|
||||
|
||||
/***** Search *****/
|
||||
|
||||
this._searchActive = false;
|
||||
this._searchEntry = new SearchEntry();
|
||||
this.searchArea.append(this._searchEntry.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._searchTimeoutId = 0;
|
||||
this._searchEntry.entry.connect('text-changed', Lang.bind(this, function (se, prop) {
|
||||
let text = this._searchEntry.getText();
|
||||
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "")
|
||||
this._searchActive = text != '';
|
||||
this._updateDashActors();
|
||||
if (!this._searchActive) {
|
||||
if (this._searchTimeoutId > 0) {
|
||||
Mainloop.source_remove(this._searchTimeoutId);
|
||||
this._searchTimeoutId = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this._searchTimeoutId > 0)
|
||||
return;
|
||||
this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, function() {
|
||||
this._searchTimeoutId = 0;
|
||||
let text = this._searchEntry.getText();
|
||||
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
||||
|
||||
let selectionSet = false;
|
||||
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
section.resultArea.display.setSearch(text);
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
let itemCountText = itemCount + "";
|
||||
section.header.countText.text = itemCountText;
|
||||
|
||||
if (this._searchResultsSingleShownSection == section.type) {
|
||||
this._searchResultsSection.header.setCountText(itemCountText);
|
||||
if (itemCount == 0) {
|
||||
section.resultArea.actor.hide();
|
||||
} else {
|
||||
section.resultArea.actor.show();
|
||||
}
|
||||
} else if (this._searchResultsSingleShownSection == null) {
|
||||
// Don't show the section if it has no results
|
||||
if (itemCount == 0) {
|
||||
section.header.actor.hide();
|
||||
section.resultArea.actor.hide();
|
||||
} else {
|
||||
section.header.actor.show();
|
||||
section.resultArea.actor.show();
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh the selection when a new search is applied.
|
||||
section.resultArea.display.unsetSelected();
|
||||
if (!selectionSet && section.resultArea.display.hasItems() &&
|
||||
(this._searchResultsSingleShownSection == null || this._searchResultsSingleShownSection == section.type)) {
|
||||
section.resultArea.display.selectFirstItem();
|
||||
selectionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}));
|
||||
}));
|
||||
this._searchEntry.entry.connect('activate', Lang.bind(this, function (se) {
|
||||
// Only one of the displays will have an item selected, so it's ok to
|
||||
// call activateSelected() on all of them.
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
section.resultArea.display.activateSelected();
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
this._searchEntry.entry.connect('key-press-event', Lang.bind(this, function (se, e) {
|
||||
let text = this._searchEntry.getText();
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
// Escape will keep clearing things back to the desktop.
|
||||
// If we are showing a particular section of search, go back to all sections.
|
||||
if (this._searchResultsSingleShownSection != null)
|
||||
this._showAllSearchSections();
|
||||
// If we have an active search, we remove it.
|
||||
else if (this._searchActive)
|
||||
this._searchEntry.reset();
|
||||
// Next, if we're in one of the "more" modes or showing the details pane, close them
|
||||
else if (this._activePane != null)
|
||||
this._activePane.close();
|
||||
// Finally, just close the Overview entirely
|
||||
else
|
||||
Main.overview.hide();
|
||||
return true;
|
||||
} else if (symbol == Clutter.Up) {
|
||||
if (!this._searchActive)
|
||||
return true;
|
||||
// selectUp and selectDown wrap around in their respective displays
|
||||
// too, but there doesn't seem to be any flickering if we first select
|
||||
// something in one display, but then unset the selection, and move
|
||||
// it to the other display, so it's ok to do that.
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectUp()) {
|
||||
if (this._searchResultsSingleShownSection != section.type) {
|
||||
// We need to move the selection to the next section above this section that has items,
|
||||
// wrapping around at the bottom, if necessary.
|
||||
let newSectionIndex = this._findAnotherSectionWithItems(i, -1);
|
||||
if (newSectionIndex >= 0) {
|
||||
this._searchSections[newSectionIndex].resultArea.display.selectLastItem();
|
||||
section.resultArea.display.unsetSelected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (symbol == Clutter.Down) {
|
||||
if (!this._searchActive)
|
||||
return true;
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectDown()) {
|
||||
if (this._searchResultsSingleShownSection != section.type) {
|
||||
// We need to move the selection to the next section below this section that has items,
|
||||
// wrapping around at the top, if necessary.
|
||||
let newSectionIndex = this._findAnotherSectionWithItems(i, 1);
|
||||
if (newSectionIndex >= 0) {
|
||||
this._searchSections[newSectionIndex].resultArea.display.selectFirstItem();
|
||||
section.resultArea.display.unsetSelected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
|
||||
/***** Applications *****/
|
||||
|
||||
this._appsSection = new Section(_("APPLICATIONS"));
|
||||
let appWell = new AppDisplay.AppWell();
|
||||
this._appsSection.content.append(appWell.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._moreAppsPane = null;
|
||||
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
||||
if (this._moreAppsPane == null) {
|
||||
this._moreAppsPane = new ResultPane(this);
|
||||
this._moreAppsPane.packResults(APPS, true);
|
||||
this._addPane(this._moreAppsPane);
|
||||
link.setPane(this._moreAppsPane);
|
||||
}
|
||||
}));
|
||||
|
||||
this.sectionArea.append(this._appsSection.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
/***** Places *****/
|
||||
|
||||
/* Translators: This is in the sense of locations for documents,
|
||||
network locations, etc. */
|
||||
this._placesSection = new Section(_("PLACES"), true);
|
||||
let placesDisplay = new Places.Places();
|
||||
this._placesSection.content.append(placesDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
this.sectionArea.append(this._placesSection.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
/***** Documents *****/
|
||||
|
||||
this._docsSection = new Section(_("RECENT DOCUMENTS"));
|
||||
|
||||
let docDisplay = new DocDisplay.DashDocDisplay();
|
||||
this._docsSection.content.append(docDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._moreDocsPane = null;
|
||||
this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
||||
if (this._moreDocsPane == null) {
|
||||
this._moreDocsPane = new ResultPane(this);
|
||||
this._moreDocsPane.packResults(DOCS, true);
|
||||
this._addPane(this._moreDocsPane);
|
||||
link.setPane(this._moreDocsPane);
|
||||
}
|
||||
}));
|
||||
|
||||
this.sectionArea.append(this._docsSection.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
/***** Search Results *****/
|
||||
|
||||
this._searchResultsSection = new Section(_("SEARCH RESULTS"), true);
|
||||
|
||||
this._searchResultsSingleShownSection = null;
|
||||
|
||||
this._searchResultsSection.header.connect('back-link-activated', Lang.bind(this, function () {
|
||||
this._showAllSearchSections();
|
||||
}));
|
||||
|
||||
this._searchSections = [
|
||||
{ type: APPS,
|
||||
title: _("APPLICATIONS"),
|
||||
header: null,
|
||||
resultArea: null
|
||||
},
|
||||
{ type: PREFS,
|
||||
title: _("PREFERENCES"),
|
||||
header: null,
|
||||
resultArea: null
|
||||
},
|
||||
{ type: DOCS,
|
||||
title: _("RECENT DOCUMENTS"),
|
||||
header: null,
|
||||
resultArea: null
|
||||
}
|
||||
];
|
||||
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
section.header = new SearchSectionHeader(section.title,
|
||||
Lang.bind(this,
|
||||
function () {
|
||||
this._showSingleSearchSection(section.type);
|
||||
}));
|
||||
this._searchResultsSection.content.append(section.header.actor, Big.BoxPackFlags.NONE);
|
||||
section.resultArea = new ResultArea(section.type, false);
|
||||
section.resultArea.controlBox.hide();
|
||||
this._searchResultsSection.content.append(section.resultArea.actor, Big.BoxPackFlags.EXPAND);
|
||||
createPaneForDetails(this, section.resultArea.display);
|
||||
}
|
||||
|
||||
this.sectionArea.append(this._searchResultsSection.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._searchResultsSection.actor.hide();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
global.stage.set_key_focus(this._searchEntry.entry);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._firstSelectAfterOverlayShow = true;
|
||||
this._searchEntry.reset();
|
||||
if (this._activePane != null)
|
||||
this._activePane.close();
|
||||
},
|
||||
|
||||
closePanes: function () {
|
||||
if (this._activePane != null)
|
||||
this._activePane.close();
|
||||
},
|
||||
|
||||
_addPane: function(pane) {
|
||||
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
|
||||
if (isOpen) {
|
||||
if (pane != this._activePane && this._activePane != null) {
|
||||
this._activePane.close();
|
||||
}
|
||||
this._activePane = pane;
|
||||
} else if (pane == this._activePane) {
|
||||
this._activePane = null;
|
||||
}
|
||||
}));
|
||||
Main.overview.addPane(pane);
|
||||
},
|
||||
|
||||
_updateDashActors: function() {
|
||||
if (!this._searchActive && this._searchResultsSection.actor.visible) {
|
||||
this._showAllSearchSections();
|
||||
this._searchResultsSection.actor.hide();
|
||||
this._appsSection.actor.show();
|
||||
this._placesSection.actor.show();
|
||||
this._docsSection.actor.show();
|
||||
} else if (this._searchActive && !this._searchResultsSection.actor.visible) {
|
||||
this._searchResultsSection.actor.show();
|
||||
this._appsSection.actor.hide();
|
||||
this._placesSection.actor.hide();
|
||||
this._docsSection.actor.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_showSingleSearchSection: function(type) {
|
||||
// We currently don't allow going from showing one section to showing another section.
|
||||
if (this._searchResultsSingleShownSection != null) {
|
||||
throw new Error("We were already showing a single search section: '" + this._searchResultsSingleShownSection
|
||||
+ "' when _showSingleSearchSection() was called for '" + type + "'");
|
||||
}
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.type == type) {
|
||||
// This will be the only section shown.
|
||||
section.resultArea.display.selectFirstItem();
|
||||
section.resultArea.controlBox.show();
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
let itemCountText = itemCount + "";
|
||||
section.header.actor.hide();
|
||||
this._searchResultsSection.header.setTitle(section.title);
|
||||
this._searchResultsSection.header.setBackLinkVisible(true);
|
||||
this._searchResultsSection.header.setCountText(itemCountText);
|
||||
} else {
|
||||
// We need to hide this section.
|
||||
section.header.actor.hide();
|
||||
section.resultArea.actor.hide();
|
||||
section.resultArea.display.unsetSelected();
|
||||
}
|
||||
}
|
||||
this._searchResultsSingleShownSection = type;
|
||||
},
|
||||
|
||||
_showAllSearchSections: function() {
|
||||
if (this._searchResultsSingleShownSection != null) {
|
||||
let selectionSet = false;
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.type == this._searchResultsSingleShownSection) {
|
||||
// This will no longer be the only section shown.
|
||||
section.resultArea.display.displayPage(0);
|
||||
section.resultArea.controlBox.hide();
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
if (itemCount != 0) {
|
||||
section.header.actor.show();
|
||||
section.resultArea.display.selectFirstItem();
|
||||
selectionSet = true;
|
||||
}
|
||||
this._searchResultsSection.header.setTitle(_("SEARCH RESULTS"));
|
||||
this._searchResultsSection.header.setBackLinkVisible(false);
|
||||
this._searchResultsSection.header.setCountText("");
|
||||
} else {
|
||||
// We need to restore this section.
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
if (itemCount != 0) {
|
||||
section.header.actor.show();
|
||||
section.resultArea.actor.show();
|
||||
// This ensures that some other section will have the selection if the
|
||||
// single section that was being displayed did not have any items.
|
||||
if (!selectionSet) {
|
||||
section.resultArea.display.selectFirstItem();
|
||||
selectionSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._searchResultsSingleShownSection = null;
|
||||
}
|
||||
},
|
||||
|
||||
_findAnotherSectionWithItems: function(index, increment) {
|
||||
let pos = _getIndexWrapped(index, increment, this._searchSections.length);
|
||||
while (pos != index) {
|
||||
if (this._searchSections[pos].resultArea.display.hasItems())
|
||||
return pos;
|
||||
pos = _getIndexWrapped(pos, increment, this._searchSections.length);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Dash.prototype);
|
158
js/ui/dnd.js
@ -8,15 +8,17 @@ const Tweener = imports.ui.tweener;
|
||||
|
||||
const SNAP_BACK_ANIMATION_TIME = 0.25;
|
||||
|
||||
function _Draggable(actor) {
|
||||
this._init(actor);
|
||||
function _Draggable(actor, manualMode) {
|
||||
this._init(actor, manualMode);
|
||||
}
|
||||
|
||||
_Draggable.prototype = {
|
||||
_init : function(actor) {
|
||||
_init : function(actor, manualMode) {
|
||||
this.actor = actor;
|
||||
this.actor.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
if (!manualMode)
|
||||
this.actor.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
this._haveSourceGrab = false;
|
||||
},
|
||||
|
||||
_onButtonPress : function (actor, event) {
|
||||
@ -25,6 +27,7 @@ _Draggable.prototype = {
|
||||
if (Tweener.getTweenCount(actor))
|
||||
return false;
|
||||
|
||||
this._haveSourceGrab = true;
|
||||
this._grabActor(actor);
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
@ -66,6 +69,80 @@ _Draggable.prototype = {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* startDrag:
|
||||
* @actor: Origin actor for drag and drop
|
||||
* @stageX: X coordinate of event
|
||||
* @stageY: Y coordinate of event
|
||||
* @time: Event timestamp
|
||||
*
|
||||
* Directly initiate a drag and drop operation from the given actor.
|
||||
* This function is useful to call if you've specified manualMode
|
||||
* for the draggable.
|
||||
*/
|
||||
startDrag: function (actor, stageX, stageY, time) {
|
||||
this.emit('drag-begin', time);
|
||||
|
||||
this._dragStartX = stageX;
|
||||
this._dragStartY = stageY;
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||
// Drag actor does not always have to be the same as actor. For example drag actor
|
||||
// can be an image that's part of the actor. So to perform "snap back" correctly we need
|
||||
// to know what was the drag actor source.
|
||||
if (this.actor._delegate.getDragActorSource) {
|
||||
this._dragActorSource = this.actor._delegate.getDragActorSource();
|
||||
// If the user dragged from the source, then position
|
||||
// the dragActor over it. Otherwise, center it
|
||||
// around the pointer
|
||||
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
||||
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
|
||||
let x, y;
|
||||
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
|
||||
stageY > sourceY && stageY <= sourceY + sourceHeight) {
|
||||
x = sourceX;
|
||||
y = sourceY;
|
||||
} else {
|
||||
x = stageX - this._dragActor.width / 2;
|
||||
y = stageY - this._dragActor.height / 2;
|
||||
}
|
||||
this._dragActor.set_position(x, y);
|
||||
} else {
|
||||
this._dragActorSource = this.actor;
|
||||
}
|
||||
this._dragOrigParent = undefined;
|
||||
if (this._haveSourceGrab) {
|
||||
this._haveSourceGrab = false;
|
||||
this._ungrabActor(actor);
|
||||
}
|
||||
this._grabActor(this._dragActor);
|
||||
|
||||
this._dragOffsetX = this._dragActor.x - this._dragStartX;
|
||||
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
||||
} else {
|
||||
this._dragActor = actor;
|
||||
this._dragActorSource = undefined;
|
||||
this._dragOrigParent = actor.get_parent();
|
||||
this._dragOrigX = this._dragActor.x;
|
||||
this._dragOrigY = this._dragActor.y;
|
||||
this._dragOrigScale = this._dragActor.scale_x;
|
||||
|
||||
let [actorStageX, actorStageY] = actor.get_transformed_position();
|
||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||
|
||||
// Set the actor's scale such that it will keep the same
|
||||
// transformed size when it's reparented to the stage
|
||||
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
|
||||
actor.set_scale(scaledWidth / actor.width,
|
||||
scaledHeight / actor.height);
|
||||
}
|
||||
|
||||
this._dragActor.reparent(actor.get_stage());
|
||||
this._dragActor.raise_top();
|
||||
},
|
||||
|
||||
_onMotion : function (actor, event) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
|
||||
@ -75,44 +152,7 @@ _Draggable.prototype = {
|
||||
if (!this._dragActor &&
|
||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||
this.emit('drag-begin', event.get_time());
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||
// Drag actor does not always have to be the same as actor. For example drag actor
|
||||
// can be an image that's part of the actor. So to perform "snap back" correctly we need
|
||||
// to know what was the drag actor source.
|
||||
if (this.actor._delegate.getDragActorSource)
|
||||
this._dragActorSource = this.actor._delegate.getDragActorSource();
|
||||
else
|
||||
this._dragActorSource = this.actor;
|
||||
this._dragOrigParent = undefined;
|
||||
this._ungrabActor(actor);
|
||||
this._grabActor(this._dragActor);
|
||||
|
||||
this._dragOffsetX = this._dragActor.x - this._dragStartX;
|
||||
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
||||
} else {
|
||||
this._dragActor = actor;
|
||||
this._dragActorSource = undefined;
|
||||
this._dragOrigParent = actor.get_parent();
|
||||
this._dragOrigX = this._dragActor.x;
|
||||
this._dragOrigY = this._dragActor.y;
|
||||
this._dragOrigScale = this._dragActor.scale_x;
|
||||
|
||||
let [actorStageX, actorStageY] = actor.get_transformed_position();
|
||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||
|
||||
// Set the actor's scale such that it will keep the same
|
||||
// transformed size when it's reparented to the stage
|
||||
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
|
||||
actor.set_scale(scaledWidth / actor.width,
|
||||
scaledHeight / actor.height);
|
||||
}
|
||||
|
||||
this._dragActor.reparent(actor.get_stage());
|
||||
this._dragActor.raise_top();
|
||||
this.startDrag(actor, stageX, stageY, event.get_time());
|
||||
}
|
||||
|
||||
// If we are dragging, update the position
|
||||
@ -133,12 +173,12 @@ _Draggable.prototype = {
|
||||
// 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.
|
||||
target._delegate.handleDragOver(this.actor._delegate, actor,
|
||||
(stageX + this._dragOffsetX + this._xOffset - targX) / target.scale_x,
|
||||
(stageY + this._dragOffsetY + this._yOffset - targY) / target.scale_y,
|
||||
(stageX + this._dragOffsetX - targX) / target.scale_x,
|
||||
(stageY + this._dragOffsetY - targY) / target.scale_y,
|
||||
event.get_time());
|
||||
}
|
||||
target = target.get_parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -153,8 +193,6 @@ _Draggable.prototype = {
|
||||
if (!dragging)
|
||||
return false;
|
||||
|
||||
this.emit('drag-end', event.get_time());
|
||||
|
||||
// Find a drop target
|
||||
actor.hide();
|
||||
let [dropX, dropY] = event.get_coords();
|
||||
@ -165,14 +203,15 @@ _Draggable.prototype = {
|
||||
if (target._delegate && target._delegate.acceptDrop) {
|
||||
let [targX, targY] = target.get_transformed_position();
|
||||
if (target._delegate.acceptDrop(this.actor._delegate, actor,
|
||||
(dropX + this._xOffset - targX) / target.scale_x,
|
||||
(dropY + this._yOffset - targY) / target.scale_y,
|
||||
(dropX - targX) / target.scale_x,
|
||||
(dropY - targY) / target.scale_y,
|
||||
event.get_time())) {
|
||||
// If it accepted the drop without taking the actor,
|
||||
// destroy it.
|
||||
if (actor.get_parent() == actor.get_stage())
|
||||
actor.destroy();
|
||||
|
||||
this.emit('drag-end', event.get_time(), true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -196,23 +235,32 @@ _Draggable.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._onSnapBackComplete,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor]
|
||||
onCompleteParams: [actor, event.get_time()]
|
||||
});
|
||||
return true;
|
||||
},
|
||||
|
||||
_onSnapBackComplete : function (dragActor) {
|
||||
_onSnapBackComplete : function (dragActor, eventTime) {
|
||||
if (this._dragOrigParent) {
|
||||
dragActor.reparent(this._dragOrigParent);
|
||||
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
|
||||
dragActor.set_position(this._dragOrigX, this._dragOrigY);
|
||||
} else
|
||||
} else {
|
||||
dragActor.destroy();
|
||||
}
|
||||
this.emit('drag-end', eventTime, false);
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(_Draggable.prototype);
|
||||
|
||||
function makeDraggable(actor) {
|
||||
return new _Draggable(actor);
|
||||
/**
|
||||
* makeDraggable:
|
||||
* @actor: Source actor
|
||||
* @manualMode: If given, do not automatically start drag and drop on click
|
||||
*
|
||||
* Create an object which controls drag and drop for the given actor.
|
||||
*/
|
||||
function makeDraggable(actor, manualMode) {
|
||||
return new _Draggable(actor, manualMode);
|
||||
}
|
||||
|
@ -1,38 +1,59 @@
|
||||
/* -*- 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 Lang = imports.lang;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
const DND = imports.ui.dnd;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const DASH_DOCS_ICON_SIZE = 16;
|
||||
|
||||
const DEFAULT_SPACING = 4;
|
||||
|
||||
/* This class represents a single display item containing information about a document.
|
||||
* We take the current number of seconds in the constructor to avoid looking up the current
|
||||
* time for every item when they are created in a batch.
|
||||
*
|
||||
* docInfo - DocInfo object containing information about the document
|
||||
* availableWidth - total width available for the item
|
||||
* currentSeconds - current number of seconds since the epoch
|
||||
*/
|
||||
function DocDisplayItem(docInfo, availableWidth) {
|
||||
this._init(docInfo, availableWidth);
|
||||
function DocDisplayItem(docInfo, currentSecs) {
|
||||
this._init(docInfo, currentSecs);
|
||||
}
|
||||
|
||||
DocDisplayItem.prototype = {
|
||||
__proto__: GenericDisplay.GenericDisplayItem.prototype,
|
||||
|
||||
_init : function(docInfo, availableWidth) {
|
||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
|
||||
_init : function(docInfo, currentSecs) {
|
||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
|
||||
this._docInfo = docInfo;
|
||||
|
||||
this._setItemInfo(docInfo.name, "",
|
||||
docInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
|
||||
|
||||
this._setItemInfo(docInfo.name, "");
|
||||
|
||||
this._timeoutTime = -1;
|
||||
this._resetTimeDisplay(currentSecs);
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
getUpdateTimeoutTime: function() {
|
||||
return this._timeoutTime;
|
||||
},
|
||||
|
||||
// Update any relative-time based displays for this item.
|
||||
redisplay: function(currentSecs) {
|
||||
this._resetTimeDisplay(currentSecs);
|
||||
},
|
||||
|
||||
//// Public method overrides ////
|
||||
|
||||
// Opens a document represented by this display item.
|
||||
@ -42,66 +63,95 @@ DocDisplayItem.prototype = {
|
||||
|
||||
//// Protected method overrides ////
|
||||
|
||||
// Ensures the preview icon is created.
|
||||
_ensurePreviewIconCreated : function() {
|
||||
if (!this._previewIcon)
|
||||
this._previewIcon = this._docInfo.getIcon(GenericDisplay.PREVIEW_ICON_SIZE);
|
||||
// Returns an icon for the item.
|
||||
_createIcon : function() {
|
||||
return this._docInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
|
||||
},
|
||||
|
||||
// Returns a preview icon for the item.
|
||||
_createPreviewIcon : function() {
|
||||
return this._docInfo.createIcon(GenericDisplay.PREVIEW_ICON_SIZE);
|
||||
},
|
||||
|
||||
// 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.
|
||||
_createLargePreviewIcon : function(availableWidth, availableHeight) {
|
||||
_createLargePreviewIcon : function() {
|
||||
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf("image/") != 0)
|
||||
return null;
|
||||
|
||||
return Shell.TextureCache.get_default().load_uri_sync(this._docInfo.uri, availableWidth, availableHeight);
|
||||
try {
|
||||
return Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.NONE,
|
||||
this._docInfo.uri, -1, -1);
|
||||
} catch (e) {
|
||||
// An exception will be raised when the image format isn't know
|
||||
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
|
||||
* only ignore GDK_PIXBUF_ERROR_UNKNOWN_TYPE. */
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
//// Drag and Drop ////
|
||||
|
||||
shellWorkspaceLaunch: function() {
|
||||
this.launch();
|
||||
},
|
||||
|
||||
//// Private Methods ////
|
||||
|
||||
// Updates the last visited time displayed in the description text for the item.
|
||||
_resetTimeDisplay: function(currentSecs) {
|
||||
let lastSecs = this._docInfo.timestamp;
|
||||
let timeDelta = currentSecs - lastSecs;
|
||||
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
|
||||
this._timeoutTime = currentSecs + nextUpdate;
|
||||
this._setDescriptionText(text);
|
||||
}
|
||||
};
|
||||
|
||||
/* This class represents a display containing a collection of document items.
|
||||
* The documents are sorted by how recently they were last visited.
|
||||
*
|
||||
* width - width available for the display
|
||||
* height - height available for the display
|
||||
*/
|
||||
function DocDisplay(width, height, numberOfColumns, columnGap) {
|
||||
this._init(width, height, numberOfColumns, columnGap);
|
||||
}
|
||||
function DocDisplay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DocDisplay.prototype = {
|
||||
__proto__: GenericDisplay.GenericDisplay.prototype,
|
||||
|
||||
_init : function(width, height, numberOfColumns, columnGap) {
|
||||
GenericDisplay.GenericDisplay.prototype._init.call(this, width, height, numberOfColumns, columnGap);
|
||||
let me = this;
|
||||
this._recentManager = Gtk.RecentManager.get_default();
|
||||
_init : function() {
|
||||
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||
// We keep a single timeout callback for updating last visited times
|
||||
// for all the items in the display. This avoids creating individual
|
||||
// callbacks for each item in the display. So proper time updates
|
||||
// for individual items and item details depend on the item being
|
||||
// associated with one of the displays.
|
||||
this._updateTimeoutTargetTime = -1;
|
||||
this._updateTimeoutId = 0;
|
||||
|
||||
this._docManager = DocInfo.getDocManager();
|
||||
this._docsStale = true;
|
||||
this._recentManager.connect('changed', function(recentManager, userData) {
|
||||
me._docsStale = true;
|
||||
// Changes in local recent files should not happen when we are in the overlay mode,
|
||||
this._docManager.connect('changed', Lang.bind(this, function(mgr, userData) {
|
||||
this._docsStale = true;
|
||||
// Changes in local recent files should not happen when we are in the Overview mode,
|
||||
// but redisplaying right away is cool when we use Zephyr.
|
||||
// Also, we might be displaying remote documents, like Google Docs, in the future
|
||||
// which might be edited by someone else.
|
||||
me._redisplay(false);
|
||||
});
|
||||
this._redisplay(false);
|
||||
}));
|
||||
|
||||
this.connect('destroy', Lang.bind(this, function (o) {
|
||||
if (this._updateTimeoutId > 0)
|
||||
Mainloop.source_remove(this._updateTimeoutId);
|
||||
}));
|
||||
},
|
||||
|
||||
//// Protected method overrides ////
|
||||
|
||||
// Gets the list of recent items from the recent items manager.
|
||||
_refreshCache : function() {
|
||||
let me = this;
|
||||
if (!this._docsStale)
|
||||
return;
|
||||
this._allItems = {};
|
||||
let docs = this._recentManager.get_items();
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
let recentInfo = docs[i];
|
||||
let docInfo = new DocInfo.DocInfo(recentInfo);
|
||||
|
||||
// we use GtkRecentInfo URI as an item Id
|
||||
this._allItems[docInfo.uri] = docInfo;
|
||||
}
|
||||
this._allItems = this._docManager.getItems();
|
||||
this._docsStale = false;
|
||||
},
|
||||
|
||||
@ -116,7 +166,7 @@ DocDisplay.prototype = {
|
||||
// we should do the sorting manually because we want the order to be based on last visited.
|
||||
//
|
||||
// This function is called each time the search string is set back to '' or we display
|
||||
// the overlay, so we are doing the sorting over the same items multiple times if the list
|
||||
// the Overview, so we are doing the sorting over the same items multiple times if the list
|
||||
// of recent items didn't change. We could store an additional array of doc ids and sort
|
||||
// them once when they are returned by this._recentManager.get_items() to avoid having to do
|
||||
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
|
||||
@ -145,7 +195,7 @@ DocDisplay.prototype = {
|
||||
let docA = this._allItems[itemIdA];
|
||||
let docB = this._allItems[itemIdB];
|
||||
|
||||
return docB.lastVisited() - docA.lastVisited();
|
||||
return docB.timestamp - docA.timestamp;
|
||||
},
|
||||
|
||||
// Checks if the item info can be a match for the search string by checking
|
||||
@ -168,8 +218,219 @@ DocDisplay.prototype = {
|
||||
|
||||
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
|
||||
_createDisplayItem: function(itemInfo) {
|
||||
return new DocDisplayItem(itemInfo, this._columnWidth);
|
||||
}
|
||||
let currentSecs = new Date().getTime() / 1000;
|
||||
let docDisplayItem = new DocDisplayItem(itemInfo, currentSecs);
|
||||
this._updateTimeoutCallback(docDisplayItem, currentSecs);
|
||||
return docDisplayItem;
|
||||
},
|
||||
|
||||
//// Private Methods ////
|
||||
|
||||
// A callback function that redisplays the items, updating their descriptions,
|
||||
// and sets up a new timeout callback.
|
||||
_docTimeout: function () {
|
||||
let currentSecs = new Date().getTime() / 1000;
|
||||
this._updateTimeoutId = 0;
|
||||
this._updateTimeoutTargetTime = -1;
|
||||
for (let docId in this._displayedItems) {
|
||||
let docDisplayItem = this._displayedItems[docId];
|
||||
docDisplayItem.redisplay(currentSecs);
|
||||
this._updateTimeoutCallback(docDisplayItem, currentSecs);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Updates the timeout callback if the timeout time for the docDisplayItem
|
||||
// is earlier than the target time for the current timeout callback.
|
||||
_updateTimeoutCallback: function (docDisplayItem, currentSecs) {
|
||||
let timeoutTime = docDisplayItem.getUpdateTimeoutTime();
|
||||
if (this._updateTimeoutTargetTime < 0 || timeoutTime < this._updateTimeoutTargetTime) {
|
||||
if (this._updateTimeoutId > 0)
|
||||
Mainloop.source_remove(this._updateTimeoutId);
|
||||
this._updateTimeoutId = Mainloop.timeout_add_seconds(timeoutTime - currentSecs, Lang.bind(this, this._docTimeout));
|
||||
this._updateTimeoutTargetTime = timeoutTime;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(DocDisplay.prototype);
|
||||
|
||||
function DashDocDisplayItem(docInfo) {
|
||||
this._init(docInfo);
|
||||
}
|
||||
|
||||
DashDocDisplayItem.prototype = {
|
||||
_init: function(docInfo) {
|
||||
this._info = docInfo;
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: DEFAULT_SPACING,
|
||||
reactive: true });
|
||||
this.actor.connect('button-release-event', Lang.bind(this, function () {
|
||||
docInfo.launch();
|
||||
Main.overview.hide();
|
||||
}));
|
||||
|
||||
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
|
||||
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);
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
this.actor._delegate = this;
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this._icon;
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
this.dragActor = this._info.createIcon(DASH_DOCS_ICON_SIZE);
|
||||
return this.dragActor;
|
||||
},
|
||||
|
||||
//// Drag and drop functions ////
|
||||
|
||||
shellWorkspaceLaunch: function () {
|
||||
this._info.launch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class used to display two column recent documents in the dash
|
||||
*/
|
||||
function DashDocDisplay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DashDocDisplay.prototype = {
|
||||
_init: function() {
|
||||
this.actor = new Shell.GenericContainer();
|
||||
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._docManager = DocInfo.getDocManager();
|
||||
this._docManager.connect('changed', Lang.bind(this, function(mgr) {
|
||||
this._redisplay();
|
||||
}));
|
||||
this._redisplay();
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
let children = actor.get_children();
|
||||
|
||||
// We use two columns maximum. Just take the min and natural size of the
|
||||
// first two items, even though strictly speaking it's not correct; we'd
|
||||
// need to calculate how many items we could fit for the height, then
|
||||
// take the biggest preferred width for each column.
|
||||
// In practice the dash gets a fixed width anyways.
|
||||
|
||||
// If we have one child, add its minimum and natural size
|
||||
if (children.length > 0) {
|
||||
let [minSize, naturalSize] = children[0].get_preferred_width(forHeight);
|
||||
alloc.min_size += minSize;
|
||||
alloc.natural_size += naturalSize;
|
||||
}
|
||||
// If we have two, add its size, plus DEFAULT_SPACING
|
||||
if (children.length > 1) {
|
||||
let [minSize, naturalSize] = children[1].get_preferred_width(forHeight);
|
||||
alloc.min_size += DEFAULT_SPACING + minSize;
|
||||
alloc.natural_size += DEFAULT_SPACING + naturalSize;
|
||||
}
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
let children = actor.get_children();
|
||||
|
||||
// Two columns, where we go vertically down first. So just take
|
||||
// the height of half of the children as our preferred height.
|
||||
|
||||
let firstColumnChildren = children.length / 2;
|
||||
|
||||
alloc.min_size = 0;
|
||||
for (let i = 0; i < firstColumnChildren; i++) {
|
||||
let child = children[i];
|
||||
let [minSize, naturalSize] = child.get_preferred_height(forWidth);
|
||||
alloc.natural_size += naturalSize;
|
||||
|
||||
if (i > 0 && i < children.length - 1) {
|
||||
alloc.min_size += DEFAULT_SPACING;
|
||||
alloc.natural_size += DEFAULT_SPACING;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let width = box.x2 - box.x1;
|
||||
let height = box.y2 - box.y1;
|
||||
|
||||
let children = actor.get_children();
|
||||
|
||||
// The width of an item is our allocated width, minus spacing, divided in half.
|
||||
let itemWidth = Math.floor((width - DEFAULT_SPACING) / 2);
|
||||
let x = box.x1;
|
||||
let y = box.y1;
|
||||
let columnIndex = 0;
|
||||
let i = 0;
|
||||
// Loop over the children, going vertically down first. When we run
|
||||
// out of vertical space (our y variable is bigger than box.y2), switch
|
||||
// to the second column.
|
||||
for (; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
|
||||
let [minSize, naturalSize] = child.get_preferred_height(-1);
|
||||
|
||||
if (y + naturalSize > box.y2) {
|
||||
// Is this the second column? Ok, break.
|
||||
if (columnIndex == 1) {
|
||||
break;
|
||||
}
|
||||
// Set x to the halfway point.
|
||||
columnIndex += 1;
|
||||
x = x + itemWidth + DEFAULT_SPACING;
|
||||
// And y is back to the top.
|
||||
y = box.y1;
|
||||
}
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = x;
|
||||
childBox.y1 = y;
|
||||
childBox.x2 = childBox.x1 + itemWidth;
|
||||
childBox.y2 = y + naturalSize;
|
||||
|
||||
y = childBox.y2 + DEFAULT_SPACING;
|
||||
|
||||
child.show();
|
||||
child.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
// Everything else didn't fit, just hide it.
|
||||
for (; i < children.length; i++) {
|
||||
children[i].hide();
|
||||
}
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
this.actor.remove_all();
|
||||
|
||||
let docs = this._docManager.getItems();
|
||||
let docUrls = [];
|
||||
for (let url in docs) {
|
||||
docUrls.push(url);
|
||||
}
|
||||
docUrls.sort(function (urlA, urlB) { return docs[urlB].timestamp - docs[urlA].timestamp; });
|
||||
let textureCache = Shell.TextureCache.get_default();
|
||||
|
||||
for (let i = 0; i < docUrls.length; i++) {
|
||||
let url = docUrls[i];
|
||||
let docInfo = docs[url];
|
||||
let display = new DashDocDisplayItem(docInfo);
|
||||
this.actor.add_actor(display.actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
js/ui/environment.js
Normal file
@ -0,0 +1,32 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Nbtk = imports.gi.Nbtk;
|
||||
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
// "monkey patch" in some varargs ClutterContainer methods; we need
|
||||
// to do this per-container class since there is no representation
|
||||
// of interfaces in Javascript
|
||||
function _patchContainerClass(containerClass) {
|
||||
// This one is a straightforward mapping of the C method
|
||||
containerClass.prototype.child_set = function(actor, props) {
|
||||
let meta = this.get_child_meta(actor);
|
||||
for (prop in props)
|
||||
meta[prop] = props[prop];
|
||||
};
|
||||
|
||||
// clutter_container_add() actually is a an add-many-actors
|
||||
// method. We conveniently, but somewhat dubiously, take the
|
||||
// this opportunity to make it do something more useful.
|
||||
containerClass.prototype.add = function(actor, props) {
|
||||
this.add_actor(actor);
|
||||
if (props)
|
||||
this.child_set(actor, props);
|
||||
};
|
||||
}
|
||||
|
||||
_patchContainerClass(Nbtk.BoxLayout);
|
||||
|
||||
function init() {
|
||||
Tweener.init();
|
||||
}
|
562
js/ui/lookingGlass.js
Normal file
@ -0,0 +1,562 @@
|
||||
/* -*- 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 Pango = imports.gi.Pango;
|
||||
const Nbtk = imports.gi.Nbtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
/* Imports...feel free to add here as needed */
|
||||
var commandHeader = "const Clutter = imports.gi.Clutter; " +
|
||||
"const GLib = imports.gi.GLib; " +
|
||||
"const Gtk = imports.gi.Gtk; " +
|
||||
"const Mainloop = imports.mainloop; " +
|
||||
"const Meta = imports.gi.Meta; " +
|
||||
"const Shell = imports.gi.Shell; " +
|
||||
"const Main = imports.ui.main; " +
|
||||
"const Lang = imports.lang; " +
|
||||
"const Tweener = imports.ui.tweener; " +
|
||||
/* Utility functions...we should probably be able to use these
|
||||
* in the shell core code too. */
|
||||
"const stage = global.stage; " +
|
||||
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
|
||||
/* Special lookingGlass functions */
|
||||
"const it = Main.lookingGlass.getIt(); " +
|
||||
"const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ";
|
||||
|
||||
function Notebook() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Notebook.prototype = {
|
||||
_init: function() {
|
||||
this.actor = new Nbtk.BoxLayout({ vertical: true });
|
||||
|
||||
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: 4, padding: 2 });
|
||||
|
||||
this._selectedIndex = -1;
|
||||
this._tabs = [];
|
||||
},
|
||||
|
||||
appendPage: function(name, child) {
|
||||
let labelOuterBox = new Big.Box({ padding: 2 });
|
||||
let labelBox = new Nbtk.BoxLayout({ reactive: true });
|
||||
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
|
||||
let label = new Nbtk.Label({ text: name });
|
||||
labelBox.connect('button-press-event', Lang.bind(this, function () {
|
||||
this.selectChild(child);
|
||||
return true;
|
||||
}));
|
||||
labelBox.add(label, { expand: true });
|
||||
this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
let scrollview = new Nbtk.ScrollView({ x_fill: true, y_fill: true });
|
||||
scrollview.get_hscroll_bar().hide();
|
||||
scrollview.add_actor(child);
|
||||
|
||||
this._tabs.push([child, labelBox, scrollview]);
|
||||
scrollview.hide();
|
||||
this.actor.add(scrollview, { expand: true });
|
||||
|
||||
if (this._selectedIndex == -1)
|
||||
this.selectIndex(0);
|
||||
},
|
||||
|
||||
_unselect: function() {
|
||||
if (this._selectedIndex < 0)
|
||||
return;
|
||||
let [child, labelBox, scrollview] = this._tabs[this._selectedIndex];
|
||||
labelBox.padding = 2;
|
||||
labelBox.border = 0;
|
||||
scrollview.hide();
|
||||
this._selectedIndex = -1;
|
||||
},
|
||||
|
||||
selectIndex: function(index) {
|
||||
if (index == this._selectedIndex)
|
||||
return;
|
||||
this._unselect();
|
||||
if (index < 0) {
|
||||
this.emit('selection', null);
|
||||
return;
|
||||
}
|
||||
let [child, labelBox, scrollview] = this._tabs[index];
|
||||
labelBox.padding = 1;
|
||||
labelBox.border = 1;
|
||||
scrollview.show();
|
||||
this._selectedIndex = index;
|
||||
this.emit('selection', child);
|
||||
},
|
||||
|
||||
selectChild: function(child) {
|
||||
if (child == null)
|
||||
this.selectIndex(-1);
|
||||
else {
|
||||
for (let i = 0; i < this._tabs.length; i++) {
|
||||
let [tabChild, labelBox, scrollview] = this._tabs[i];
|
||||
if (tabChild == child) {
|
||||
this.selectIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Signals.addSignalMethods(Notebook.prototype);
|
||||
|
||||
function Result(command, o, index) {
|
||||
this._init(command, o, index);
|
||||
}
|
||||
|
||||
Result.prototype = {
|
||||
_init : function(command, o, index) {
|
||||
this.index = index;
|
||||
this.o = o;
|
||||
|
||||
this.actor = new Big.Box();
|
||||
|
||||
let cmdTxt = new Nbtk.Label({ text: command });
|
||||
cmdTxt.ellipsize = Pango.EllipsizeMode.END;
|
||||
|
||||
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
|
||||
let resultTxt = new Nbtk.Label({ text: "r(" + index + ") = " + o });
|
||||
resultTxt.ellipsize = Pango.EllipsizeMode.END;
|
||||
|
||||
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
|
||||
let line = new Clutter.Rectangle({ name: "Separator",
|
||||
height: 1 });
|
||||
let padBin = new Nbtk.Bin({ name: "Separator", x_fill: true, y_fill: true });
|
||||
padBin.add_actor(line);
|
||||
this.actor.append(padBin, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
function ActorHierarchy() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
ActorHierarchy.prototype = {
|
||||
_init : function () {
|
||||
this._previousTarget = null;
|
||||
this._target = null;
|
||||
|
||||
this._parentList = [];
|
||||
|
||||
this.actor = new Nbtk.BoxLayout({ name: "ActorHierarchy", vertical: true });
|
||||
},
|
||||
|
||||
setTarget: function(actor) {
|
||||
this._previousTarget = this._target;
|
||||
this.target = actor;
|
||||
|
||||
this.actor.get_children().forEach(function (child) { child.destroy(); });
|
||||
|
||||
if (!(actor instanceof Clutter.Actor))
|
||||
return;
|
||||
|
||||
if (this.target == null)
|
||||
return;
|
||||
|
||||
this._parentList = [];
|
||||
let parent = actor;
|
||||
while ((parent = parent.get_parent()) != null) {
|
||||
this._parentList.push(parent);
|
||||
|
||||
let link = new Nbtk.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);
|
||||
},
|
||||
|
||||
_selectByActor: function(actor) {
|
||||
let idx = this._parentList.indexOf(actor);
|
||||
let children = this.actor.get_children();
|
||||
let link = children[idx];
|
||||
this.emit('selection', actor);
|
||||
}
|
||||
}
|
||||
Signals.addSignalMethods(ActorHierarchy.prototype);
|
||||
|
||||
function PropertyInspector() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
PropertyInspector.prototype = {
|
||||
_init : function () {
|
||||
this._target = null;
|
||||
|
||||
this._parentList = [];
|
||||
|
||||
this.actor = new Nbtk.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 Nbtk.Label({ reactive: true,
|
||||
text: propText });
|
||||
this.actor.add_actor(propDisplay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Inspector() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Inspector.prototype = {
|
||||
_init: function() {
|
||||
let width = 150;
|
||||
let eventHandler = new Nbtk.BoxLayout({ name: "LookingGlassDialog",
|
||||
vertical: false,
|
||||
y: Math.floor(global.stage.height/2),
|
||||
reactive: true });
|
||||
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
|
||||
eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2);
|
||||
}));
|
||||
global.stage.add_actor(eventHandler);
|
||||
let displayText = new Nbtk.Label();
|
||||
eventHandler.add(displayText, { expand: true });
|
||||
|
||||
let borderPaintTarget = null;
|
||||
let borderPaintId = null;
|
||||
eventHandler.connect('destroy', Lang.bind(this, function() {
|
||||
if (borderPaintTarget != null)
|
||||
borderPaintTarget.disconnect(borderPaintId);
|
||||
}));
|
||||
|
||||
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
|
||||
Clutter.ungrab_pointer(eventHandler);
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
||||
stageX,
|
||||
stageY);
|
||||
this.emit('target', target, stageX, stageY);
|
||||
eventHandler.destroy();
|
||||
this.emit('closed');
|
||||
return true;
|
||||
}));
|
||||
|
||||
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
||||
stageX,
|
||||
stageY);
|
||||
displayText.text = '<inspect x: ' + stageX + ' y: ' + stageY + '> ' + target;
|
||||
if (borderPaintTarget != null)
|
||||
borderPaintTarget.disconnect(borderPaintId);
|
||||
borderPaintTarget = target;
|
||||
borderPaintId = Shell.add_hook_paint_red_border(target);
|
||||
return true;
|
||||
}));
|
||||
Clutter.grab_pointer(eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(Inspector.prototype);
|
||||
|
||||
function LookingGlass() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
LookingGlass.prototype = {
|
||||
_init : function() {
|
||||
this._idleHistorySaveId = 0;
|
||||
let historyPath = global.configdir + "/lookingglass-history.txt";
|
||||
this._historyFile = Gio.file_new_for_path(historyPath);
|
||||
this._savedText = null;
|
||||
this._historyNavIndex = -1;
|
||||
this._history = [];
|
||||
this._readHistory();
|
||||
|
||||
this._open = false;
|
||||
|
||||
this._offset = 0;
|
||||
this._results = [];
|
||||
|
||||
// Sort of magic, but...eh.
|
||||
this._maxItems = 150;
|
||||
|
||||
this.actor = new Nbtk.BoxLayout({ name: "LookingGlassDialog",
|
||||
vertical: true,
|
||||
visible: false });
|
||||
|
||||
let gconf = Shell.GConf.get_default();
|
||||
gconf.watch_directory("/desktop/gnome/interface");
|
||||
gconf.connect("changed::/desktop/gnome/interface/monospace_font_name",
|
||||
Lang.bind(this, this._updateFont));
|
||||
this._updateFont();
|
||||
|
||||
global.stage.add_actor(this.actor);
|
||||
|
||||
let toolbar = new Nbtk.BoxLayout({ name: "Toolbar" });
|
||||
this.actor.add_actor(toolbar);
|
||||
let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
|
||||
24);
|
||||
toolbar.add_actor(inspectIcon);
|
||||
inspectIcon.reactive = true;
|
||||
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
|
||||
let inspector = new Inspector();
|
||||
inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
|
||||
this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
|
||||
target);
|
||||
this._hierarchy.setTarget(target);
|
||||
}));
|
||||
inspector.connect('closed', Lang.bind(this, function() {
|
||||
this.actor.show();
|
||||
global.stage.set_key_focus(this._entry);
|
||||
}));
|
||||
this.actor.hide();
|
||||
return true;
|
||||
}));
|
||||
|
||||
let notebook = new Notebook();
|
||||
this.actor.add(notebook.actor, { expand: true });
|
||||
|
||||
let emptyBox = new Nbtk.Bin();
|
||||
toolbar.add(emptyBox, { expand: true });
|
||||
toolbar.add_actor(notebook.tabControls);
|
||||
|
||||
this._evalBox = new Nbtk.BoxLayout({ name: "EvalBox", vertical: true });
|
||||
notebook.appendPage('Evaluator', this._evalBox);
|
||||
|
||||
this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
spacing: 4 });
|
||||
this._evalBox.add(this._resultsArea, { expand: true });
|
||||
|
||||
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||
this._evalBox.add_actor(entryArea);
|
||||
|
||||
let label = new Nbtk.Label({ text: 'js>>> ' });
|
||||
entryArea.append(label, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._entry = new Nbtk.Entry();
|
||||
/* unmapping the edit box will un-focus it, undo that */
|
||||
notebook.connect('selection', Lang.bind(this, function (nb, child) {
|
||||
if (child == this._evalBox)
|
||||
global.stage.set_key_focus(this._entry);
|
||||
}));
|
||||
entryArea.append(this._entry, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._hierarchy = new ActorHierarchy();
|
||||
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);
|
||||
}));
|
||||
|
||||
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
|
||||
let text = o.get_text();
|
||||
// Ensure we don't get newlines in the command; the history file is
|
||||
// newline-separated.
|
||||
text.replace('\n', ' ');
|
||||
// Strip leading and trailing whitespace
|
||||
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
||||
if (text == '')
|
||||
return true;
|
||||
this._evaluate(text);
|
||||
this._historyNavIndex = -1;
|
||||
return true;
|
||||
}));
|
||||
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
this.close();
|
||||
return true;
|
||||
} else if (symbol == Clutter.Up) {
|
||||
if (this._historyNavIndex >= this._history.length - 1)
|
||||
return true;
|
||||
this._historyNavIndex++;
|
||||
if (this._historyNavIndex == 0)
|
||||
this._savedText = this._entry.text;
|
||||
this._entry.text = this._history[this._history.length - this._historyNavIndex - 1];
|
||||
return true;
|
||||
} else if (symbol == Clutter.Down) {
|
||||
if (this._historyNavIndex <= 0)
|
||||
return true;
|
||||
this._historyNavIndex--;
|
||||
if (this._historyNavIndex < 0)
|
||||
this._entry.text = this._savedText;
|
||||
else
|
||||
this._entry.text = this._history[this._history.length - this._historyNavIndex - 1];
|
||||
return true;
|
||||
} else {
|
||||
this._historyNavIndex = -1;
|
||||
this._savedText = null;
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_updateFont: function() {
|
||||
let gconf = Shell.GConf.get_default();
|
||||
let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name");
|
||||
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
|
||||
let fontDesc = Pango.Font.description_from_string(fontName);
|
||||
// We ignore everything but size and style; you'd be crazy to set your system-wide
|
||||
// monospace font to be bold/oblique/etc. Could easily be added here.
|
||||
this.actor.style =
|
||||
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
|
||||
+ 'font-family: "' + fontDesc.get_family() + '";';
|
||||
},
|
||||
|
||||
_readHistory: function () {
|
||||
if (!this._historyFile.query_exists(null))
|
||||
return;
|
||||
let [result, contents, length, etag] = this._historyFile.load_contents(null);
|
||||
this._history = contents.split('\n').filter(function (e) { return e != ''; });
|
||||
},
|
||||
|
||||
_queueHistorySave: function() {
|
||||
if (this._idleHistorySaveId > 0)
|
||||
return;
|
||||
this._idleHistorySaveId = Mainloop.timeout_add_seconds(5, Lang.bind(this, this._doSaveHistory));
|
||||
},
|
||||
|
||||
_doSaveHistory: function () {
|
||||
this._idleHistorySaveId = false;
|
||||
let output = this._historyFile.replace(null, true, Gio.FileCreateFlags.NONE, null);
|
||||
let dataOut = new Gio.DataOutputStream({ base_stream: output });
|
||||
dataOut.put_string(this._history.join('\n'), null);
|
||||
dataOut.put_string('\n', null);
|
||||
dataOut.close(null);
|
||||
return false;
|
||||
},
|
||||
|
||||
_pushResult: function(command, obj) {
|
||||
let index = this._results.length + this._offset;
|
||||
let result = new Result('>>> ' + command, obj, index);
|
||||
this._results.push(result);
|
||||
this._resultsArea.append(result.actor, Big.BoxPackFlags.NONE);
|
||||
this._propInspector.setTarget(obj);
|
||||
let children = this._resultsArea.get_children();
|
||||
if (children.length > this._maxItems) {
|
||||
this._results.shift();
|
||||
children[0].destroy();
|
||||
this._offset++;
|
||||
}
|
||||
this._it = obj;
|
||||
},
|
||||
|
||||
_evaluate : function(command) {
|
||||
this._history.push(command);
|
||||
this._queueHistorySave();
|
||||
|
||||
let fullCmd = commandHeader + command;
|
||||
|
||||
let resultObj;
|
||||
try {
|
||||
resultObj = eval(fullCmd);
|
||||
} catch (e) {
|
||||
resultObj = "<exception " + e + ">";
|
||||
}
|
||||
|
||||
this._pushResult(command, resultObj);
|
||||
this._hierarchy.setTarget(null);
|
||||
this._entry.text = '';
|
||||
},
|
||||
|
||||
getIt: function () {
|
||||
return this._it;
|
||||
},
|
||||
|
||||
getResult: function(idx) {
|
||||
return this._results[idx - this._offset].o;
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
if (this._open)
|
||||
this.close();
|
||||
else
|
||||
this.open();
|
||||
},
|
||||
|
||||
_resizeTo: function(actor) {
|
||||
let stage = global.stage;
|
||||
let myWidth = stage.width * 0.7;
|
||||
let myHeight = stage.height * 0.7;
|
||||
let [srcX, srcY] = actor.get_transformed_position();
|
||||
this.actor.x = srcX + (stage.width-myWidth)/2;
|
||||
this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners
|
||||
this._targetY = this._hiddenY + myHeight;
|
||||
this.actor.y = this._hiddenY;
|
||||
this.actor.width = myWidth;
|
||||
this.actor.height = myHeight;
|
||||
},
|
||||
|
||||
slaveTo: function(actor) {
|
||||
this._slaveTo = actor;
|
||||
actor.connect('notify::allocation', Lang.bind(this, function () {
|
||||
this._resizeTo(actor);
|
||||
}));
|
||||
this._resizeTo(actor);
|
||||
},
|
||||
|
||||
open : function() {
|
||||
if (this._open)
|
||||
return;
|
||||
|
||||
this.actor.show();
|
||||
this.actor.lower(Main.chrome.actor);
|
||||
this._open = true;
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
|
||||
Main.pushModal(this.actor);
|
||||
global.stage.set_key_focus(this._entry);
|
||||
|
||||
Tweener.addTween(this.actor, { time: 0.5,
|
||||
transition: "easeOutQuad",
|
||||
y: this._targetY
|
||||
});
|
||||
},
|
||||
|
||||
close : function() {
|
||||
if (!this._open)
|
||||
return;
|
||||
|
||||
this._historyNavIndex = -1;
|
||||
this._open = false;
|
||||
Tweener.removeTweens(this.actor);
|
||||
|
||||
Main.popModal(this.actor);
|
||||
|
||||
Tweener.addTween(this.actor, { time: 0.5,
|
||||
transition: "easeOutQuad",
|
||||
y: this._hiddenY,
|
||||
onComplete: Lang.bind(this, function () {
|
||||
this.actor.hide();
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(LookingGlass.prototype);
|
231
js/ui/main.js
@ -3,18 +3,21 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Nbtk = imports.gi.Nbtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Chrome = imports.ui.chrome;
|
||||
const Overlay = imports.ui.overlay;
|
||||
const Environment = imports.ui.environment;
|
||||
const Overview = imports.ui.overview;
|
||||
const Panel = imports.ui.panel;
|
||||
const RunDialog = imports.ui.runDialog;
|
||||
const LookingGlass = imports.ui.lookingGlass;
|
||||
const Sidebar = imports.ui.sidebar;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const WindowManager = imports.ui.windowManager;
|
||||
|
||||
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
|
||||
@ -23,21 +26,35 @@ DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
|
||||
let chrome = null;
|
||||
let panel = null;
|
||||
let sidebar = null;
|
||||
let overlay = null;
|
||||
let overview = null;
|
||||
let runDialog = null;
|
||||
let lookingGlass = null;
|
||||
let wm = null;
|
||||
let recorder = null;
|
||||
let inModal = false;
|
||||
let modalCount = 0;
|
||||
let modalActorFocusStack = [];
|
||||
|
||||
function start() {
|
||||
let global = Shell.Global.get();
|
||||
// Add a binding for "global" in the global JS namespace; (gjs
|
||||
// keeps the web browser convention of having that namespace be
|
||||
// called "window".)
|
||||
window.global = Shell.Global.get();
|
||||
|
||||
Gio.DesktopAppInfo.set_desktop_env("GNOME");
|
||||
|
||||
global.grab_dbus_service();
|
||||
global.start_task_panel();
|
||||
|
||||
Tweener.init();
|
||||
Environment.init();
|
||||
|
||||
// Ensure ShellAppMonitor is initialized; this will
|
||||
// also initialize ShellAppSystem first. ShellAppSystem
|
||||
// needs to load all the .desktop files, and ShellAppMonitor
|
||||
// will use those to associate with windows. Right now
|
||||
// the Monitor doesn't listen for installed app changes
|
||||
// and recalculate application associations, so to avoid
|
||||
// races for now we initialize it here. It's better to
|
||||
// be predictable anyways.
|
||||
Shell.AppMonitor.get_default();
|
||||
|
||||
// The background color really only matters if there is no desktop
|
||||
// window (say, nautilus) running. We set it mostly so things look good
|
||||
@ -45,39 +62,29 @@ function start() {
|
||||
global.stage.color = DEFAULT_BACKGROUND_COLOR;
|
||||
|
||||
// Mutter currently hardcodes putting "Yessir. The compositor is running""
|
||||
// in the overlay. Clear that out.
|
||||
// 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 = Shell.ThemeContext.get_for_stage (global.stage);
|
||||
let stylesheetPath = global.datadir + "/theme/gnome-shell.css";
|
||||
let theme = new Shell.Theme ({ application_stylesheet: stylesheetPath });
|
||||
themeContext.set_theme (theme);
|
||||
|
||||
global.connect('panel-run-dialog', function(panel) {
|
||||
// Make sure not more than one run dialog is shown.
|
||||
if (!runDialog) {
|
||||
runDialog = new RunDialog.RunDialog();
|
||||
let endHandler = function() {
|
||||
runDialog.destroy();
|
||||
runDialog = null;
|
||||
};
|
||||
runDialog.connect('run', endHandler);
|
||||
runDialog.connect('cancel', endHandler);
|
||||
if (!runDialog.show())
|
||||
endHandler();
|
||||
}
|
||||
getRunDialog().open();
|
||||
});
|
||||
|
||||
overlay = new Overlay.Overlay();
|
||||
overview = new Overview.Overview();
|
||||
chrome = new Chrome.Chrome();
|
||||
panel = new Panel.Panel();
|
||||
sidebar = new Sidebar.Sidebar();
|
||||
wm = new WindowManager.WindowManager();
|
||||
|
||||
|
||||
global.screen.connect('toggle-recording', function() {
|
||||
if (recorder == null) {
|
||||
// We have to initialize GStreamer first. This isn't done
|
||||
// inside ShellRecorder to make it usable inside projects
|
||||
// with other usage of GStreamer.
|
||||
let Gst = imports.gi.Gst;
|
||||
Gst.init(null, null);
|
||||
recorder = new Shell.Recorder({ stage: global.stage });
|
||||
}
|
||||
|
||||
@ -88,13 +95,24 @@ function start() {
|
||||
}
|
||||
});
|
||||
|
||||
_relayout();
|
||||
|
||||
panel.startupAnimation();
|
||||
|
||||
let display = global.screen.get_display();
|
||||
display.connect('overlay-key', Lang.bind(overlay, overlay.toggle));
|
||||
global.connect('panel-main-menu', Lang.bind(overlay, overlay.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);
|
||||
|
||||
Mainloop.idle_add(_removeUnusedWorkspaces);
|
||||
}
|
||||
|
||||
function _relayout() {
|
||||
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
|
||||
overview.relayout();
|
||||
}
|
||||
|
||||
// metacity-clutter currently uses the same prefs as plain metacity,
|
||||
// which probably means we'll be starting out with multiple workspaces;
|
||||
// remove any unused ones. (We do this from an idle handler, because
|
||||
@ -102,8 +120,6 @@ function start() {
|
||||
// is called.)
|
||||
function _removeUnusedWorkspaces() {
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
let windows = global.get_windows();
|
||||
let maxWorkspace = 0;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
@ -125,31 +141,154 @@ function _removeUnusedWorkspaces() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Used to go into a mode where all keyboard and mouse input goes to
|
||||
// the stage. Returns true if we successfully grabbed the keyboard and
|
||||
// went modal, false otherwise
|
||||
function startModal() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
if (!global.grab_keyboard())
|
||||
// This function encapsulates hacks to make certain global keybindings
|
||||
// work even when we are in one of our modes where global keybindings
|
||||
// are disabled with a global grab. (When there is a global grab, then
|
||||
// all key events will be delivered to the stage, so ::captured-event
|
||||
// on the stage can be used for global keybindings.)
|
||||
//
|
||||
// We expect to need to conditionally enable just a few keybindings
|
||||
// depending on circumstance; the main hackiness here is that we are
|
||||
// assuming that keybindings have their default values; really we
|
||||
// should be asking Mutter to resolve the key into an action and then
|
||||
// base our handling based on the action.
|
||||
function _globalKeyPressHandler(actor, event) {
|
||||
if (modalCount == 0)
|
||||
return false;
|
||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
||||
|
||||
inModal = true;
|
||||
let type = event.type();
|
||||
|
||||
return true;
|
||||
if (type == Clutter.EventType.KEY_PRESS) {
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.Print) {
|
||||
// We want to be able to take screenshots of the shell at all times
|
||||
let gconf = Shell.GConf.get_default();
|
||||
let command = gconf.get_string("/apps/metacity/keybinding_commands/command_screenshot");
|
||||
if (command != null && command != "") {
|
||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||
let p = new Shell.Process({'args' : args});
|
||||
p.run();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} else if (type == Clutter.EventType.KEY_RELEASE) {
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
|
||||
// The super key is the default for triggering the overview, and should
|
||||
// get us out of the overview when we are already in it.
|
||||
if (overview.visible)
|
||||
overview.hide();
|
||||
|
||||
return true;
|
||||
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
|
||||
getRunDialog().open();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function endModal() {
|
||||
let global = Shell.Global.get();
|
||||
function _findModal(actor) {
|
||||
for (let i = 0; i < modalActorFocusStack.length; i++) {
|
||||
let [stackActor, stackFocus] = modalActorFocusStack[i];
|
||||
if (stackActor == actor) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
global.ungrab_keyboard();
|
||||
/**
|
||||
* pushModal:
|
||||
* @actor: #ClutterActor which will be given keyboard focus
|
||||
*
|
||||
* Ensure we are in a mode where all keyboard and mouse input goes to
|
||||
* the stage. Multiple calls to this function act in a stacking fashion;
|
||||
* the effect will be undone when an equal number of popModal() invocations
|
||||
* have been made.
|
||||
*
|
||||
* Next, record the current Clutter keyboard focus on a stack. If the modal stack
|
||||
* returns to this actor, reset the focus to the actor which was focused
|
||||
* at the time pushModal() was invoked.
|
||||
*/
|
||||
function pushModal(actor) {
|
||||
let timestamp = global.screen.get_display().get_current_time();
|
||||
|
||||
modalCount += 1;
|
||||
actor.connect('destroy', function() {
|
||||
let index = _findModal(actor);
|
||||
if (index >= 0)
|
||||
modalActorFocusStack.splice(index, 1);
|
||||
});
|
||||
let curFocus = global.stage.get_key_focus();
|
||||
if (curFocus != null) {
|
||||
curFocus.connect('destroy', function() {
|
||||
let index = _findModal(actor);
|
||||
if (index >= 0)
|
||||
modalActorFocusStack[index][1] = null;
|
||||
});
|
||||
}
|
||||
modalActorFocusStack.push([actor, curFocus]);
|
||||
|
||||
if (modalCount > 1)
|
||||
return;
|
||||
|
||||
if (!global.begin_modal(timestamp)) {
|
||||
log("pushModal: invocation of begin_modal failed");
|
||||
return;
|
||||
}
|
||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* popModal:
|
||||
* @actor: #ClutterActor passed to original invocation of pushModal().
|
||||
*
|
||||
* Reverse the effect of pushModal(). If this invocation is undoing
|
||||
* the topmost invocation, then the focus will be restored to the
|
||||
* previous focus at the time when pushModal() was invoked.
|
||||
*/
|
||||
function popModal(actor) {
|
||||
let timestamp = global.screen.get_display().get_current_time();
|
||||
|
||||
modalCount -= 1;
|
||||
let focusIndex = _findModal(actor);
|
||||
if (focusIndex >= 0) {
|
||||
if (focusIndex == modalActorFocusStack.length - 1) {
|
||||
let [stackActor, stackFocus] = modalActorFocusStack[focusIndex];
|
||||
global.stage.set_key_focus(stackFocus);
|
||||
} else {
|
||||
// Remove from the middle, shift the focus chain up
|
||||
for (let i = focusIndex; i < modalActorFocusStack.length - 1; i++) {
|
||||
modalActorFocusStack[i + 1][1] = modalActorFocusStack[i][1];
|
||||
}
|
||||
}
|
||||
modalActorFocusStack.splice(focusIndex, 1);
|
||||
}
|
||||
if (modalCount > 0)
|
||||
return;
|
||||
|
||||
global.end_modal(timestamp);
|
||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||
inModal = false;
|
||||
}
|
||||
|
||||
function createLookingGlass() {
|
||||
if (lookingGlass == null) {
|
||||
lookingGlass = new LookingGlass.LookingGlass();
|
||||
lookingGlass.slaveTo(panel.actor);
|
||||
}
|
||||
return lookingGlass;
|
||||
}
|
||||
|
||||
function getRunDialog() {
|
||||
if (runDialog == null) {
|
||||
runDialog = new RunDialog.RunDialog();
|
||||
}
|
||||
return runDialog;
|
||||
}
|
||||
|
||||
function createAppLaunchContext() {
|
||||
let global = Shell.Global.get();
|
||||
let screen = global.screen;
|
||||
let display = screen.get_display();
|
||||
|
||||
|
975
js/ui/overlay.js
@ -1,975 +0,0 @@
|
||||
/* -*- 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 Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const DocDisplay = imports.ui.docDisplay;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Link = imports.ui.link;
|
||||
const Main = imports.ui.main;
|
||||
const Panel = imports.ui.panel;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Workspaces = imports.ui.workspaces;
|
||||
|
||||
const ROOT_OVERLAY_COLOR = new Clutter.Color();
|
||||
ROOT_OVERLAY_COLOR.from_pixel(0x000000bb);
|
||||
|
||||
// The factor to scale the overlay wallpaper with. This should not be less
|
||||
// than 3/2, because the rule of thirds is used for positioning (see below).
|
||||
const BACKGROUND_SCALE = 2;
|
||||
|
||||
const LABEL_HEIGHT = 16;
|
||||
// We use SIDESHOW_PAD for the padding on the left side of the sideshow and as a gap
|
||||
// between sideshow columns.
|
||||
const SIDESHOW_PAD = 6;
|
||||
const SIDESHOW_MIN_WIDTH = 250;
|
||||
const SIDESHOW_SECTION_PADDING_TOP = 6;
|
||||
const SIDESHOW_SECTION_SPACING = 6;
|
||||
const SIDESHOW_COLUMNS = 1;
|
||||
const DETAILS_CORNER_RADIUS = 5;
|
||||
const DETAILS_BORDER_WIDTH = 1;
|
||||
const DETAILS_PADDING = 6;
|
||||
// This is the height of section components other than the item display.
|
||||
const SIDESHOW_SECTION_MISC_HEIGHT = (LABEL_HEIGHT + SIDESHOW_SECTION_SPACING) * 2 + SIDESHOW_SECTION_PADDING_TOP;
|
||||
const SIDESHOW_SEARCH_BG_COLOR = new Clutter.Color();
|
||||
SIDESHOW_SEARCH_BG_COLOR.from_pixel(0xffffffff);
|
||||
const SIDESHOW_TEXT_COLOR = new Clutter.Color();
|
||||
SIDESHOW_TEXT_COLOR.from_pixel(0xffffffff);
|
||||
const DETAILS_BORDER_COLOR = new Clutter.Color();
|
||||
DETAILS_BORDER_COLOR.from_pixel(0xffffffff);
|
||||
|
||||
// Time for initial animation going into overlay mode
|
||||
const ANIMATION_TIME = 0.25;
|
||||
|
||||
// We divide the screen into a grid of rows and columns, which we use
|
||||
// to help us position the overlay components, such as the side panel
|
||||
// that lists applications and documents, the workspaces display, and
|
||||
// the button for adding additional workspaces.
|
||||
// In the regular mode, the side panel takes up one column on the left,
|
||||
// and the workspaces display takes up the remaining columns.
|
||||
// In the expanded side panel display mode, the side panel takes up two
|
||||
// columns, and the workspaces display slides all the way to the right,
|
||||
// being visible only in the last quarter of the right-most column.
|
||||
// In the future, this mode will have more components, such as a display
|
||||
// of documents which were recently opened with a given application, which
|
||||
// will take up the remaining sections of the display.
|
||||
|
||||
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
|
||||
|
||||
const COLUMNS_REGULAR_SCREEN = 4;
|
||||
const ROWS_REGULAR_SCREEN = 8;
|
||||
const COLUMNS_WIDE_SCREEN = 5;
|
||||
const ROWS_WIDE_SCREEN = 10;
|
||||
|
||||
// Padding around workspace grid / Spacing between Sideshow and Workspaces
|
||||
const WORKSPACE_GRID_PADDING = 12;
|
||||
|
||||
const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
|
||||
const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6;
|
||||
const WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN = 4 - 0.25;
|
||||
const EXPANDED_SIDESHOW_COLUMNS_REGULAR_SCREEN = 2;
|
||||
|
||||
const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
|
||||
const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8;
|
||||
const WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN = 5 - 0.25;
|
||||
const EXPANDED_SIDESHOW_COLUMNS_WIDE_SCREEN = 3;
|
||||
|
||||
// A multi-state; PENDING is used during animations
|
||||
const STATE_ACTIVE = true;
|
||||
const STATE_PENDING_INACTIVE = false;
|
||||
const STATE_INACTIVE = false;
|
||||
|
||||
let wideScreen = false;
|
||||
let displayGridColumnWidth = null;
|
||||
let displayGridRowHeight = null;
|
||||
|
||||
function SearchEntry(width) {
|
||||
this._init(width);
|
||||
}
|
||||
|
||||
SearchEntry.prototype = {
|
||||
_init : function(width) {
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
background_color: SIDESHOW_SEARCH_BG_COLOR,
|
||||
corner_radius: 4,
|
||||
spacing: 4,
|
||||
padding_left: 4,
|
||||
padding_right: 4,
|
||||
width: width,
|
||||
height: 24
|
||||
});
|
||||
|
||||
let icontheme = Gtk.IconTheme.get_default();
|
||||
let searchIconTexture = new Clutter.Texture({});
|
||||
let searchIconPath = icontheme.lookup_icon('gtk-find', 16, 0).get_filename();
|
||||
searchIconTexture.set_from_file(searchIconPath);
|
||||
this.actor.append(searchIconTexture, 0);
|
||||
|
||||
// We need to initialize the text for the entry to have the cursor displayed
|
||||
// in it. See http://bugzilla.openedhand.com/show_bug.cgi?id=1365
|
||||
this.entry = new Clutter.Text({ font_name: "Sans 14px",
|
||||
editable: true,
|
||||
activatable: true,
|
||||
singleLineMode: true,
|
||||
text: ""
|
||||
});
|
||||
this.entry.connect('text-changed', Lang.bind(this, function (e) {
|
||||
let text = this.entry.text;
|
||||
}));
|
||||
this.actor.append(this.entry, Big.BoxPackFlags.EXPAND);
|
||||
}
|
||||
};
|
||||
|
||||
function Sideshow() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Sideshow.prototype = {
|
||||
_init : function() {
|
||||
let me = this;
|
||||
|
||||
this._moreAppsMode = STATE_INACTIVE;
|
||||
this._moreDocsMode = STATE_INACTIVE;
|
||||
|
||||
let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN;
|
||||
this._expandedSideshowColumns = wideScreen ? EXPANDED_SIDESHOW_COLUMNS_WIDE_SCREEN : EXPANDED_SIDESHOW_COLUMNS_REGULAR_SCREEN;
|
||||
|
||||
this._width = displayGridColumnWidth;
|
||||
this._displayWidth = this._width - SIDESHOW_PAD;
|
||||
|
||||
this._expandedWidth = displayGridColumnWidth * asideXFactor;
|
||||
|
||||
// this figures out the additional width we can give to the display in the 'More' mode,
|
||||
// assuming that we want to keep the columns the same width in both modes
|
||||
this._additionalWidth = (this._width / SIDESHOW_COLUMNS) *
|
||||
(this._expandedSideshowColumns - SIDESHOW_COLUMNS);
|
||||
|
||||
let bottomHeight = displayGridRowHeight / 2;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
let previewWidth = this._expandedWidth - this._width -
|
||||
this._additionalWidth - SIDESHOW_SECTION_SPACING;
|
||||
|
||||
let previewHeight = global.screen_height - Panel.PANEL_HEIGHT - SIDESHOW_PAD - bottomHeight;
|
||||
|
||||
this.actor = new Clutter.Group();
|
||||
this.actor.height = global.screen_height;
|
||||
this._searchEntry = new SearchEntry(this._displayWidth);
|
||||
this.actor.add_actor(this._searchEntry.actor);
|
||||
|
||||
this._searchEntry.actor.set_position(SIDESHOW_PAD, Panel.PANEL_HEIGHT + SIDESHOW_PAD);
|
||||
|
||||
this._searchQueued = false;
|
||||
this._searchEntry.entry.connect('text-changed', function (se, prop) {
|
||||
if (me._searchQueued)
|
||||
return;
|
||||
me._searchQueued = true;
|
||||
Mainloop.timeout_add(250, function() {
|
||||
// Strip leading and trailing whitespace
|
||||
let text = me._searchEntry.entry.text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
||||
me._searchQueued = false;
|
||||
me._appDisplay.setSearch(text);
|
||||
me._docDisplay.setSearch(text);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
this._searchEntry.entry.connect('activate', function (se) {
|
||||
// only one of the displays will have an item selected, so it's ok to
|
||||
// call activateSelected() on both of them
|
||||
me._appDisplay.activateSelected();
|
||||
me._docDisplay.activateSelected();
|
||||
return true;
|
||||
});
|
||||
this._searchEntry.entry.connect('key-press-event', function (se, e) {
|
||||
let symbol = Shell.get_event_key_symbol(e);
|
||||
if (symbol == Clutter.Escape) {
|
||||
// We always want to hide the previews when the user hits Escape.
|
||||
// If something that should have a preview gets displayed under
|
||||
// the mouse pointer afterwards the preview will get redisplayed.
|
||||
me._appDisplay.hidePreview();
|
||||
me._docDisplay.hidePreview();
|
||||
// Escape will keep clearing things back to the desktop. First, if
|
||||
// we have active text, we remove it.
|
||||
if (me._searchEntry.text != '')
|
||||
me._searchEntry.text = '';
|
||||
// Next, if we're in one of the "more" modes, close it
|
||||
else if (me._moreAppsMode)
|
||||
me._unsetMoreAppsMode();
|
||||
else if (me._moreDocsMode)
|
||||
me._unsetMoreDocsMode();
|
||||
else
|
||||
// Finally, just close the overlay entirely
|
||||
me.emit('activated');
|
||||
return true;
|
||||
} else if (symbol == Clutter.Up) {
|
||||
// selectUp and selectDown wrap around in their respective displays
|
||||
// too, but there doesn't seem to be any flickering if we first select
|
||||
// something in one display, but then unset the selection, and move
|
||||
// it to the other display, so it's ok to do that.
|
||||
if (me._moreAppsMode)
|
||||
me._appDisplay.selectUp();
|
||||
else if (me._moreDocsMode)
|
||||
me._docDisplay.selectUp();
|
||||
else if (me._appDisplay.hasSelected() && !me._appDisplay.selectUp() && me._docDisplay.hasItems()) {
|
||||
me._appDisplay.unsetSelected();
|
||||
me._docDisplay.selectLastItem();
|
||||
} else if (me._docDisplay.hasSelected() && !me._docDisplay.selectUp() && me._appDisplay.hasItems()) {
|
||||
me._docDisplay.unsetSelected();
|
||||
me._appDisplay.selectLastItem();
|
||||
}
|
||||
return true;
|
||||
} else if (symbol == Clutter.Down) {
|
||||
if (me._moreAppsMode)
|
||||
me._appDisplay.selectDown();
|
||||
else if (me._moreDocsMode)
|
||||
me._docDisplay.selectDown();
|
||||
else if (me._appDisplay.hasSelected() && !me._appDisplay.selectDown() && me._docDisplay.hasItems()) {
|
||||
me._appDisplay.unsetSelected();
|
||||
me._docDisplay.selectFirstItem();
|
||||
} else if (me._docDisplay.hasSelected() && !me._docDisplay.selectDown() && me._appDisplay.hasItems()) {
|
||||
me._docDisplay.unsetSelected();
|
||||
me._appDisplay.selectFirstItem();
|
||||
}
|
||||
return true;
|
||||
} else if (me._moreAppsMode && me._searchEntry.text == '') {
|
||||
if (symbol == Clutter.Right) {
|
||||
me._appDisplay.moveRight();
|
||||
return true;
|
||||
} else if (symbol == Clutter.Left) {
|
||||
me._appDisplay.moveLeft();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else if (symbol == Clutter.Right && me._searchEntry.text == '') {
|
||||
if (me._appDisplay.hasSelected())
|
||||
me._setMoreAppsMode();
|
||||
else
|
||||
me._setMoreDocsMode();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this._appsSection = new Big.Box({ x: SIDESHOW_PAD,
|
||||
y: this._searchEntry.actor.y + this._searchEntry.actor.height,
|
||||
padding_top: SIDESHOW_SECTION_PADDING_TOP,
|
||||
spacing: SIDESHOW_SECTION_SPACING});
|
||||
|
||||
this._appsText = new Clutter.Text({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "Applications",
|
||||
height: LABEL_HEIGHT});
|
||||
this._appsSection.append(this._appsText, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._itemDisplayHeight = global.screen_height - this._appsSection.y - SIDESHOW_SECTION_MISC_HEIGHT * 2 - bottomHeight;
|
||||
|
||||
this._appsContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||
this._appsSection.append(this._appsContent, Big.BoxPackFlags.EXPAND);
|
||||
this._appDisplay = new AppDisplay.AppDisplay(this._displayWidth, this._itemDisplayHeight / 2, SIDESHOW_COLUMNS, SIDESHOW_PAD);
|
||||
let sideArea = this._appDisplay.getSideArea();
|
||||
sideArea.hide();
|
||||
this._appsContent.append(sideArea, Big.BoxPackFlags.NONE);
|
||||
this._appsContent.append(this._appDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let moreAppsBox = new Big.Box({x_align: Big.BoxAlignment.END});
|
||||
this._moreAppsLink = new Link.Link({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "More...",
|
||||
height: LABEL_HEIGHT });
|
||||
moreAppsBox.append(this._moreAppsLink.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._appsSection.append(moreAppsBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.actor.add_actor(this._appsSection);
|
||||
|
||||
this._appsSectionDefaultHeight = this._appsSection.height;
|
||||
|
||||
this._appsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER});
|
||||
this._appsDisplayControlBox.append(this._appDisplay.displayControl, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._docsSection = new Big.Box({ x: SIDESHOW_PAD,
|
||||
y: this._appsSection.y + this._appsSection.height,
|
||||
padding_top: SIDESHOW_SECTION_PADDING_TOP,
|
||||
spacing: SIDESHOW_SECTION_SPACING});
|
||||
|
||||
this._docsText = new Clutter.Text({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "Recent Documents",
|
||||
height: LABEL_HEIGHT});
|
||||
this._docsSection.append(this._docsText, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._docDisplay = new DocDisplay.DocDisplay(this._displayWidth, this._itemDisplayHeight - this._appsContent.height, SIDESHOW_COLUMNS, SIDESHOW_PAD);
|
||||
this._docsSection.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let moreDocsBox = new Big.Box({x_align: Big.BoxAlignment.END});
|
||||
this._moreDocsLink = new Link.Link({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "More...",
|
||||
height: LABEL_HEIGHT });
|
||||
moreDocsBox.append(this._moreDocsLink.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._docsSection.append(moreDocsBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.actor.add_actor(this._docsSection);
|
||||
|
||||
this._docsSectionDefaultHeight = this._docsSection.height;
|
||||
|
||||
this._docsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER});
|
||||
this._docsDisplayControlBox.append(this._docDisplay.displayControl, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._details = new Big.Box({ x: this._width + this._additionalWidth + SIDESHOW_SECTION_SPACING,
|
||||
y: Panel.PANEL_HEIGHT + SIDESHOW_PAD,
|
||||
width: previewWidth,
|
||||
height: previewHeight,
|
||||
corner_radius: DETAILS_CORNER_RADIUS,
|
||||
border: DETAILS_BORDER_WIDTH,
|
||||
border_color: DETAILS_BORDER_COLOR,
|
||||
padding: DETAILS_PADDING});
|
||||
this._appDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2,
|
||||
previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
|
||||
this._docDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2,
|
||||
previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
|
||||
|
||||
/* Proxy the activated signals */
|
||||
this._appDisplay.connect('activated', function(appDisplay) {
|
||||
me.emit('activated');
|
||||
});
|
||||
this._docDisplay.connect('activated', function(docDisplay) {
|
||||
me.emit('activated');
|
||||
});
|
||||
this._appDisplay.connect('selected', function(appDisplay) {
|
||||
// We allow clicking on any item to select it, so if an
|
||||
// item in the app display is selected, we need to make sure that
|
||||
// no item in the doc display has the selection.
|
||||
me._docDisplay.unsetSelected();
|
||||
me._docDisplay.hidePreview();
|
||||
});
|
||||
this._docDisplay.connect('selected', function(docDisplay) {
|
||||
// We allow clicking on any item to select it, so if an
|
||||
// item in the doc display is selected, we need to make sure that
|
||||
// no item in the app display has the selection.
|
||||
me._appDisplay.unsetSelected();
|
||||
me._appDisplay.hidePreview();
|
||||
});
|
||||
this._appDisplay.connect('redisplayed', function(appDisplay) {
|
||||
me._ensureItemSelected();
|
||||
});
|
||||
this._docDisplay.connect('redisplayed', function(docDisplay) {
|
||||
me._ensureItemSelected();
|
||||
});
|
||||
|
||||
this._moreAppsLink.connect('clicked',
|
||||
function(o, event) {
|
||||
if (me._moreAppsMode) {
|
||||
me._unsetMoreAppsMode();
|
||||
} else {
|
||||
me._setMoreAppsMode();
|
||||
}
|
||||
});
|
||||
|
||||
this._moreDocsLink.connect('clicked',
|
||||
function(o, event) {
|
||||
if (me._moreDocsMode) {
|
||||
me._unsetMoreDocsMode();
|
||||
} else {
|
||||
me._setMoreDocsMode();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
show: function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._appDisplay.show();
|
||||
this._appsContent.show();
|
||||
this._docDisplay.show();
|
||||
this._appDisplay.selectFirstItem();
|
||||
if (!this._appDisplay.hasSelected())
|
||||
this._docDisplay.selectFirstItem();
|
||||
else
|
||||
this._docDisplay.unsetSelected();
|
||||
global.stage.set_key_focus(this._searchEntry.entry);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._appsContent.hide();
|
||||
this._docDisplay.hide();
|
||||
this._searchEntry.entry.text = '';
|
||||
this._unsetMoreAppsMode();
|
||||
this._unsetMoreDocsMode();
|
||||
},
|
||||
|
||||
// Ensures that one of the displays has the selection if neither owns it after the
|
||||
// latest redisplay. This can be applicable if the display that earlier had the
|
||||
// selection no longer has any items, or if their is a single section being shown
|
||||
// in the expanded view and it went from having no matching items to having some.
|
||||
// We first try to place the selection in the applications section, because it is
|
||||
// displayed above the documents section.
|
||||
_ensureItemSelected: function() {
|
||||
if (!this._appDisplay.hasSelected() && !this._docDisplay.hasSelected()) {
|
||||
if (this._appDisplay.hasItems()) {
|
||||
this._appDisplay.selectFirstItem();
|
||||
} else if (this._docDisplay.hasItems()) {
|
||||
this._docDisplay.selectFirstItem();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Sets the 'More' mode for browsing applications. Updates the applications section to have more items.
|
||||
// Slides down the documents section to reveal the additional applications.
|
||||
_setMoreAppsMode: function() {
|
||||
if (this._moreAppsMode)
|
||||
return;
|
||||
|
||||
// No corresponding STATE_PENDING_ACTIVE, because we call updateAppsSection
|
||||
// immediately below.
|
||||
this._moreAppsMode = STATE_ACTIVE;
|
||||
|
||||
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
|
||||
|
||||
this._moreAppsLink.actor.hide();
|
||||
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
|
||||
|
||||
// Move the selection to the applications section if it was in the docs section.
|
||||
this._docDisplay.unsetSelected();
|
||||
// Because we have menus in applications, we want to reset the selection for applications
|
||||
// as well. The default is no menu.
|
||||
this._appDisplay.unsetSelected();
|
||||
this._updateAppsSection();
|
||||
|
||||
Tweener.addTween(this._docsSection,
|
||||
{ y: this._docsSection.y + this._docsSection.height,
|
||||
clipHeightBottom: 0,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
|
||||
// We need to expand the clip on the applications section so that the first additional
|
||||
// application to be displayed does not appear abruptly.
|
||||
Tweener.addTween(this._appsSection,
|
||||
{ clipHeightBottom: this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT * 2 - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._onAppsSectionExpanded,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
|
||||
Tweener.addTween(this.actor,
|
||||
{ clipWidthRight: this._expandedWidth,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
|
||||
this.emit('more-activated');
|
||||
},
|
||||
|
||||
// Unsets the 'More' mode for browsing applications. Slides in the documents section.
|
||||
_unsetMoreAppsMode: function() {
|
||||
if (!this._moreAppsMode)
|
||||
return;
|
||||
|
||||
this._moreAppsMode = STATE_PENDING_INACTIVE;
|
||||
|
||||
this._moreAppsLink.actor.hide();
|
||||
|
||||
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
|
||||
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
|
||||
this._docDisplay.show();
|
||||
|
||||
// We need to be reducing the clip on the applications section so that the last application to
|
||||
// be removed does not disappear abruptly.
|
||||
Tweener.addTween(this._appsSection,
|
||||
{ clipHeightBottom: this._appsSectionDefaultHeight - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._onAppsSectionReduced,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
Tweener.addTween(this._docsSection,
|
||||
{ y: this._docsSection.y - this._docsSection.height,
|
||||
clipHeightBottom: this._docsSection.height,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
Tweener.addTween(this.actor,
|
||||
{ clipWidthRight: this._width,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
this.emit('less-activated');
|
||||
},
|
||||
|
||||
// Removes the clip from the applications section to reveal the 'Less...' text.
|
||||
// Hides the documents section so that it doesn't get updated on new searches.
|
||||
_onAppsSectionExpanded: function() {
|
||||
this._appsSection.remove_clip();
|
||||
this._docDisplay.hide();
|
||||
this.actor.remove_clip();
|
||||
},
|
||||
|
||||
// Updates the applications section to contain fewer items. Selects the first item in the
|
||||
// documents section if applications section has no items.
|
||||
// Removes the clip from the applications section to reveal the 'More...' text.
|
||||
// Removes the clip from the documents section, so that the clip does not limit the size of
|
||||
// the section if it is expanded later.
|
||||
_onAppsSectionReduced: function() {
|
||||
this.actor.remove_clip();
|
||||
if (this._moreAppsMode != STATE_PENDING_INACTIVE)
|
||||
return;
|
||||
this._moreAppsMode = STATE_INACTIVE;
|
||||
this._updateAppsSection();
|
||||
if (!this._appDisplay.hasItems())
|
||||
this._docDisplay.selectFirstItem();
|
||||
this._appsSection.remove_clip();
|
||||
this._docsSection.remove_clip();
|
||||
},
|
||||
|
||||
// Updates the applications section display and the 'More...' or 'Less...' control associated with it
|
||||
// depending on the current mode. This function must only be called once after the 'More' mode has been
|
||||
// changed, which is ensured by _setMoreAppsMode() and _unsetMoreAppsMode() functions.
|
||||
_updateAppsSection: function() {
|
||||
if (this._moreAppsMode) {
|
||||
// Subtract one from columns since we are displaying menus
|
||||
this._appDisplay.setExpanded(true, this._displayWidth, this._additionalWidth,
|
||||
this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT,
|
||||
this._expandedSideshowColumns - 1);
|
||||
this._moreAppsLink.setText("Less...");
|
||||
this._appsSection.insert_after(this._appsDisplayControlBox, this._appsContent, Big.BoxPackFlags.NONE);
|
||||
this.actor.add_actor(this._details);
|
||||
this._details.append(this._appDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
|
||||
} else {
|
||||
this._appDisplay.setExpanded(false, this._displayWidth, 0,
|
||||
this._appsSectionDefaultHeight - SIDESHOW_SECTION_MISC_HEIGHT,
|
||||
SIDESHOW_COLUMNS);
|
||||
this._moreAppsLink.setText("More...");
|
||||
this._appsSection.remove_actor(this._appsDisplayControlBox);
|
||||
this.actor.remove_actor(this._details);
|
||||
this._details.remove_all();
|
||||
}
|
||||
this._moreAppsLink.actor.show();
|
||||
},
|
||||
|
||||
// Sets the 'More' mode for browsing documents. Updates the documents section to have more items.
|
||||
// Slides up the applications section and the documents section at the same time to reveal the additional
|
||||
// documents.
|
||||
_setMoreDocsMode: function() {
|
||||
if (this._moreDocsMode)
|
||||
return;
|
||||
|
||||
this._moreDocsMode = true;
|
||||
|
||||
if (!this._appsSection.has_clip)
|
||||
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
|
||||
|
||||
this._moreDocsLink.actor.hide();
|
||||
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
|
||||
|
||||
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
|
||||
|
||||
// Move the selection to the docs section if it was in the apps section.
|
||||
this._appDisplay.unsetSelected();
|
||||
if (!this._docDisplay.hasSelected())
|
||||
this._docDisplay.selectFirstItem();
|
||||
|
||||
|
||||
this._updateDocsSection();
|
||||
|
||||
Tweener.addTween(this._appsSection,
|
||||
{ y: this._appsSection.y - this._appsSection.height,
|
||||
clipHeightTop: 0,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
// We do not slide in the 'Less...' text along with the documents so that the documents appear from the same
|
||||
// edge where the last document was displayed, and not have that edge gradually move over to where the 'Less'
|
||||
// text is displayed.
|
||||
Tweener.addTween(this._docsSection,
|
||||
{ y: this._searchEntry.actor.y + this._searchEntry.actor.height,
|
||||
clipHeightBottom: this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT * 2 - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._onDocsSectionExpanded,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
Tweener.addTween(this.actor,
|
||||
{ clipWidthRight: this._expandedWidth,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
|
||||
this.emit('more-activated');
|
||||
},
|
||||
|
||||
// Unsets the 'More' mode for browsing documents. Slides in the applications section
|
||||
// and slides down the documents section.
|
||||
_unsetMoreDocsMode: function() {
|
||||
if (!this._moreDocsMode)
|
||||
return;
|
||||
|
||||
this._moreDocsMode = false;
|
||||
|
||||
this._moreDocsLink.actor.hide();
|
||||
|
||||
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
|
||||
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
|
||||
this._appsContent.show();
|
||||
|
||||
Tweener.addTween(this._docsSection,
|
||||
{ y: this._docsSection.y + this._appsSectionDefaultHeight,
|
||||
clipHeightBottom: this._docsSectionDefaultHeight - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._onDocsSectionReduced,
|
||||
onCompleteScope: this
|
||||
});
|
||||
Tweener.addTween(this._appsSection,
|
||||
{ y: this._appsSection.y + this._appsSection.height,
|
||||
clipHeightTop: this._appsSection.height,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
Tweener.addTween(this.actor,
|
||||
{ clipWidthRight: this._width,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
|
||||
this.emit('less-activated');
|
||||
},
|
||||
|
||||
// Removes the clip from the documents section to reveal the 'Less...' text.
|
||||
// Hides the applications section so that it doesn't get updated on new searches.
|
||||
_onDocsSectionExpanded: function() {
|
||||
this._docsSection.remove_clip();
|
||||
this._appsContent.hide();
|
||||
this.actor.remove_clip();
|
||||
},
|
||||
|
||||
// Updates the documents section to contain fewer items. Selects the first item in the
|
||||
// applications section if applications section has no items.
|
||||
// Removes the clip from the documents section to reveal the 'More...' text.
|
||||
// Removes the clip from the applications section, so that the clip does not limit the size of
|
||||
// the section if it is expanded later.
|
||||
_onDocsSectionReduced: function() {
|
||||
this.actor.remove_clip();
|
||||
this._updateDocsSection();
|
||||
if (!this._docDisplay.hasItems())
|
||||
this._appDisplay.selectFirstItem();
|
||||
this._docsSection.remove_clip();
|
||||
this._appsSection.remove_clip();
|
||||
},
|
||||
|
||||
// Updates the documents section display and the 'More...' or 'Less...' control associated with it
|
||||
// depending on the current mode. This function must only be called once after the 'More' mode has been
|
||||
// changed, which is ensured by _setMoreDocsMode() and _unsetMoreDocsMode() functions.
|
||||
_updateDocsSection: function() {
|
||||
if (this._moreDocsMode) {
|
||||
this._docDisplay.setExpanded(true, this._displayWidth, this._additionalWidth,
|
||||
this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT,
|
||||
this._expandedSideshowColumns);
|
||||
this._moreDocsLink.setText("Less...");
|
||||
this._docsSection.insert_after(this._docsDisplayControlBox, this._docDisplay.actor, Big.BoxPackFlags.NONE);
|
||||
this.actor.add_actor(this._details);
|
||||
this._details.append(this._docDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
|
||||
} else {
|
||||
this._docDisplay.setExpanded(false, this._displayWidth, 0,
|
||||
this._docsSectionDefaultHeight - SIDESHOW_SECTION_MISC_HEIGHT,
|
||||
SIDESHOW_COLUMNS);
|
||||
this._moreDocsLink.setText("More...");
|
||||
this._docsSection.remove_actor(this._docsDisplayControlBox);
|
||||
this.actor.remove_actor(this._details);
|
||||
this._details.remove_all();
|
||||
}
|
||||
this._moreDocsLink.actor.show();
|
||||
}
|
||||
|
||||
};
|
||||
Signals.addSignalMethods(Sideshow.prototype);
|
||||
|
||||
function Overlay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Overlay.prototype = {
|
||||
_init : function() {
|
||||
let me = this;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
|
||||
|
||||
// We divide the screen into an imaginary grid which helps us determine the layout of
|
||||
// different visual components.
|
||||
if (wideScreen) {
|
||||
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
|
||||
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
|
||||
} else {
|
||||
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
|
||||
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
|
||||
}
|
||||
|
||||
this._group = new Clutter.Group();
|
||||
this._group._delegate = this;
|
||||
|
||||
this.visible = false;
|
||||
this._hideInProgress = false;
|
||||
|
||||
// A scaled root pixmap actor is used as a background. It is zoomed in
|
||||
// to the lower right intersection of the lines that divide the image
|
||||
// evenly in a 3x3 grid. This is based on the rule of thirds, a
|
||||
// compositional rule of thumb in visual arts. The choice for the
|
||||
// lower right point is based on a quick survey of GNOME wallpapers.
|
||||
let background = global.create_root_pixmap_actor();
|
||||
background.width = global.screen_width * BACKGROUND_SCALE;
|
||||
background.height = global.screen_height * BACKGROUND_SCALE;
|
||||
background.x = -global.screen_width * (4 * BACKGROUND_SCALE - 3) / 6;
|
||||
background.y = -global.screen_height * (4 * BACKGROUND_SCALE - 3) / 6;
|
||||
this._group.add_actor(background);
|
||||
|
||||
// Draw a semitransparent rectangle over the background for readability.
|
||||
let backOver = new Clutter.Rectangle({ color: ROOT_OVERLAY_COLOR,
|
||||
width: global.screen_width,
|
||||
height: global.screen_height - Panel.PANEL_HEIGHT,
|
||||
y: Panel.PANEL_HEIGHT });
|
||||
this._group.add_actor(backOver);
|
||||
|
||||
this._group.hide();
|
||||
global.overlay_group.add_actor(this._group);
|
||||
|
||||
// TODO - recalculate everything when desktop size changes
|
||||
this._sideshow = new Sideshow();
|
||||
this._group.add_actor(this._sideshow.actor);
|
||||
this._workspaces = null;
|
||||
this._sideshow.connect('activated', function(sideshow) {
|
||||
// TODO - have some sort of animation/effect while
|
||||
// transitioning to the new app. We definitely need
|
||||
// startup-notification integration at least.
|
||||
me.hide();
|
||||
});
|
||||
this._sideshow.connect('more-activated', function(sideshow) {
|
||||
if (me._workspaces != null) {
|
||||
let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN;
|
||||
|
||||
let workspacesX = displayGridColumnWidth * asideXFactor + WORKSPACE_GRID_PADDING;
|
||||
me._workspaces.addButton.hide();
|
||||
me._workspaces.updatePosition(workspacesX, null);
|
||||
}
|
||||
});
|
||||
this._sideshow.connect('less-activated', function(sideshow) {
|
||||
if (me._workspaces != null) {
|
||||
let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
||||
me._workspaces.addButton.show();
|
||||
me._workspaces.updatePosition(workspacesX, null);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//// Draggable target interface ////
|
||||
|
||||
// Unsets the expanded display mode if a GenericDisplayItem is being
|
||||
// dragged over the overlay, i.e. as soon as it starts being dragged.
|
||||
// This slides the workspaces back in and allows the user to place
|
||||
// the item on any workspace.
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
if (source instanceof GenericDisplay.GenericDisplayItem) {
|
||||
this._sideshow._unsetMoreAppsMode();
|
||||
this._sideshow._unsetMoreDocsMode();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
show : function() {
|
||||
if (this.visible)
|
||||
return;
|
||||
if (!Main.startModal())
|
||||
return;
|
||||
|
||||
this.visible = true;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
let screenWidth = global.screen_width;
|
||||
let screenHeight = global.screen_height;
|
||||
|
||||
this._sideshow.show();
|
||||
|
||||
let columnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||
let rowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||
|
||||
let workspacesWidth = displayGridColumnWidth * columnsUsed - WORKSPACE_GRID_PADDING * 2;
|
||||
// We scale the vertical padding by (screenHeight / screenWidth) so that the workspace preserves its aspect ratio.
|
||||
let workspacesHeight = displayGridRowHeight * rowsUsed - WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
|
||||
|
||||
let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
||||
let workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
|
||||
|
||||
// place the 'Add Workspace' button in the bottom row of the grid
|
||||
let addButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
||||
let addButtonX = workspacesX + workspacesWidth - addButtonSize;
|
||||
let addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
|
||||
|
||||
this._workspaces = new Workspaces.Workspaces(workspacesWidth, workspacesHeight, workspacesX, workspacesY,
|
||||
addButtonSize, addButtonX, addButtonY);
|
||||
this._group.add_actor(this._workspaces.actor);
|
||||
|
||||
// All the the actors in the window group are completely obscured,
|
||||
// hiding the group holding them while the overlay is displayed greatly
|
||||
// increases performance of the overlay especially when there are many
|
||||
// windows visible.
|
||||
//
|
||||
// If we switched to displaying the actors in the overlay rather than
|
||||
// clones of them, this would obviously no longer be necessary.
|
||||
global.window_group.hide();
|
||||
this._group.show();
|
||||
|
||||
// Try to make the menu not too visible behind the empty space between
|
||||
// the workspace previews by sliding in its clipping rectangle.
|
||||
// We want to finish drawing the sideshow just before the top workspace fully
|
||||
// slides in on the top. Which means that we have more time to wait before
|
||||
// drawing the sideshow if the active workspace is displayed on the bottom of
|
||||
// the workspaces grid, and almost no time to wait if it is displayed in the top
|
||||
// row of the workspaces grid. The calculations used below try to roughly
|
||||
// capture the animation ratio for when workspaces are covering the top of the overlay
|
||||
// vs. when workspaces are already below the top of the overlay, and apply it
|
||||
// to clipping the sideshow. The clipping is removed in this._showDone().
|
||||
this._sideshow.actor.set_clip(0, 0,
|
||||
this._workspaces.getFullSizeX(),
|
||||
this._sideshow.actor.height);
|
||||
Tweener.addTween(this._sideshow.actor,
|
||||
{ clipWidthRight: this._sideshow._width + WORKSPACE_GRID_PADDING + this._workspaces.getWidthToTopActiveWorkspace(),
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._showDone,
|
||||
onCompleteScope: this
|
||||
|
||||
});
|
||||
|
||||
this.emit('showing');
|
||||
},
|
||||
|
||||
hide : function() {
|
||||
if (!this.visible || this._hideInProgress)
|
||||
return;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._hideInProgress = true;
|
||||
// lower the sideshow, so that workspaces display is on top and covers the sideshow while it is sliding out
|
||||
this._sideshow.actor.lower(this._workspaces.actor);
|
||||
this._workspaces.hide();
|
||||
|
||||
// Try to make the menu not too visible behind the empty space between
|
||||
// the workspace previews by sliding in its clipping rectangle.
|
||||
// The logic used is the same as described in this.show(). If the active workspace
|
||||
// is displayed in the top row, than almost full animation time is needed for it
|
||||
// to reach the top of the overlay and cover the sideshow fully, while if the
|
||||
// active workspace is in the lower row, than the top left workspace reaches the
|
||||
// top of the overlay sooner as it is moving out of the way.
|
||||
// The clipping is removed in this._hideDone().
|
||||
this._sideshow.actor.set_clip(0, 0,
|
||||
this._sideshow.actor.width + WORKSPACE_GRID_PADDING + this._workspaces.getWidthToTopActiveWorkspace(),
|
||||
this._sideshow.actor.height);
|
||||
Tweener.addTween(this._sideshow.actor,
|
||||
{ clipWidthRight: this._workspaces.getFullSizeX() + this._workspaces.getWidthToTopActiveWorkspace() - global.screen_width,
|
||||
time: ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._hideDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
this.emit('hiding');
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
if (this.visible)
|
||||
this.hide();
|
||||
else
|
||||
this.show();
|
||||
},
|
||||
|
||||
//// Private methods ////
|
||||
|
||||
// Raises the sideshow to the top, so that we can tell if the pointer is above one of its items.
|
||||
// We need to do this once the workspaces are shown because the workspaces actor currently covers
|
||||
// the whole screen, regardless of where the workspaces are actually displayed.
|
||||
//
|
||||
// Once we rework the workspaces actor to only cover the area it actually needs, we can
|
||||
// remove this workaround. Also http://bugzilla.openedhand.com/show_bug.cgi?id=1513 requests being
|
||||
// able to pick only a reactive actor at a certain position, rather than any actor. Being able
|
||||
// to do that would allow us to not have to raise the sideshow.
|
||||
_showDone: function() {
|
||||
if (this._hideInProgress)
|
||||
return;
|
||||
|
||||
this._sideshow.actor.raise_top();
|
||||
this._sideshow.actor.remove_clip();
|
||||
|
||||
this.emit('shown');
|
||||
},
|
||||
|
||||
_hideDone: function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
global.window_group.show();
|
||||
|
||||
this._workspaces.destroy();
|
||||
this._workspaces = null;
|
||||
|
||||
this._sideshow.actor.remove_clip();
|
||||
this._sideshow.hide();
|
||||
this._group.hide();
|
||||
|
||||
this.visible = false;
|
||||
this._hideInProgress = false;
|
||||
|
||||
Main.endModal();
|
||||
this.emit('hidden');
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Overlay.prototype);
|
||||
|
||||
Tweener.registerSpecialProperty("clipHeightBottom", _clipHeightBottomGet, _clipHeightBottomSet);
|
||||
|
||||
function _clipHeightBottomGet(actor) {
|
||||
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
|
||||
return clipHeight;
|
||||
}
|
||||
|
||||
function _clipHeightBottomSet(actor, clipHeight) {
|
||||
actor.set_clip(0, 0, actor.width, clipHeight);
|
||||
}
|
||||
|
||||
Tweener.registerSpecialProperty("clipHeightTop", _clipHeightTopGet, _clipHeightTopSet);
|
||||
|
||||
function _clipHeightTopGet(actor) {
|
||||
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
|
||||
return clipHeight;
|
||||
}
|
||||
|
||||
function _clipHeightTopSet(actor, clipHeight) {
|
||||
actor.set_clip(0, actor.height - clipHeight, actor.width, clipHeight);
|
||||
}
|
||||
|
||||
Tweener.registerSpecialProperty("clipWidthRight", _clipWidthRightGet, _clipWidthRightSet);
|
||||
|
||||
function _clipWidthRightGet(actor) {
|
||||
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
|
||||
return clipWidth;
|
||||
}
|
||||
|
||||
function _clipWidthRightSet(actor, clipWidth) {
|
||||
actor.set_clip(0, 0, clipWidth, actor.height);
|
||||
}
|
480
js/ui/overview.js
Normal file
@ -0,0 +1,480 @@
|
||||
/* -*- 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 Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const DocDisplay = imports.ui.docDisplay;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Link = imports.ui.link;
|
||||
const Main = imports.ui.main;
|
||||
const Panel = imports.ui.panel;
|
||||
const Dash = imports.ui.dash;
|
||||
const Tweener = imports.ui.tweener;
|
||||
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
|
||||
const ANIMATION_TIME = 0.25;
|
||||
|
||||
// We divide the screen into a grid of rows and columns, which we use
|
||||
// to help us position the Overview components, such as the side panel
|
||||
// that lists applications and documents, the workspaces display, and
|
||||
// the button for adding additional workspaces.
|
||||
// In the regular mode, the side panel takes up one column on the left,
|
||||
// and the workspaces display takes up the remaining columns.
|
||||
// In the expanded side panel display mode, the side panel takes up two
|
||||
// columns, and the workspaces display slides all the way to the right,
|
||||
// being visible only in the last quarter of the right-most column.
|
||||
// In the future, this mode will have more components, such as a display
|
||||
// of documents which were recently opened with a given application, which
|
||||
// will take up the remaining sections of the display.
|
||||
|
||||
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
|
||||
|
||||
const COLUMNS_REGULAR_SCREEN = 4;
|
||||
const ROWS_REGULAR_SCREEN = 8;
|
||||
const COLUMNS_WIDE_SCREEN = 5;
|
||||
const ROWS_WIDE_SCREEN = 10;
|
||||
|
||||
const DEFAULT_PADDING = 4;
|
||||
|
||||
// Padding around workspace grid / Spacing between Dash and Workspaces
|
||||
const WORKSPACE_GRID_PADDING = 12;
|
||||
|
||||
const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
|
||||
const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6;
|
||||
|
||||
const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
|
||||
const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8;
|
||||
|
||||
// A multi-state; PENDING is used during animations
|
||||
const STATE_ACTIVE = true;
|
||||
const STATE_PENDING_INACTIVE = false;
|
||||
const STATE_INACTIVE = false;
|
||||
|
||||
const SHADOW_COLOR = new Clutter.Color();
|
||||
SHADOW_COLOR.from_pixel(0x00000033);
|
||||
const TRANSPARENT_COLOR = new Clutter.Color();
|
||||
TRANSPARENT_COLOR.from_pixel(0x00000000);
|
||||
|
||||
const SHADOW_WIDTH = 6;
|
||||
|
||||
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
||||
|
||||
let wideScreen = false;
|
||||
let displayGridColumnWidth = null;
|
||||
let displayGridRowHeight = null;
|
||||
let addRemoveButtonSize = null;
|
||||
|
||||
function Overview() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Overview.prototype = {
|
||||
_init : function() {
|
||||
this._group = new Clutter.Group();
|
||||
this._group._delegate = this;
|
||||
|
||||
this.visible = false;
|
||||
this.animationInProgress = false;
|
||||
this._hideInProgress = false;
|
||||
|
||||
this._recalculateGridSizes();
|
||||
|
||||
this._activeDisplayPane = null;
|
||||
|
||||
// During transitions, we raise this to the top to avoid having the overview
|
||||
// area be reactive; it causes too many issues such as double clicks on
|
||||
// Dash elements, or mouseover handlers in the workspaces.
|
||||
this._coverPane = new Clutter.Rectangle({ opacity: 0,
|
||||
reactive: true });
|
||||
this._group.add_actor(this._coverPane);
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||
|
||||
// Similar to the cover pane but used for dialogs ("panes"); see the comments
|
||||
// in addPane below.
|
||||
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
|
||||
reactive: true });
|
||||
this._group.add_actor(this._transparentBackground);
|
||||
|
||||
// Background color for the Overview
|
||||
this._backOver = new Clutter.Rectangle({ color: ROOT_OVERVIEW_COLOR });
|
||||
this._group.add_actor(this._backOver);
|
||||
|
||||
this._group.hide();
|
||||
global.overlay_group.add_actor(this._group);
|
||||
|
||||
// TODO - recalculate everything when desktop size changes
|
||||
this._dash = new Dash.Dash();
|
||||
this._group.add_actor(this._dash.actor);
|
||||
|
||||
// Container to hold popup pane chrome.
|
||||
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
|
||||
// inside the notify::visible handler on panes.
|
||||
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
|
||||
this._activeDisplayPane.close();
|
||||
return true;
|
||||
}));
|
||||
this._group.add_actor(this._paneContainer);
|
||||
|
||||
this._transparentBackground.lower_bottom();
|
||||
this._paneContainer.lower_bottom();
|
||||
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
this._workspaces = null;
|
||||
},
|
||||
|
||||
_recalculateGridSizes: function () {
|
||||
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
|
||||
|
||||
// We divide the screen into an imaginary grid which helps us determine the layout of
|
||||
// different visual components.
|
||||
if (wideScreen) {
|
||||
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
|
||||
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
|
||||
} else {
|
||||
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
|
||||
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
|
||||
}
|
||||
},
|
||||
|
||||
relayout: function () {
|
||||
let screenHeight = global.screen_height;
|
||||
let screenWidth = global.screen_width;
|
||||
|
||||
let contentY = Panel.PANEL_HEIGHT;
|
||||
let contentHeight = screenHeight - contentY;
|
||||
|
||||
this._coverPane.set_position(0, contentY);
|
||||
this._coverPane.set_size(screenWidth, contentHeight);
|
||||
|
||||
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;
|
||||
|
||||
this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
|
||||
- WORKSPACE_GRID_PADDING * 2;
|
||||
// We scale the vertical padding by (screenHeight / screenWidth)
|
||||
// so that the workspace preserves its aspect ratio.
|
||||
this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed
|
||||
- WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
|
||||
|
||||
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
||||
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
|
||||
|
||||
this._dash.actor.set_position(0, contentY);
|
||||
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
|
||||
this._dash.searchArea.height = this._workspacesY - contentY;
|
||||
this._dash.sectionArea.height = this._workspacesHeight;
|
||||
|
||||
// place the 'Add Workspace' button in the bottom row of the grid
|
||||
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
||||
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
|
||||
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
|
||||
|
||||
this._backOver.set_position(0, contentY);
|
||||
this._backOver.set_size(global.screen_width, contentHeight);
|
||||
|
||||
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
||||
contentY);
|
||||
// Dynamic width
|
||||
this._paneContainer.height = contentHeight;
|
||||
|
||||
this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y);
|
||||
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) {
|
||||
this._paneContainer.append(pane.actor, Big.BoxPackFlags.NONE);
|
||||
// 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.
|
||||
// The idea here is that clicking anywhere outside the pane should close it.
|
||||
// When the active pane is closed, undo the effect.
|
||||
let backgroundEventId = null;
|
||||
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
|
||||
if (isOpen) {
|
||||
pane.actor.width = displayGridColumnWidth * 2;
|
||||
this._activeDisplayPane = pane;
|
||||
this._transparentBackground.raise_top();
|
||||
this._paneContainer.raise_top();
|
||||
if (backgroundEventId != null)
|
||||
this._transparentBackground.disconnect(backgroundEventId);
|
||||
backgroundEventId = this._transparentBackground.connect('button-release-event', Lang.bind(this, function () {
|
||||
this._activeDisplayPane.close();
|
||||
return true;
|
||||
}));
|
||||
} else if (pane == this._activeDisplayPane) {
|
||||
this._activeDisplayPane = null;
|
||||
if (backgroundEventId != null) {
|
||||
this._transparentBackground.disconnect(backgroundEventId);
|
||||
backgroundEventId = null;
|
||||
}
|
||||
this._transparentBackground.lower_bottom();
|
||||
this._paneContainer.lower_bottom();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
//// Draggable target interface ////
|
||||
|
||||
// Closes any active panes if a GenericDisplayItem is being
|
||||
// dragged over the Overview, i.e. as soon as it starts being dragged.
|
||||
// This allows the user to place the item on any workspace.
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
if (source instanceof GenericDisplay.GenericDisplayItem
|
||||
|| source instanceof AppDisplay.BaseWellItem) {
|
||||
if (this._activeDisplayPane != null)
|
||||
this._activeDisplayPane.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
// Returns the scale the Overview has when we just start zooming out
|
||||
// to overview mode. That is, when just the active workspace is showing.
|
||||
getZoomedInScale : function() {
|
||||
return 1 / this._workspaces.getScale();
|
||||
},
|
||||
|
||||
// Returns the position the Overview has when we just start zooming out
|
||||
// to overview mode. That is, when just the active workspace is showing.
|
||||
getZoomedInPosition : function() {
|
||||
let [posX, posY] = this._workspaces.getActiveWorkspacePosition();
|
||||
let scale = this.getZoomedInScale();
|
||||
|
||||
return [- posX * scale, - posY * scale];
|
||||
},
|
||||
|
||||
// Returns the current scale of the Overview.
|
||||
getScale : function() {
|
||||
return this._group.scaleX;
|
||||
},
|
||||
|
||||
// Returns the current position of the Overview.
|
||||
getPosition : function() {
|
||||
return [this._group.x, this._group.y];
|
||||
},
|
||||
|
||||
show : function() {
|
||||
if (this.visible)
|
||||
return;
|
||||
Main.pushModal(this._dash.actor);
|
||||
|
||||
this.visible = true;
|
||||
this.animationInProgress = true;
|
||||
|
||||
this._dash.show();
|
||||
|
||||
/* TODO: make this stuff dynamic */
|
||||
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
|
||||
this._workspacesX, this._workspacesY);
|
||||
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
|
||||
// for drag and drop to work. In the future we should fix the workspaces to not
|
||||
// be as big as the screen.
|
||||
this._dash.actor.raise(this._workspaces.actor);
|
||||
|
||||
// Create (+) button
|
||||
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
|
||||
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
|
||||
this._group.add_actor(this._addButton.actor);
|
||||
this._addButton.actor.raise(this._workspaces.actor);
|
||||
|
||||
// All the the actors in the window group are completely obscured,
|
||||
// hiding the group holding them while the Overview is displayed greatly
|
||||
// increases performance of the Overview especially when there are many
|
||||
// windows visible.
|
||||
//
|
||||
// If we switched to displaying the actors in the Overview rather than
|
||||
// clones of them, this would obviously no longer be necessary.
|
||||
global.window_group.hide();
|
||||
this._group.show();
|
||||
|
||||
// Create a zoom out effect. First scale the Overview group up and
|
||||
// position it so that the active workspace fills up the whole screen,
|
||||
// then transform the group to its normal dimensions and position.
|
||||
// The opposite transition is used in hide().
|
||||
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
|
||||
[this._group.x, this._group.y] = this.getZoomedInPosition();
|
||||
Tweener.addTween(this._group,
|
||||
{ x: 0,
|
||||
y: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
onComplete: this._showDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
// Make Dash fade in so that it doesn't appear to big.
|
||||
this._dash.actor.opacity = 0;
|
||||
Tweener.addTween(this._dash.actor,
|
||||
{ opacity: 255,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
this.emit('showing');
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (!this.visible || this._hideInProgress)
|
||||
return;
|
||||
|
||||
this.animationInProgress = true;
|
||||
this._hideInProgress = true;
|
||||
if (this._activeDisplayPane != null)
|
||||
this._activeDisplayPane.close();
|
||||
this._workspaces.hide();
|
||||
|
||||
// Create a zoom in effect by transforming the Overview group so that
|
||||
// the active workspace fills up the whole screen. The opposite
|
||||
// transition is used in show().
|
||||
let scale = this.getZoomedInScale();
|
||||
let [posX, posY] = this.getZoomedInPosition();
|
||||
Tweener.addTween(this._group,
|
||||
{ x: posX,
|
||||
y: posY,
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
onComplete: this._hideDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
// Make Dash fade out so that it doesn't appear to big.
|
||||
Tweener.addTween(this._dash.actor,
|
||||
{ opacity: 0,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
this.emit('hiding');
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
if (this.visible)
|
||||
this.hide();
|
||||
else
|
||||
this.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* getWorkspacesForWindow:
|
||||
* @metaWindow: A #MetaWindow
|
||||
*
|
||||
* Returns the Workspaces object associated with the given window.
|
||||
* This method is not be accessible if the overview is not open
|
||||
* and will return %null.
|
||||
*/
|
||||
getWorkspacesForWindow: function(metaWindow) {
|
||||
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 ////
|
||||
|
||||
_showDone: function() {
|
||||
if (this._hideInProgress)
|
||||
return;
|
||||
|
||||
this.animationInProgress = false;
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
this.emit('shown');
|
||||
},
|
||||
|
||||
_hideDone: function() {
|
||||
global.window_group.show();
|
||||
|
||||
this._workspaces.destroy();
|
||||
this._workspaces = null;
|
||||
|
||||
this._dash.hide();
|
||||
this._group.hide();
|
||||
|
||||
this.visible = false;
|
||||
this.animationInProgress = false;
|
||||
this._hideInProgress = false;
|
||||
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
Main.popModal(this._dash.actor);
|
||||
this.emit('hidden');
|
||||
},
|
||||
|
||||
_addNewWorkspace: function() {
|
||||
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
|
||||
},
|
||||
|
||||
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||
this._addNewWorkspace();
|
||||
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
||||
}
|
||||
};
|
||||
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);
|
||||
}
|
||||
};
|
472
js/ui/panel.js
@ -7,35 +7,48 @@ const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Button = imports.ui.button;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const PANEL_HEIGHT = 32;
|
||||
const PANEL_HEIGHT = 26;
|
||||
const TRAY_HEIGHT = PANEL_HEIGHT - 1;
|
||||
const SHADOW_HEIGHT = 6;
|
||||
|
||||
// The panel has a transparent white background with a gradient.
|
||||
const PANEL_TOP_COLOR = new Clutter.Color();
|
||||
PANEL_TOP_COLOR.from_pixel(0xffffff99);
|
||||
const PANEL_MIDDLE_COLOR = new Clutter.Color();
|
||||
PANEL_MIDDLE_COLOR.from_pixel(0xffffff88);
|
||||
const PANEL_BOTTOM_COLOR = new Clutter.Color();
|
||||
PANEL_BOTTOM_COLOR.from_pixel(0xffffffaa);
|
||||
const DEFAULT_PADDING = 4;
|
||||
|
||||
const PANEL_ICON_SIZE = 24;
|
||||
|
||||
const BACKGROUND_TOP = new Clutter.Color();
|
||||
BACKGROUND_TOP.from_pixel(0x161616ff);
|
||||
const BACKGROUND_BOTTOM = new Clutter.Color();
|
||||
BACKGROUND_BOTTOM.from_pixel(0x000000ff);
|
||||
|
||||
const PANEL_FOREGROUND_COLOR = new Clutter.Color();
|
||||
PANEL_FOREGROUND_COLOR.from_pixel(0xffffffff);
|
||||
const SN_BACKGROUND_COLOR = new Clutter.Color();
|
||||
SN_BACKGROUND_COLOR.from_pixel(0xffff00a0);
|
||||
|
||||
const SHADOW_COLOR = new Clutter.Color();
|
||||
SHADOW_COLOR.from_pixel(0x00000033);
|
||||
const TRANSPARENT_COLOR = new Clutter.Color();
|
||||
TRANSPARENT_COLOR.from_pixel(0x00000000);
|
||||
|
||||
// Darken (pressed) buttons; lightening has no effect on white backgrounds.
|
||||
// Don't make the mouse hover effect visible to the user for a menu feel.
|
||||
const PANEL_BUTTON_COLOR = new Clutter.Color();
|
||||
PANEL_BUTTON_COLOR.from_pixel(0x00000015);
|
||||
PANEL_BUTTON_COLOR.from_pixel(0x00000000);
|
||||
|
||||
// Lighten pressed buttons; darkening has no effect on a black background.
|
||||
const PRESSED_BUTTON_BACKGROUND_COLOR = new Clutter.Color();
|
||||
PRESSED_BUTTON_BACKGROUND_COLOR.from_pixel(0x00000030);
|
||||
PRESSED_BUTTON_BACKGROUND_COLOR.from_pixel(0x324c6ffa);
|
||||
|
||||
const DEFAULT_FONT = 'Sans 16px';
|
||||
|
||||
const TRAY_PADDING = 0;
|
||||
const TRAY_SPACING = 2;
|
||||
// See comments around _recomputeTraySize
|
||||
const TRAY_SPACING = 14;
|
||||
const TRAY_SPACING_MIN = 8;
|
||||
|
||||
// Used for the tray icon container with gtk pre-2.16, which doesn't
|
||||
// fully support tray icon transparency
|
||||
@ -46,84 +59,277 @@ TRAY_BORDER_COLOR.from_pixel(0x00000033);
|
||||
const TRAY_CORNER_RADIUS = 5;
|
||||
const TRAY_BORDER_WIDTH = 0;
|
||||
|
||||
|
||||
function AppPanelMenu() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
AppPanelMenu.prototype = {
|
||||
_init: function() {
|
||||
this._metaDisplay = global.screen.get_display();
|
||||
|
||||
this._focusedApp = null;
|
||||
this._activeSequence = null;
|
||||
this._startupSequences = {};
|
||||
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: DEFAULT_PADDING,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this._iconBox = new Big.Box({ width: PANEL_ICON_SIZE, height: PANEL_ICON_SIZE,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this.actor.append(this._iconBox, Big.BoxPackFlags.NONE);
|
||||
let labelBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this._label = new Clutter.Text({ font_name: DEFAULT_FONT,
|
||||
color: PANEL_FOREGROUND_COLOR,
|
||||
text: "" });
|
||||
labelBox.append(this._label, Big.BoxPackFlags.EXPAND);
|
||||
this.actor.append(labelBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._startupBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this.actor.append(this._startupBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
Main.overview.connect('hiding', Lang.bind(this, function () {
|
||||
this.actor.opacity = 255;
|
||||
}));
|
||||
Main.overview.connect('showing', Lang.bind(this, function () {
|
||||
this.actor.opacity = 192;
|
||||
}));
|
||||
|
||||
this._metaDisplay.connect('notify::focus-window', Lang.bind(this, this._sync));
|
||||
|
||||
let appMonitor = Shell.AppMonitor.get_default();
|
||||
appMonitor.connect('startup-sequence-changed', Lang.bind(this, this._sync));
|
||||
// For now just resync on application add/remove; this is mainly to handle
|
||||
// cases where the focused window's application changes without the focus
|
||||
// changing. An example case is how we map Firefox based on the window
|
||||
// title which is a dynamic property.
|
||||
appMonitor.connect('app-added', Lang.bind(this, this._sync));
|
||||
appMonitor.connect('app-removed', Lang.bind(this, this._sync));
|
||||
|
||||
this._sync();
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let appMonitor = Shell.AppMonitor.get_default();
|
||||
|
||||
let focusWindow = this._metaDisplay.get_focus_window();
|
||||
let focusedApp;
|
||||
if (focusWindow == null) {
|
||||
focusedApp = null;
|
||||
} else {
|
||||
focusedApp = appMonitor.get_window_app(focusWindow);
|
||||
}
|
||||
|
||||
let lastSequence = null;
|
||||
if (focusedApp == null) {
|
||||
let sequences = appMonitor.get_startup_sequences();
|
||||
if (sequences.length > 0)
|
||||
lastSequence = sequences[sequences.length - 1];
|
||||
}
|
||||
|
||||
// If the currently focused app hasn't changed and the current
|
||||
// startup sequence hasn't changed, we have nothing to do
|
||||
if (focusedApp == this._focusedApp
|
||||
&& ((lastSequence == null && this._activeSequence == null)
|
||||
|| (lastSequence != null && this._activeSequence != null
|
||||
&& lastSequence.get_id() == this._activeSequence.get_id())))
|
||||
return;
|
||||
|
||||
this._focusedApp = focusedApp;
|
||||
this._activeSequence = lastSequence;
|
||||
|
||||
this._iconBox.remove_all();
|
||||
this._iconBox.hide();
|
||||
this._label.text = '';
|
||||
if (this._focusedApp != null) {
|
||||
let icon = focusedApp.create_icon_texture(PANEL_ICON_SIZE);
|
||||
this._iconBox.append(icon, Big.BoxPackFlags.NONE);
|
||||
this._iconBox.show();
|
||||
this._label.text = focusedApp.get_name();
|
||||
} else if (this._activeSequence != null) {
|
||||
let icon = this._activeSequence.create_icon(PANEL_ICON_SIZE);
|
||||
this._iconBox.append(icon, Big.BoxPackFlags.NONE);
|
||||
this._iconBox.show();
|
||||
this._label.text = this._activeSequence.get_name();
|
||||
}
|
||||
|
||||
this.emit('changed');
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(AppPanelMenu.prototype);
|
||||
|
||||
function Panel() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Panel.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// Put the background under the panel within a group.
|
||||
this.actor = new Clutter.Group();
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
|
||||
});
|
||||
let backgroundGradient = Shell.create_vertical_gradient(BACKGROUND_TOP,
|
||||
BACKGROUND_BOTTOM);
|
||||
this.actor.connect('notify::allocation', Lang.bind(this, function () {
|
||||
let [width, height] = this.actor.get_size();
|
||||
backgroundGradient.set_size(width, height);
|
||||
}));
|
||||
this.actor.add_actor(backgroundGradient);
|
||||
|
||||
// Create backBox, which contains two boxes, backUpper and backLower,
|
||||
// for the background gradients and one for the shadow. The shadow at
|
||||
// the bottom has a fixed height (packing flag NONE), and the rest of
|
||||
// the height above is divided evenly between backUpper and backLower
|
||||
// (with packing flag EXPAND).
|
||||
let backBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: global.screen_width,
|
||||
height: PANEL_HEIGHT + SHADOW_HEIGHT });
|
||||
let backUpper = global.create_vertical_gradient(PANEL_TOP_COLOR,
|
||||
PANEL_MIDDLE_COLOR);
|
||||
let backLower = global.create_vertical_gradient(PANEL_MIDDLE_COLOR,
|
||||
PANEL_BOTTOM_COLOR);
|
||||
let shadow = global.create_vertical_gradient(SHADOW_COLOR,
|
||||
TRANSPARENT_COLOR);
|
||||
shadow.set_height(SHADOW_HEIGHT + 1);
|
||||
backBox.append(backUpper, Big.BoxPackFlags.EXPAND);
|
||||
backBox.append(backLower, Big.BoxPackFlags.EXPAND);
|
||||
backBox.append(shadow, Big.BoxPackFlags.NONE);
|
||||
this.actor.add_actor(backBox);
|
||||
this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
spacing: DEFAULT_PADDING,
|
||||
padding_right: DEFAULT_PADDING });
|
||||
this._centerBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this._rightBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
padding_left: DEFAULT_PADDING });
|
||||
|
||||
let box = new Big.Box({ x: 0,
|
||||
y: 0,
|
||||
height: PANEL_HEIGHT,
|
||||
width: global.screen_width,
|
||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: 4 });
|
||||
/* This box container ensures that the centerBox is positioned in the *absolute*
|
||||
* center, but can be pushed aside if necessary. */
|
||||
this._boxContainer = new Shell.GenericContainer();
|
||||
this.actor.append(this._boxContainer, Big.BoxPackFlags.EXPAND);
|
||||
this._boxContainer.add_actor(this._leftBox);
|
||||
this._boxContainer.add_actor(this._centerBox);
|
||||
this._boxContainer.add_actor(this._rightBox);
|
||||
this._boxContainer.connect('get-preferred-width', Lang.bind(this, function(box, forHeight, alloc) {
|
||||
let children = box.get_children();
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let [childMin, childNatural] = children[i].get_preferred_width(forHeight);
|
||||
alloc.min_size += childMin;
|
||||
alloc.natural_size += childNatural;
|
||||
}
|
||||
}));
|
||||
this._boxContainer.connect('get-preferred-height', Lang.bind(this, function(box, forWidth, alloc) {
|
||||
let children = box.get_children();
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let [childMin, childNatural] = children[i].get_preferred_height(forWidth);
|
||||
if (childMin > alloc.min_size)
|
||||
alloc.min_size = childMin;
|
||||
if (childNatural > alloc.natural_size)
|
||||
alloc.natural_size = childNatural;
|
||||
}
|
||||
}));
|
||||
this._boxContainer.connect('allocate', Lang.bind(this, function(container, box, flags) {
|
||||
let allocWidth = box.x2 - box.x1;
|
||||
let allocHeight = box.y2 - box.y1;
|
||||
let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
|
||||
let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
|
||||
let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
|
||||
let leftWidth, centerWidth, rightWidth;
|
||||
if (allocWidth < (leftNaturalWidth + centerNaturalWidth + rightNaturalWidth)) {
|
||||
leftWidth = leftMinWidth;
|
||||
centerWidth = centerMinWidth;
|
||||
rightWidth = rightMinWidth;
|
||||
} else {
|
||||
leftWidth = leftNaturalWidth;
|
||||
centerWidth = centerNaturalWidth;
|
||||
rightWidth = rightNaturalWidth;
|
||||
}
|
||||
|
||||
this.button = new Button.Button("Activities", PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, true, null, PANEL_HEIGHT);
|
||||
let x;
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = box.x1;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.x2 = x = childBox.x1 + leftWidth;
|
||||
childBox.y2 = box.y2;
|
||||
this._leftBox.allocate(childBox, flags);
|
||||
|
||||
box.append(this.button.button, Big.BoxPackFlags.NONE);
|
||||
let centerNaturalX = Math.floor((box.x2 - box.x1) / 2 - (centerWidth / 2));
|
||||
/* Check left side */
|
||||
if (x < centerNaturalX) {
|
||||
/* We didn't overflow the left, use the natural. */
|
||||
x = centerNaturalX;
|
||||
}
|
||||
/* Check right side */
|
||||
if (x + centerWidth > (box.x2 - rightWidth)) {
|
||||
x = box.x2 - rightWidth - centerWidth;
|
||||
}
|
||||
childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = x;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.x2 = x = childBox.x1 + centerWidth;
|
||||
childBox.y2 = box.y2;
|
||||
this._centerBox.allocate(childBox, flags);
|
||||
|
||||
let statusbox = new Big.Box();
|
||||
let statusmenu = this._statusmenu = new Shell.StatusMenu();
|
||||
statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE);
|
||||
let statusbutton = new Button.Button(statusbox, PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||
true, null, PANEL_HEIGHT);
|
||||
statusbutton.button.connect('button-press-event', function (b, e) {
|
||||
statusmenu.toggle(e);
|
||||
return false;
|
||||
});
|
||||
box.append(statusbutton.button, Big.BoxPackFlags.END);
|
||||
// We get a deactivated event when the popup disappears
|
||||
this._statusmenu.connect('deactivated', function (sm) {
|
||||
statusbutton.release();
|
||||
});
|
||||
childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = box.x2 - rightWidth;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.x2 = box.x2;
|
||||
childBox.y2 = box.y2;
|
||||
this._rightBox.allocate(childBox, flags);
|
||||
}));
|
||||
|
||||
this._clock = new Clutter.Text({ font_name: "Sans Bold 16px",
|
||||
/* left side */
|
||||
|
||||
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||
PANEL_FOREGROUND_COLOR, DEFAULT_FONT);
|
||||
this.button.actor.height = PANEL_HEIGHT;
|
||||
|
||||
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
// We use this flag to mark the case where the user has entered the
|
||||
// hot corner and has not left both the hot corner and a surrounding
|
||||
// guard area (the "environs"). This avoids triggering the hot corner
|
||||
// multiple times due to an accidental jitter.
|
||||
this._hotCornerEntered = false;
|
||||
|
||||
this._hotCornerEnvirons = new Clutter.Rectangle({ width: 3,
|
||||
height: 3,
|
||||
opacity: 0,
|
||||
reactive: true });
|
||||
|
||||
this._hotCorner = new Clutter.Rectangle({ width: 1,
|
||||
height: 1,
|
||||
opacity: 0,
|
||||
reactive: true });
|
||||
|
||||
this._hotCornerEnvirons.connect('leave-event',
|
||||
Lang.bind(this, this._onHotCornerEnvironsLeft));
|
||||
// Clicking on the hot corner environs should result in the same bahavior
|
||||
// as clicking on the hot corner.
|
||||
this._hotCornerEnvirons.connect('button-release-event',
|
||||
Lang.bind(this, this._onHotCornerClicked));
|
||||
|
||||
// In addition to being triggered by the mouse enter event, the hot corner
|
||||
// can be triggered by clicking on it. This is useful if the user wants to
|
||||
// undo the effect of triggering the hot corner once in the hot corner.
|
||||
this._hotCorner.connect('enter-event',
|
||||
Lang.bind(this, this._onHotCornerEntered));
|
||||
this._hotCorner.connect('button-release-event',
|
||||
Lang.bind(this, this._onHotCornerClicked));
|
||||
this._hotCorner.connect('leave-event',
|
||||
Lang.bind(this, this._onHotCornerLeft));
|
||||
|
||||
this._leftBox.append(this._hotCornerEnvirons, Big.BoxPackFlags.FIXED);
|
||||
this._leftBox.append(this._hotCorner, Big.BoxPackFlags.FIXED);
|
||||
|
||||
let appMenu = new AppPanelMenu();
|
||||
this._leftBox.append(appMenu.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
/* center */
|
||||
|
||||
this._clock = new Clutter.Text({ font_name: DEFAULT_FONT,
|
||||
color: PANEL_FOREGROUND_COLOR,
|
||||
text: "" });
|
||||
let pad = (PANEL_HEIGHT - this._clock.height) / 2;
|
||||
let clockbox = new Big.Box({ padding_top: pad,
|
||||
padding_bottom: pad,
|
||||
padding_left: 4,
|
||||
padding_right: 4 });
|
||||
clockbox.append(this._clock, Big.BoxPackFlags.NONE);
|
||||
box.append(clockbox, Big.BoxPackFlags.END);
|
||||
this._centerBox.append(this._clock, Big.BoxPackFlags.NONE);
|
||||
|
||||
/* right */
|
||||
|
||||
// The tray icons live in trayBox within trayContainer.
|
||||
// The trayBox is hidden when there are no tray icons.
|
||||
let trayContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
y_align: Big.BoxAlignment.START });
|
||||
box.append(trayContainer, Big.BoxPackFlags.END);
|
||||
this._rightBox.append(trayContainer, Big.BoxPackFlags.NONE);
|
||||
let trayBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
height: TRAY_HEIGHT,
|
||||
padding: TRAY_PADDING,
|
||||
spacing: TRAY_SPACING });
|
||||
this._trayBox = trayBox;
|
||||
|
||||
// gtk+ < 2.16 doesn't have fully-working icon transparency,
|
||||
// so we want trayBox to be opaque in that case (the icons
|
||||
@ -140,42 +346,100 @@ Panel.prototype = {
|
||||
|
||||
this._traymanager = new Shell.TrayManager({ bg_color: TRAY_BACKGROUND_COLOR });
|
||||
this._traymanager.connect('tray-icon-added',
|
||||
function(o, icon) {
|
||||
Lang.bind(this, function(o, icon) {
|
||||
trayBox.append(icon, Big.BoxPackFlags.NONE);
|
||||
|
||||
// Make sure the trayBox is shown.
|
||||
trayBox.show();
|
||||
});
|
||||
this._recomputeTraySize();
|
||||
}));
|
||||
this._traymanager.connect('tray-icon-removed',
|
||||
function(o, icon) {
|
||||
Lang.bind(this, function(o, icon) {
|
||||
trayBox.remove_actor(icon);
|
||||
|
||||
if (trayBox.get_children().length == 0)
|
||||
trayBox.hide();
|
||||
});
|
||||
this._recomputeTraySize();
|
||||
}));
|
||||
this._traymanager.manage_stage(global.stage);
|
||||
|
||||
// TODO: decide what to do with the rest of the panel in the overlay mode (make it fade-out, become non-reactive, etc.)
|
||||
// We get into the overlay mode on button-press-event as opposed to button-release-event because eventually we'll probably
|
||||
// have the overlay act like a menu that allows the user to release the mouse on the activity the user wants
|
||||
let statusbox = new Big.Box();
|
||||
let statusmenu = this._statusmenu = new Shell.StatusMenu();
|
||||
statusmenu.get_icon().hide();
|
||||
statusmenu.get_name().fontName = DEFAULT_FONT;
|
||||
statusmenu.get_name().color = PANEL_FOREGROUND_COLOR;
|
||||
statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE);
|
||||
let statusbutton = new Button.Button(statusbox,
|
||||
PANEL_BUTTON_COLOR,
|
||||
PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||
PANEL_FOREGROUND_COLOR);
|
||||
statusbutton.actor.height = PANEL_HEIGHT;
|
||||
statusbutton.actor.connect('button-press-event', function (b, e) {
|
||||
if (e.get_button() == 1 && e.get_click_count() == 1) {
|
||||
statusmenu.toggle(e);
|
||||
// The statusmenu might not pop up if it couldn't get a pointer grab
|
||||
if (statusmenu.is_active())
|
||||
statusbutton.actor.active = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this._rightBox.append(statusbutton.actor, Big.BoxPackFlags.NONE);
|
||||
// We get a deactivated event when the popup disappears
|
||||
this._statusmenu.connect('deactivated', function (sm) {
|
||||
statusbutton.actor.active = false;
|
||||
});
|
||||
|
||||
// TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.)
|
||||
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
|
||||
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
|
||||
// to switch to.
|
||||
this.button.button.connect('button-press-event',
|
||||
Lang.bind(Main.overlay, Main.overlay.toggle));
|
||||
// In addition to pressing the button, the overlay can be entered and exited by other means, such as
|
||||
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the overlay is entered
|
||||
this.button.actor.connect('button-press-event', function(b, e) {
|
||||
if (e.get_button() == 1 && e.get_click_count() == 1) {
|
||||
Main.overview.toggle();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// In addition to pressing the button, the Overview can be entered and exited by other means, such as
|
||||
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
|
||||
// and to be released when it is exited regardless of how it was triggered.
|
||||
Main.overlay.connect('showing', Lang.bind(this.button, this.button.pressIn));
|
||||
Main.overlay.connect('hiding', Lang.bind(this.button, this.button.release));
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
this.button.actor.active = true;
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||
this.button.actor.active = false;
|
||||
}));
|
||||
|
||||
this.actor.add_actor(box);
|
||||
|
||||
Main.chrome.addActor(this.actor, box);
|
||||
Main.chrome.setVisibleInOverlay(this.actor, true);
|
||||
Main.chrome.addActor(this.actor);
|
||||
Main.chrome.setVisibleInOverview(this.actor, true);
|
||||
|
||||
// Start the clock
|
||||
this._updateClock();
|
||||
},
|
||||
|
||||
startupAnimation: function() {
|
||||
this.actor.y = -this.actor.height;
|
||||
Tweener.addTween(this.actor,
|
||||
{ y: 0,
|
||||
time: 0.2,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
},
|
||||
|
||||
// By default, tray icons have a spacing of TRAY_SPACING. However this
|
||||
// starts to fail if we have too many as can sadly happen; just jump down
|
||||
// to a spacing of 8 if we're over 6.
|
||||
// http://bugzilla.gnome.org/show_bug.cgi?id=590495
|
||||
_recomputeTraySize: function () {
|
||||
if (this._trayBox.get_children().length > 6)
|
||||
this._trayBox.spacing = TRAY_SPACING_MIN;
|
||||
else
|
||||
this._trayBox.spacing = TRAY_SPACING;
|
||||
},
|
||||
|
||||
_updateClock: function() {
|
||||
let displayDate = new Date();
|
||||
let msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
|
||||
@ -184,8 +448,40 @@ Panel.prototype = {
|
||||
displayDate.setMinutes(displayDate.getMinutes() + 1);
|
||||
msecRemaining += 60000;
|
||||
}
|
||||
this._clock.set_text(displayDate.toLocaleFormat("%a %b %e, %l:%M %p"));
|
||||
/* Translators: This is a time format. */
|
||||
this._clock.set_text(displayDate.toLocaleFormat(_("%a %l:%M %p")));
|
||||
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClock));
|
||||
return false;
|
||||
},
|
||||
|
||||
_onHotCornerEntered : function() {
|
||||
if (!this._hotCornerEntered) {
|
||||
this._hotCornerEntered = true;
|
||||
if (!Main.overview.animationInProgress) {
|
||||
Main.overview.toggle();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_onHotCornerClicked : function() {
|
||||
if (!Main.overview.animationInProgress) {
|
||||
Main.overview.toggle();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_onHotCornerLeft : function(actor, event) {
|
||||
if (event.get_related() != this._hotCornerEnvirons) {
|
||||
this._hotCornerEntered = false;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_onHotCornerEnvironsLeft : function(actor, event) {
|
||||
if (event.get_related() != this._hotCorner) {
|
||||
this._hotCornerEntered = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
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,8 +1,15 @@
|
||||
/* -*- 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 Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
@ -15,8 +22,10 @@ BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
|
||||
const BOX_TEXT_COLOR = new Clutter.Color();
|
||||
BOX_TEXT_COLOR.from_pixel(0xffffffff);
|
||||
|
||||
const BOX_WIDTH = 320;
|
||||
const BOX_HEIGHT = 56;
|
||||
const DIALOG_WIDTH = 320;
|
||||
const DIALOG_PADDING = 6;
|
||||
const ICON_SIZE = 24;
|
||||
const ICON_BOX_SIZE = 36;
|
||||
|
||||
function RunDialog() {
|
||||
this._init();
|
||||
@ -24,7 +33,33 @@ function RunDialog() {
|
||||
|
||||
RunDialog.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
this._isOpen = false;
|
||||
|
||||
let gconf = Shell.GConf.get_default();
|
||||
gconf.connect('changed', Lang.bind(this, function (gconf, key) {
|
||||
if (key == 'development_tools')
|
||||
this._enableInternalCommands = gconf.get_bool('development_tools');
|
||||
}));
|
||||
this._enableInternalCommands = gconf.get_boolean('development_tools');
|
||||
|
||||
this._internalCommands = { 'lg':
|
||||
Lang.bind(this, function() {
|
||||
Main.createLookingGlass().open();
|
||||
}),
|
||||
|
||||
'r': Lang.bind(this, function() {
|
||||
global.reexec_self();
|
||||
}),
|
||||
|
||||
// Developer brain backwards compatibility
|
||||
'restart': Lang.bind(this, function() {
|
||||
global.reexec_self();
|
||||
}),
|
||||
|
||||
'debugexit': Lang.bind(this, function() {
|
||||
Meta.exit(Meta.ExitCode.ERROR);
|
||||
})
|
||||
};
|
||||
|
||||
// All actors are inside _group. We create it initially
|
||||
// hidden then show it in show()
|
||||
@ -38,100 +73,139 @@ RunDialog.prototype = {
|
||||
reactive: true });
|
||||
this._group.add_actor(this._overlay);
|
||||
|
||||
let boxGroup = new Clutter.Group();
|
||||
boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
|
||||
(global.screen_height - BOX_HEIGHT) / 2);
|
||||
this._group.add_actor(boxGroup);
|
||||
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
width: global.screen_width,
|
||||
height: global.screen_height });
|
||||
|
||||
let box = new Clutter.Rectangle({ color: BOX_BACKGROUND_COLOR,
|
||||
reactive: false,
|
||||
width: BOX_WIDTH,
|
||||
height: BOX_HEIGHT,
|
||||
border_width: 0 });
|
||||
boxGroup.add_actor(box);
|
||||
this._group.add_actor(boxH);
|
||||
|
||||
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
|
||||
boxH.append(boxV, Big.BoxPackFlags.NONE);
|
||||
|
||||
|
||||
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 });
|
||||
|
||||
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||
font_name: '18px Sans',
|
||||
text: 'Please enter a command:' });
|
||||
label.set_position(6, 6);
|
||||
boxGroup.add_actor(label);
|
||||
text: _("Please enter a command:") });
|
||||
|
||||
dialogBox.append(label, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||
font_name: '20px Sans Bold',
|
||||
editable: true,
|
||||
activatable: true,
|
||||
singleLineMode: true,
|
||||
text: '',
|
||||
width: BOX_WIDTH - 12,
|
||||
height: BOX_HEIGHT - 12 });
|
||||
// TODO: Implement relative positioning using Tidy.
|
||||
this._entry.set_position(6, 30);
|
||||
boxGroup.add_actor(this._entry);
|
||||
singleLineMode: true });
|
||||
|
||||
let me = this;
|
||||
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._entry.connect('activate', function (o, e) {
|
||||
me.hide();
|
||||
me._run(o.get_text());
|
||||
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;
|
||||
|
||||
let errorIcon = Shell.TextureCache.get_default().load_icon_name("gtk-dialog-error", ICON_SIZE);
|
||||
iconBox.append(errorIcon, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
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._entry.connect('activate', Lang.bind(this, function (o, e) {
|
||||
this._run(o.get_text());
|
||||
if (!this._commandError)
|
||||
this.close();
|
||||
}));
|
||||
|
||||
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
this.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}));
|
||||
},
|
||||
|
||||
_run : function(command) {
|
||||
if (command == 'restart') {
|
||||
let global = Shell.Global.get();
|
||||
global.reexec_self();
|
||||
let f;
|
||||
if (this._enableInternalCommands)
|
||||
f = this._internalCommands[command];
|
||||
else
|
||||
f = null;
|
||||
if (f) {
|
||||
f();
|
||||
} else if (command) {
|
||||
var p = new Shell.Process({'args' : [command]});
|
||||
try {
|
||||
this._commandError = false;
|
||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||
let p = new Shell.Process({'args' : args});
|
||||
p.run();
|
||||
} catch (e) {
|
||||
// TODO: Give the user direct feedback.
|
||||
log('Could not run command ' + command + '.');
|
||||
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 '" + command + "' failed:\n" + m[1];
|
||||
this._errorMessage.set_text(errorStr);
|
||||
this._errorBox.show();
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('run');
|
||||
},
|
||||
|
||||
show : function() {
|
||||
let me = this;
|
||||
|
||||
if (this._group.visible) // Already shown
|
||||
return false;
|
||||
|
||||
if (!Main.startModal())
|
||||
return false;
|
||||
|
||||
this._group.show_all();
|
||||
|
||||
this._entry.connect('key-press-event', function(o, e) {
|
||||
if (Shell.get_event_key_symbol(e) == Clutter.Escape) {
|
||||
me.hide();
|
||||
me.emit('cancel');
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
});
|
||||
|
||||
let global = Shell.Global.get();
|
||||
global.stage.set_key_focus(this._entry);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
hide : function() {
|
||||
if (!this._group.visible)
|
||||
open : function() {
|
||||
if (this._isOpen) // Already shown
|
||||
return;
|
||||
|
||||
this._group.hide();
|
||||
Main.endModal();
|
||||
this._isOpen = true;
|
||||
this._group.show();
|
||||
|
||||
Main.pushModal(this._group);
|
||||
global.stage.set_key_focus(this._entry);
|
||||
},
|
||||
|
||||
destroy : function(){
|
||||
this.hide();
|
||||
this._group.destroy();
|
||||
close : function() {
|
||||
if (!this._isOpen)
|
||||
return;
|
||||
|
||||
this._isOpen = false;
|
||||
|
||||
this._errorBox.hide();
|
||||
this._commandError = false;
|
||||
|
||||
this._group.hide();
|
||||
this._entry.text = '';
|
||||
|
||||
Main.popModal(this._group);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(RunDialog.prototype);
|
||||
|
105
js/ui/sidebar.js
@ -14,24 +14,12 @@ 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, plus the sidebar padding
|
||||
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 2 * WidgetBox.WIDGETBOX_PADDING + 2 * SIDEBAR_PADDING;
|
||||
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 2 * WidgetBox.WIDGETBOX_PADDING + 2 * SIDEBAR_PADDING;
|
||||
|
||||
// The maximum height of the sidebar would be extending from just
|
||||
// below the panel to just above the taskbar. Since the taskbar is
|
||||
// just a temporary hack and it would be too hard to do this the right
|
||||
// way, we just hardcode its size.
|
||||
const HARDCODED_TASKBAR_HEIGHT = 24;
|
||||
const MAXIMUM_SIDEBAR_HEIGHT = Shell.Global.get().screen_height - Panel.PANEL_HEIGHT - HARDCODED_TASKBAR_HEIGHT;
|
||||
|
||||
// FIXME, needs to be configurable, obviously
|
||||
const default_widgets = [
|
||||
"imports.ui.widget.ClockWidget",
|
||||
"imports.ui.widget.AppsWidget",
|
||||
"imports.ui.widget.DocsWidget"
|
||||
];
|
||||
// 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();
|
||||
@ -39,8 +27,6 @@ function Sidebar() {
|
||||
|
||||
Sidebar.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// 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
|
||||
@ -48,7 +34,6 @@ Sidebar.prototype = {
|
||||
this.actor = new Clutter.Group({ x: -WidgetBox.WIDGETBOX_PADDING,
|
||||
y: Panel.PANEL_HEIGHT,
|
||||
width: SIDEBAR_EXPANDED_WIDTH });
|
||||
Main.chrome.addActor(this.actor);
|
||||
|
||||
// The actual widgets go into a Big.Box inside this.actor. The
|
||||
// box's width will vary during the expand/collapse animations,
|
||||
@ -58,23 +43,38 @@ Sidebar.prototype = {
|
||||
// during the animation.
|
||||
this.box = new Big.Box ({ padding_top: SIDEBAR_PADDING,
|
||||
padding_bottom: SIDEBAR_PADDING,
|
||||
padding_right: SIDEBAR_PADDING,
|
||||
padding_right: 0,
|
||||
padding_left: 0,
|
||||
spacing: SIDEBAR_SPACING });
|
||||
this.actor.add_actor(this.box);
|
||||
|
||||
this._visible = this.expanded = true;
|
||||
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(this));
|
||||
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);
|
||||
widgetBox = new WidgetBox.WidgetBox(widget, this._expanded);
|
||||
} catch(e) {
|
||||
logError(e, "Failed to add widget '" + widget + "'");
|
||||
return;
|
||||
@ -84,18 +84,32 @@ Sidebar.prototype = {
|
||||
this._widgets.push(widgetBox);
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._visible = true;
|
||||
this.actor.show();
|
||||
_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);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._visible = false;
|
||||
this.actor.hide();
|
||||
_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;
|
||||
_expand: function() {
|
||||
this._expanded = true;
|
||||
for (let i = 0; i < this._widgets.length; i++)
|
||||
this._widgets[i].expand();
|
||||
|
||||
@ -106,8 +120,8 @@ Sidebar.prototype = {
|
||||
} });
|
||||
},
|
||||
|
||||
collapse: function() {
|
||||
this.expanded = false;
|
||||
_collapse: function() {
|
||||
this._expanded = false;
|
||||
for (let i = 0; i < this._widgets.length; i++)
|
||||
this._widgets[i].collapse();
|
||||
|
||||
@ -130,24 +144,33 @@ Sidebar.prototype = {
|
||||
const LEFT_DOUBLE_ARROW = "\u00AB";
|
||||
const RIGHT_DOUBLE_ARROW = "\u00BB";
|
||||
|
||||
function ToggleWidget(sidebar) {
|
||||
this._init(sidebar);
|
||||
function ToggleWidget() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
ToggleWidget.prototype = {
|
||||
__proto__ : Widget.Widget.prototype,
|
||||
|
||||
_init : function(sidebar) {
|
||||
this._sidebar = sidebar;
|
||||
_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._sidebar, this._sidebar.collapse));
|
||||
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._sidebar, this._sidebar.expand));
|
||||
Lang.bind(this, this._expand));
|
||||
},
|
||||
|
||||
_collapse : function () {
|
||||
this._gconf.set_boolean ("sidebar/expanded", false);
|
||||
},
|
||||
|
||||
_expand : function () {
|
||||
this._gconf.set_boolean ("sidebar/expanded", true);
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
@ -41,9 +42,17 @@ const Tweener = imports.tweener.tweener;
|
||||
// calls any of these is almost certainly wrong anyway, because they
|
||||
// affect the entire application.)
|
||||
|
||||
let slowDownFactor = 1.0;
|
||||
|
||||
// Called from Main.start
|
||||
function init() {
|
||||
let slowdownEnv = GLib.getenv("GNOME_SHELL_SLOWDOWN_FACTOR");
|
||||
if (slowdownEnv) {
|
||||
let factor = parseFloat(slowdownEnv);
|
||||
if (!isNaN(factor) && factor > 0.0)
|
||||
slowDownFactor = factor;
|
||||
}
|
||||
|
||||
Tweener.setFrameTicker(new ClutterFrameTicker());
|
||||
}
|
||||
|
||||
@ -208,11 +217,10 @@ ClutterFrameTicker.prototype = {
|
||||
this._startTime = -1;
|
||||
this._currentTime = -1;
|
||||
|
||||
let me = this;
|
||||
this._timeline.connect('new-frame',
|
||||
this._timeline.connect('new-frame', Lang.bind(this,
|
||||
function(timeline, frame) {
|
||||
me._onNewFrame(frame);
|
||||
});
|
||||
this._onNewFrame(frame);
|
||||
}));
|
||||
},
|
||||
|
||||
_onNewFrame : function(frame) {
|
||||
@ -225,7 +233,7 @@ ClutterFrameTicker.prototype = {
|
||||
this._startTime = this._timeline.get_elapsed_time();
|
||||
|
||||
// currentTime is in milliseconds
|
||||
this._currentTime = this._timeline.get_elapsed_time() - this._startTime;
|
||||
this._currentTime = (this._timeline.get_elapsed_time() - this._startTime) / slowDownFactor;
|
||||
this.emit('prepare-frame');
|
||||
},
|
||||
|
||||
|
102
js/ui/widget.js
@ -9,9 +9,9 @@ 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 AppInfo = imports.misc.appInfo;
|
||||
const DocDisplay = imports.ui.docDisplay;
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
|
||||
const COLLAPSED_WIDTH = 24;
|
||||
@ -31,12 +31,22 @@ function Widget() {
|
||||
Widget.prototype = {
|
||||
// _init():
|
||||
//
|
||||
// Your widget constructor. Receives no arguments. 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.
|
||||
// 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
|
||||
@ -51,6 +61,9 @@ Widget.prototype = {
|
||||
// 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():
|
||||
//
|
||||
@ -81,23 +94,22 @@ Widget.prototype = {
|
||||
// state:
|
||||
//
|
||||
// A field set on your widget by the sidebar. Will contain one of
|
||||
// the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED). Note
|
||||
// that this will not be set until *after* _init() is called, so
|
||||
// you cannot rely on it being set at that point. The widget will
|
||||
// always initially be in STATE_EXPANDED.
|
||||
// the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED).
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(Widget.prototype);
|
||||
|
||||
|
||||
function ClockWidget() {
|
||||
this._init();
|
||||
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
|
||||
@ -146,14 +158,14 @@ ClockWidget.prototype = {
|
||||
},
|
||||
|
||||
_updateText: function(time) {
|
||||
this.actor.set_text(time.toLocaleFormat("%H:%M"));
|
||||
// Translators: This is a time format.
|
||||
this.actor.set_text(time.toLocaleFormat(_("%H:%M")));
|
||||
},
|
||||
|
||||
_updateCairo: function(time) {
|
||||
let global = Shell.Global.get();
|
||||
global.clutter_cairo_texture_draw_clock(this.collapsedActor,
|
||||
time.getHours() % 12,
|
||||
time.getMinutes());
|
||||
Shell.draw_clock(this.collapsedActor,
|
||||
time.getHours() % 12,
|
||||
time.getMinutes());
|
||||
}
|
||||
};
|
||||
|
||||
@ -168,7 +180,7 @@ const ITEM_NAME_COLOR = new Clutter.Color();
|
||||
ITEM_NAME_COLOR.from_pixel(0x000000ff);
|
||||
|
||||
function LauncherWidget() {
|
||||
this._init();
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
|
||||
LauncherWidget.prototype = {
|
||||
@ -182,7 +194,7 @@ LauncherWidget.prototype = {
|
||||
spacing: ITEM_SPACING,
|
||||
reactive: true });
|
||||
item._info = info;
|
||||
item.append(info.getIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
|
||||
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,
|
||||
@ -203,7 +215,7 @@ LauncherWidget.prototype = {
|
||||
padding: ITEM_PADDING,
|
||||
reactive: true });
|
||||
item._info = info;
|
||||
item.append(info.getIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
|
||||
item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
|
||||
Big.BoxPackFlags.NONE);
|
||||
|
||||
this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
|
||||
@ -272,33 +284,61 @@ LauncherWidget.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
|
||||
AppsWidget.prototype = {
|
||||
__proto__ : LauncherWidget.prototype,
|
||||
|
||||
_init : function() {
|
||||
this.title = "Applications";
|
||||
Widget.prototype._init.apply(this, arguments);
|
||||
|
||||
this.title = _("Applications");
|
||||
this.actor = new Big.Box({ spacing: 2 });
|
||||
this.collapsedActor = new Big.Box({ spacing: 2});
|
||||
|
||||
let apps = AppInfo.getMostUsedApps(5);
|
||||
for (let i = 0; i < apps.length; i++)
|
||||
this.addItem(apps[i]);
|
||||
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 DocsWidget() {
|
||||
this._init();
|
||||
function RecentDocsWidget() {
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
|
||||
DocsWidget.prototype = {
|
||||
RecentDocsWidget.prototype = {
|
||||
__proto__ : LauncherWidget.prototype,
|
||||
|
||||
_init : function() {
|
||||
this.title = "Recent Docs";
|
||||
Widget.prototype._init.apply(this, arguments);
|
||||
|
||||
this.title = _("Recent Documents");
|
||||
this.actor = new Big.Box({ spacing: 2 });
|
||||
|
||||
this._recentManager = Gtk.RecentManager.get_default();
|
||||
@ -320,7 +360,7 @@ DocsWidget.prototype = {
|
||||
items.push(docInfo);
|
||||
}
|
||||
|
||||
items.sort(function (a,b) { return b.lastVisited() - a.lastVisited(); });
|
||||
items.sort(function (a,b) { return b.timestamp - a.timestamp; });
|
||||
for (i = 0; i < Math.min(items.length, 5); i++)
|
||||
this.addItem(items[i]);
|
||||
}
|
||||
|
@ -15,21 +15,24 @@ WIDGETBOX_BG_COLOR.from_pixel(0xf0f0f0ff);
|
||||
const BLACK = new Clutter.Color();
|
||||
BLACK.from_pixel(0x000000ff);
|
||||
|
||||
const WIDGETBOX_PADDING = 4;
|
||||
const WIDGETBOX_PADDING = 2;
|
||||
const ANIMATION_TIME = 0.5;
|
||||
const POP_IN_LAG = 250; /* milliseconds */
|
||||
|
||||
function WidgetBox(widget) {
|
||||
this._init(widget);
|
||||
function WidgetBox(widget, expanded) {
|
||||
this._init(widget, expanded);
|
||||
}
|
||||
|
||||
WidgetBox.prototype = {
|
||||
_init: function(widget) {
|
||||
if (widget instanceof Widget.Widget)
|
||||
_init: function(widget, expanded) {
|
||||
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
|
||||
|
||||
if (widget instanceof Widget.Widget) {
|
||||
this._widget = widget;
|
||||
else {
|
||||
this._widget.state = this.state;
|
||||
} else {
|
||||
let ctor = this._ctorFromName(widget);
|
||||
this._widget = new ctor();
|
||||
this._widget = new ctor(this.state);
|
||||
}
|
||||
|
||||
if (!this._widget.actor)
|
||||
@ -37,7 +40,7 @@ WidgetBox.prototype = {
|
||||
else if (!this._widget.title && !this._widget.collapsedActor)
|
||||
throw new Error("widget has neither title nor collapsedActor");
|
||||
|
||||
this.state = this._widget.state = Widget.STATE_EXPANDED;
|
||||
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
|
||||
|
||||
// The structure of a WidgetBox:
|
||||
//
|
||||
@ -77,9 +80,15 @@ WidgetBox.prototype = {
|
||||
|
||||
this.actor = new Clutter.Group();
|
||||
this._hbox = new Big.Box({ background_color: WIDGETBOX_BG_COLOR,
|
||||
padding: WIDGETBOX_PADDING,
|
||||
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 / 2,
|
||||
corner_radius: WIDGETBOX_PADDING,
|
||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
reactive: true });
|
||||
this.actor.add_actor(this._hbox);
|
||||
@ -122,7 +131,6 @@ WidgetBox.prototype = {
|
||||
this._activationHandler = this._widget.connect('activated',
|
||||
Lang.bind(this, this._activationHandler));
|
||||
}
|
||||
this._cgroup.hide();
|
||||
|
||||
this._egroup = new Clutter.Group({ clip_to_allocation: true });
|
||||
this._hbox.append(this._egroup, Big.BoxPackFlags.NONE);
|
||||
@ -142,6 +150,11 @@ WidgetBox.prototype = {
|
||||
}
|
||||
|
||||
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
|
||||
@ -178,16 +191,25 @@ WidgetBox.prototype = {
|
||||
this.state = this._widget.state = Widget.STATE_EXPANDING;
|
||||
},
|
||||
|
||||
_expandPart1Complete: function() {
|
||||
_setWidgetExpanded: function() {
|
||||
this._cgroup.hide();
|
||||
this._cbox.x = 0;
|
||||
this._egroup.show();
|
||||
|
||||
if (this._singleActor) {
|
||||
log(this._widget.actor);
|
||||
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();
|
||||
@ -196,11 +218,6 @@ WidgetBox.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
this._egroup.show();
|
||||
if (this._htitle) {
|
||||
this._htitle.show();
|
||||
this._hline.show();
|
||||
}
|
||||
this._ebox.x = -Widget.EXPANDED_WIDTH;
|
||||
Tweener.addTween(this._ebox, { x: 0,
|
||||
time: ANIMATION_TIME / 2,
|
||||
@ -222,19 +239,27 @@ WidgetBox.prototype = {
|
||||
this.state = this._widget.state = Widget.STATE_COLLAPSING;
|
||||
},
|
||||
|
||||
_collapsePart1Complete: function() {
|
||||
_setWidgetCollapsed: function() {
|
||||
this._egroup.hide();
|
||||
this._ebox.x = 0;
|
||||
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._singleActor) {
|
||||
log(this._widget.actor);
|
||||
this._widget.actor.unparent();
|
||||
this._cbox.append(this._widget.actor, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
if (this._vtitle)
|
||||
this._cbox.height = this._ebox.height;
|
||||
},
|
||||
|
||||
_collapsePart1Complete: function() {
|
||||
this._ebox.x = 0;
|
||||
this._setWidgetCollapsed();
|
||||
|
||||
if (this._widget.collapse) {
|
||||
try {
|
||||
@ -244,10 +269,7 @@ WidgetBox.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
this._cgroup.show();
|
||||
this._cbox.x = -Widget.COLLAPSED_WIDTH;
|
||||
if (this._vtitle)
|
||||
this._cbox.height = this._ebox.height;
|
||||
Tweener.addTween(this._cbox, { x: 0,
|
||||
time: ANIMATION_TIME / 2,
|
||||
transition: "easeOutQuad",
|
||||
@ -274,7 +296,7 @@ WidgetBox.prototype = {
|
||||
this.state == Widget.STATE_POPPING_OUT)) {
|
||||
// If moving into another actor within this._hbox, let the
|
||||
// event be propagated
|
||||
let into = Shell.get_event_related(event);
|
||||
let into = event.get_related();
|
||||
while (into) {
|
||||
if (into == this._hbox)
|
||||
return false;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const AltTab = imports.ui.altTab;
|
||||
const Main = imports.ui.main;
|
||||
@ -17,10 +17,8 @@ function WindowManager() {
|
||||
|
||||
WindowManager.prototype = {
|
||||
_init : function() {
|
||||
let me = this;
|
||||
let shellwm = global.window_manager;
|
||||
|
||||
this._global = Shell.Global.get();
|
||||
this._shellwm = this._global.window_manager;
|
||||
this._minimizing = [];
|
||||
this._maximizing = [];
|
||||
this._unmaximizing = [];
|
||||
@ -28,64 +26,24 @@ WindowManager.prototype = {
|
||||
this._destroying = [];
|
||||
|
||||
this._switchData = null;
|
||||
this._shellwm.connect('switch-workspace',
|
||||
function(o, from, to, direction) {
|
||||
let actors = me._shellwm.get_switch_workspace_actors();
|
||||
me._switchWorkspace(actors, from, to, direction);
|
||||
});
|
||||
this._shellwm.connect('kill-switch-workspace',
|
||||
function(o) {
|
||||
me._switchWorkspaceDone();
|
||||
});
|
||||
this._shellwm.connect('minimize',
|
||||
function(o, actor) {
|
||||
me._minimizeWindow(actor);
|
||||
});
|
||||
this._shellwm.connect('kill-minimize',
|
||||
function(o, actor) {
|
||||
me._minimizeWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('maximize',
|
||||
function(o, actor, tx, ty, tw, th) {
|
||||
me._maximizeWindow(actor, tx, ty, tw, th);
|
||||
});
|
||||
this._shellwm.connect('kill-maximize',
|
||||
function(o, actor) {
|
||||
me._maximizeWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('unmaximize',
|
||||
function(o, actor, tx, ty, tw, th) {
|
||||
me._unmaximizeWindow(actor, tx, ty, tw, th);
|
||||
});
|
||||
this._shellwm.connect('kill-unmaximize',
|
||||
function(o, actor) {
|
||||
me._unmaximizeWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('map',
|
||||
function(o, actor) {
|
||||
me._mapWindow(actor);
|
||||
});
|
||||
this._shellwm.connect('kill-map',
|
||||
function(o, actor) {
|
||||
me._mapWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('destroy',
|
||||
function(o, actor) {
|
||||
me._destroyWindow(actor);
|
||||
});
|
||||
this._shellwm.connect('kill-destroy',
|
||||
function(o, actor) {
|
||||
me._destroyWindowDone(actor);
|
||||
});
|
||||
shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
|
||||
shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
||||
shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
|
||||
shellwm.connect('kill-minimize', Lang.bind(this, this._minimizeWindowDone));
|
||||
shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
|
||||
shellwm.connect('kill-maximize', Lang.bind(this, this._maximizeWindowDone));
|
||||
shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
||||
shellwm.connect('kill-unmaximize', Lang.bind(this, this._unmaximizeWindowDone));
|
||||
shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
||||
shellwm.connect('kill-map', Lang.bind(this, this._mapWindowDone));
|
||||
shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
||||
shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
|
||||
|
||||
this._shellwm.connect('begin-alt-tab',
|
||||
function(o, handler) {
|
||||
me._beginAltTab(handler);
|
||||
});
|
||||
shellwm.connect('begin-alt-tab', Lang.bind(this, this._beginAltTab));
|
||||
},
|
||||
|
||||
_shouldAnimate : function(actor) {
|
||||
if (Main.overlay.visible)
|
||||
if (Main.overview.visible)
|
||||
return false;
|
||||
if (actor && (actor.get_window_type() != Meta.CompWindowType.NORMAL))
|
||||
return false;
|
||||
@ -101,9 +59,9 @@ WindowManager.prototype = {
|
||||
return false;
|
||||
},
|
||||
|
||||
_minimizeWindow : function(actor) {
|
||||
_minimizeWindow : function(shellwm, actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_minimize(actor);
|
||||
shellwm.completed_minimize(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,86 +79,49 @@ WindowManager.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._minimizeWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._minimizeWindowOverwritten,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
},
|
||||
|
||||
_minimizeWindowDone : function(actor) {
|
||||
_minimizeWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._minimizing, actor)) {
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||
|
||||
this._shellwm.completed_minimize(actor);
|
||||
shellwm.completed_minimize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_minimizeWindowOverwritten : function(actor) {
|
||||
_minimizeWindowOverwritten : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._minimizing, actor)) {
|
||||
this._shellwm.completed_minimize(actor);
|
||||
shellwm.completed_minimize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_maximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
_maximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
shellwm.completed_maximize(actor);
|
||||
},
|
||||
|
||||
_maximizeWindowDone : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_maximizeWindowOverwrite : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_unmaximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
shellwm.completed_unmaximize(actor);
|
||||
},
|
||||
|
||||
_unmaximizeWindowDone : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_mapWindow : function(shellwm, actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_maximize(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
/* this doesn't work very well, as simply scaling up the existing
|
||||
* window contents doesn't produce anything like the same results as
|
||||
* actually maximizing the window.
|
||||
*/
|
||||
let scaleX = targetWidth / actor.width;
|
||||
let scaleY = targetHeight / actor.height;
|
||||
let anchorX = (actor.x - targetX) * actor.width/(targetWidth - actor.width);
|
||||
let anchorY = (actor.y - targetY) * actor.height/(targetHeight - actor.height);
|
||||
|
||||
actor.move_anchor_point(anchorX, anchorY);
|
||||
|
||||
this._maximizing.push(actor);
|
||||
Tweener.addTween(actor,
|
||||
{ scale_x: scaleX,
|
||||
scale_y: scaleY,
|
||||
time: WINDOW_ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._maximizeWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onOverwrite: this._maximizeWindowOverwrite,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
});
|
||||
},
|
||||
|
||||
_maximizeWindowDone : function(actor) {
|
||||
if (this._removeEffect(this._maximizing, actor)) {
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||
this._shellwm.completed_maximize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_maximizeWindowOverwrite : function(actor) {
|
||||
if (this._removeEffect(this._maximizing, actor)) {
|
||||
this._shellwm.completed_maximize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_unmaximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
this._shellwm.completed_unmaximize(actor);
|
||||
},
|
||||
|
||||
_unmaximizeWindowDone : function(actor) {
|
||||
},
|
||||
|
||||
_mapWindow : function(actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_map(actor);
|
||||
shellwm.completed_map(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -217,31 +138,31 @@ WindowManager.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._mapWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._mapWindowOverwrite,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
},
|
||||
|
||||
_mapWindowDone : function(actor) {
|
||||
_mapWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._mapping, actor)) {
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||
this._shellwm.completed_map(actor);
|
||||
shellwm.completed_map(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_mapWindowOverwrite : function(actor) {
|
||||
_mapWindowOverwrite : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._mapping, actor)) {
|
||||
this._shellwm.completed_map(actor);
|
||||
shellwm.completed_map(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_destroyWindow : function(actor) {
|
||||
_destroyWindow : function(shellwm, actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_destroy(actor);
|
||||
shellwm.completed_destroy(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -256,33 +177,35 @@ WindowManager.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._destroyWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._destroyWindowOverwrite,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
},
|
||||
|
||||
_destroyWindowDone : function(actor) {
|
||||
_destroyWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._destroying, actor)) {
|
||||
this._shellwm.completed_destroy(actor);
|
||||
shellwm.completed_destroy(actor);
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
}
|
||||
},
|
||||
|
||||
_destroyWindowOverwrite : function(actor) {
|
||||
_destroyWindowOverwrite : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._destroying, actor)) {
|
||||
this._shellwm.completed_destroy(actor);
|
||||
shellwm.completed_destroy(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_switchWorkspace : function(windows, from, to, direction) {
|
||||
_switchWorkspace : function(shellwm, from, to, direction) {
|
||||
if (!this._shouldAnimate()) {
|
||||
this._shellwm.completed_switch_workspace();
|
||||
shellwm.completed_switch_workspace();
|
||||
return;
|
||||
}
|
||||
|
||||
let windows = shellwm.get_switch_workspace_actors();
|
||||
|
||||
/* @direction is the direction that the "camera" moves, so the
|
||||
* screen contents have to move one screen's worth in the
|
||||
* opposite direction.
|
||||
@ -292,20 +215,20 @@ WindowManager.prototype = {
|
||||
if (direction == Meta.MotionDirection.UP ||
|
||||
direction == Meta.MotionDirection.UP_LEFT ||
|
||||
direction == Meta.MotionDirection.UP_RIGHT)
|
||||
yDest = this._global.screen_height;
|
||||
yDest = global.screen_height;
|
||||
else if (direction == Meta.MotionDirection.DOWN ||
|
||||
direction == Meta.MotionDirection.DOWN_LEFT ||
|
||||
direction == Meta.MotionDirection.DOWN_RIGHT)
|
||||
yDest = -this._global.screen_height;
|
||||
yDest = -global.screen_height;
|
||||
|
||||
if (direction == Meta.MotionDirection.LEFT ||
|
||||
direction == Meta.MotionDirection.UP_LEFT ||
|
||||
direction == Meta.MotionDirection.DOWN_LEFT)
|
||||
xDest = this._global.screen_width;
|
||||
xDest = global.screen_width;
|
||||
else if (direction == Meta.MotionDirection.RIGHT ||
|
||||
direction == Meta.MotionDirection.UP_RIGHT ||
|
||||
direction == Meta.MotionDirection.DOWN_RIGHT)
|
||||
xDest = -this._global.screen_width;
|
||||
xDest = -global.screen_width;
|
||||
|
||||
let switchData = {};
|
||||
this._switchData = switchData;
|
||||
@ -313,7 +236,7 @@ WindowManager.prototype = {
|
||||
switchData.outGroup = new Clutter.Group();
|
||||
switchData.windows = [];
|
||||
|
||||
let wgroup = this._global.window_group;
|
||||
let wgroup = global.window_group;
|
||||
wgroup.add_actor(switchData.inGroup);
|
||||
wgroup.add_actor(switchData.outGroup);
|
||||
|
||||
@ -344,7 +267,8 @@ WindowManager.prototype = {
|
||||
time: WINDOW_ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._switchWorkspaceDone,
|
||||
onCompleteScope: this
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [shellwm]
|
||||
});
|
||||
Tweener.addTween(switchData.inGroup,
|
||||
{ x: 0,
|
||||
@ -354,7 +278,7 @@ WindowManager.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
_switchWorkspaceDone : function() {
|
||||
_switchWorkspaceDone : function(shellwm) {
|
||||
let switchData = this._switchData;
|
||||
if (!switchData)
|
||||
return;
|
||||
@ -373,10 +297,10 @@ WindowManager.prototype = {
|
||||
switchData.inGroup.destroy();
|
||||
switchData.outGroup.destroy();
|
||||
|
||||
this._shellwm.completed_switch_workspace();
|
||||
shellwm.completed_switch_workspace();
|
||||
},
|
||||
|
||||
_beginAltTab : function(handler) {
|
||||
_beginAltTab : function(shellwm, handler) {
|
||||
let popup = new AltTab.AltTabPopup();
|
||||
|
||||
handler.connect('window-added', function(handler, window) { popup.addWindow(window); });
|
||||
|
20
po/LINGUAS
Normal file
@ -0,0 +1,20 @@
|
||||
ca
|
||||
cs
|
||||
da
|
||||
de
|
||||
en_GB
|
||||
es
|
||||
fr
|
||||
ga
|
||||
gl
|
||||
hu
|
||||
it
|
||||
ko
|
||||
nb
|
||||
nl
|
||||
pa
|
||||
pl
|
||||
pt_BR
|
||||
sv
|
||||
tr
|
||||
zh_CN
|
9
po/POTFILES.in
Normal file
@ -0,0 +1,9 @@
|
||||
data/gnome-shell.desktop.in.in
|
||||
js/ui/panel.js
|
||||
js/ui/dash.js
|
||||
js/ui/overview.js
|
||||
js/ui/runDialog.js
|
||||
src/gdmuser/gdm-user.c
|
||||
src/shell-global.c
|
||||
src/shell-status-menu.c
|
||||
src/shell-uri-util.c
|
1
po/POTFILES.skip
Normal file
@ -0,0 +1 @@
|
||||
data/gnome-shell.desktop.in
|
189
po/ca.po
Normal file
@ -0,0 +1,189 @@
|
||||
# Catalan gnome-shell translation.
|
||||
# Copyright (C) 2009 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: HEAD\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
|
||||
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
|
||||
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
|
||||
"Language-Team: \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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestió de finestres i execució d'aplicacions"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Activitats"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Cerca..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Navega"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(mostra tot)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633
|
||||
#: ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICACIONS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "LLOCS"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660
|
||||
#: ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTS RECENTS"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RESULTATS DE LA CERCA"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Introduïu una ordre:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Fa menys d'un minut"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Fa %d minut"
|
||||
msgstr[1] "Fa %d minuts"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Fa %d hora"
|
||||
msgstr[1] "Fa %d hores"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Fa %d dia"
|
||||
msgstr[1] "Fa %d dies"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Fa %d setmana"
|
||||
msgstr[1] "Fa %d setmanes"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Desconegut"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "No es pot blocar la pantalla: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "No es pot establir temporalment l'estalvi de pantalla a pantalla negra: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "No es pot sortir: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Informació del compte..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barra lateral"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Preferències del sistema..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Bloca la pantalla"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Canvia d'usuari"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Surt..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Atura..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Carpeta d'inici"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Sistema de fitxers"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%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."
|
||||
|
189
po/cs.po
Normal file
@ -0,0 +1,189 @@
|
||||
# Czech translation 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.
|
||||
# Andre Klapper <ak-47@gmx.net>, 2009.
|
||||
# Petr Kovar <pknbe@volny.cz>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-30 17:37+0200\n"
|
||||
"PO-Revision-Date: 2009-08-30 17:33+0200\n"
|
||||
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
|
||||
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "Prostředí GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Správa oken a spouštění aplikací"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Činnosti"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a, %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Najít..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Procházet"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(zobrazit vše)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLIKACE"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "MÍSTA"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "NEDÁVNÉ DOKUMENTY"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "VÝSLEDKY HLEDÁNÍ"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Zadejte prosím příkaz:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Před méně než minutou"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Před %d minutou"
|
||||
msgstr[1] "Před %d minutami"
|
||||
msgstr[2] "Před %d minutami"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Před %d hodinou"
|
||||
msgstr[1] "Před %d hodinami"
|
||||
msgstr[2] "Před %d hodinami"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Před %d dnem"
|
||||
msgstr[1] "Před %d dny"
|
||||
msgstr[2] "Před %d dny"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Před %d týdnem"
|
||||
msgstr[1] "Před %d týdny"
|
||||
msgstr[2] "Před %d týdny"
|
||||
|
||||
#: ../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"
|
||||
msgstr "Domovská složka"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Systém souborů"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Hledat"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Správce"
|
||||
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."
|
188
po/da.po
Normal file
@ -0,0 +1,188 @@
|
||||
# Danish translation of gnome-shell
|
||||
# Copyright (C) 2009 gnome-shell
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Kris Thomsen <lakristho@gmail.com>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-09-04 01:26+0200\n"
|
||||
"PO-Revision-Date: 2009-09-01 21:48+0200\n"
|
||||
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
||||
"Language-Team: Danish <dansk@dansk-gruppen.dk>\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 "Skal til GNOME"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Vinduehåndtering og åbning af programmer"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Find..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Gennemse"
|
||||
|
||||
#: ../js/ui/dash.js:511
|
||||
msgid "(see all)"
|
||||
msgstr "(se alle)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "PROGRAMMER"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:725
|
||||
msgid "PLACES"
|
||||
msgstr "STEDER"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "SENESTE DOKUMENTER"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "SØGERESULTATER"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Indtast en kommando:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mindre end et minut siden"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minut siden"
|
||||
msgstr[1] "%d minutter siden"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d time siden"
|
||||
msgstr[1] "%d timer siden"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag siden"
|
||||
msgstr[1] "%d dage siden"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d uge siden"
|
||||
msgstr[1] "%d uger siden"
|
||||
|
||||
#: ../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"
|
||||
msgstr "Hjemmemappe"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Filsystem"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Søg"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Find programmer eller dokumenter"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Håndtering"
|
||||
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "Brugerhåndteringsobjektet, denne bruger er styret af."
|
182
po/de.po
Normal file
@ -0,0 +1,182 @@
|
||||
# German gnome-shell translation.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Hendrik Brandt <heb@gnome-de.org>, 2009.
|
||||
# Hendrik Richter <hendrikr@gnome.org>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: HEAD\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-20 16:47+0200\n"
|
||||
"PO-Revision-Date: 2009-08-20 16:49+0200\n"
|
||||
"Last-Translator: Hendrik Richter <hendrikr@gnome.org>\n"
|
||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: UTF-8\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME-Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Fenster verwalten und Anwendungen starten"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr "Aktivitäten"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:251
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Anwendungen oder Dokumente suchen"
|
||||
|
||||
#: ../js/ui/dash.js:369
|
||||
msgid "Browse"
|
||||
msgstr "Durchsuchen"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "ANWENDUNGEN"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:598
|
||||
msgid "PLACES"
|
||||
msgstr "ORTE"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Bitte geben Sie einen Befehl ein:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "Manager"
|
||||
msgstr "Verwaltung"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:244
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "Das Benutzerverwaltungsobjekt welches diesen Benutzer überwacht."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Vor weniger als einer Minute"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Vor %d Minute"
|
||||
msgstr[1] "Vor %d Minuten"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Vor %d Stunde"
|
||||
msgstr[1] "Vor %d Stunden"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Vor %d Tag"
|
||||
msgstr[1] "Vor %d Tagen"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Vor %d Woche"
|
||||
msgstr[1] "Vor %d Wochen"
|
||||
|
||||
#: ../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"
|
||||
msgstr "Persönlicher Ordner"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Dateisystem"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Suchen"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
184
po/en_GB.po
Normal file
@ -0,0 +1,184 @@
|
||||
# British English 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.
|
||||
# Philip Withnall <philip@tecnocode.co.uk>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-12 12:41+0000\n"
|
||||
"PO-Revision-Date: 2009-09-12 12:41+0000\n"
|
||||
"Last-Translator: Philip Withnall <philip@tecnocode.co.uk>\n"
|
||||
"Language-Team: British English <en_GB@li.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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "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 ****
|
||||
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APPLICATIONS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:773
|
||||
msgid "PLACES"
|
||||
msgstr "PLACES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "RECENT DOCUMENTS"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "SEARCH RESULTS"
|
||||
|
||||
#: ../js/ui/dash.js:814
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENCES"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Please enter a command:"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Less than a minute ago"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minute ago"
|
||||
msgstr[1] "%d minutes ago"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d hour ago"
|
||||
msgstr[1] "%d hours ago"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d day ago"
|
||||
msgstr[1] "%d days ago"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d week ago"
|
||||
msgstr[1] "%d weeks ago"
|
||||
|
||||
#: ../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"
|
||||
msgstr "Home Folder"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "File System"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
199
po/es.po
Normal file
@ -0,0 +1,199 @@
|
||||
# Spanish translation of gnome-shell.
|
||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Jorge González <jorgegonz@svn.gnome.org>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-11 21:48+0000\n"
|
||||
"PO-Revision-Date: 2009-09-12 14:40+0200\n"
|
||||
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
|
||||
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: UTF-8\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestión de ventanas e inicio de aplicaciones"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Actividades"
|
||||
|
||||
#. 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 "Buscar…"
|
||||
|
||||
#: ../js/ui/dash.js:400
|
||||
msgid "Browse"
|
||||
msgstr "Examine"
|
||||
|
||||
#: ../js/ui/dash.js:536
|
||||
msgid "(see all)"
|
||||
msgstr "(ver todo)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:736 ../js/ui/dash.js:792
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICACIONES"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:756
|
||||
msgid "PLACES"
|
||||
msgstr "LUGARES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:763 ../js/ui/dash.js:802
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTOS RECIENTES"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:782 ../js/ui/dash.js:907
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RESULTADOS DE LA BÚSQUEDA"
|
||||
|
||||
#: ../js/ui/dash.js:797
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENCIAS"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Introduzca un comando:"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Hace menos de un minuto"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Hace %d minuto"
|
||||
msgstr[1] "Hace %d minutos"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Hace %d hora"
|
||||
msgstr[1] "Hace %d horas"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Hace %d día"
|
||||
msgstr[1] "Hace %d días"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Hace %d semana"
|
||||
msgstr[1] "Hace %d semanas"
|
||||
|
||||
#: ../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"
|
||||
msgstr "Carpeta personal"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Sistema de archivos"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Encuentre aplicaciones o documentos"
|
||||
|
||||
#~| msgid "RECENT DOCUMENTS"
|
||||
#~ msgid "DOCUMENTS"
|
||||
#~ msgstr "DOCUMENTOS"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Gestor"
|
||||
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "El objeto de gestión de usuarios que controla a este usuario."
|
182
po/fr.po
Normal file
@ -0,0 +1,182 @@
|
||||
# French translations for gnome-shell package.
|
||||
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Mathieu Bridon <bochecha@fedoraproject.org>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: HEAD\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-09 21:30+0000\n"
|
||||
"PO-Revision-Date: 2009-09-11 21:40+0200\n"
|
||||
"Last-Translator: Mathieu Bridon <bochecha@fedoraproject.org>\n"
|
||||
"Language-Team: GNOME French Team\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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestion des fenêtres et lancement des applications"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Activités"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:255
|
||||
msgid "Find..."
|
||||
msgstr "Rechercher..."
|
||||
|
||||
#: ../js/ui/dash.js:372
|
||||
msgid "Browse"
|
||||
msgstr "Parcourir"
|
||||
|
||||
#: ../js/ui/dash.js:508
|
||||
msgid "(see all)"
|
||||
msgstr "(tout afficher)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APPLICATIONS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:720
|
||||
msgid "PLACES"
|
||||
msgstr "RACCOURCIS"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTS RÉCENTS"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RÉSULTATS DE LA RECHERCHE"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Veuillez saisir une commande :"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Il y a moins d'une minute"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Il y a %d minute"
|
||||
msgstr[1] "Il y a %d minutes"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Il y a %d heure"
|
||||
msgstr[1] "Il y a %d heures"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Il y a %d jour"
|
||||
msgstr[1] "Il y a %d jours"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Il y a %d semaine"
|
||||
msgstr[1] "Il y a %d semaines"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Inconnu"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Impossible de verrouiller l'écran : %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr ""
|
||||
"Impossible de régler temporairement l'écran de veille sur un écran vide : %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Impossible de fermer la session : %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Informations personnelles..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barre latérale"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Préférences du système..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Verrouiller l'écran"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Changer d'utilisateur"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Fermer la session..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Éteindre..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Dossier personnel"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Système de fichiers"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Recherche"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s : %2$s"
|
181
po/ga.po
Normal file
@ -0,0 +1,181 @@
|
||||
# Irish translations for gnome-shell package.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Seán de Búrca <leftmostcat@gmail.com>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell.master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-15 06:01-0600\n"
|
||||
"PO-Revision-Date: 2009-08-15 06:01-0600\n"
|
||||
"Last-Translator: Seán de Búrca <leftmostcat@gmail.com>\n"
|
||||
"Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : (n%10==1 || n%10==2) ? 1 : (n%"
|
||||
"10>=3 && n%10<= 6) ? 2 : ((n%10>=7 && n%10<=9) || n==10) ? 3 : 4;\n"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr "Gníomhartha"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:412
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#: ../js/ui/dash.js:235
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Aimsigh feidhmchláir nó cáipéisí"
|
||||
|
||||
#: ../js/ui/dash.js:336
|
||||
msgid "Browse"
|
||||
msgstr "Brabhsáil"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "FEIDHMCHLÁIR"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "CÁIPÉISÍ IS DÉANAÍ"
|
||||
|
||||
#. **** Places ****
|
||||
#: ../js/ui/dash.js:563
|
||||
msgid "PLACES"
|
||||
msgstr "ÁITEANNA"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Iontráil ordú, le do thoil:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:242
|
||||
msgid "Manager"
|
||||
msgstr "Bainisteoir"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "An réad bhainisteoir úsáideoirí a rialaíonn an t-úsáideoir seo."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Níos lú ná nóiméad ó shin"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d nóiméad ó shin"
|
||||
msgstr[1] "%d nóiméad ó shin"
|
||||
msgstr[2] "%d nóiméad ó shin"
|
||||
msgstr[3] "%d nóiméad ó shin"
|
||||
msgstr[4] "%d nóiméad ó shin"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d uair ó shin"
|
||||
msgstr[1] "%d uair ó shin"
|
||||
msgstr[2] "%d uaire ó shin"
|
||||
msgstr[3] "%d n-uaire ó shin"
|
||||
msgstr[4] "%d uair ó shin"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d lá ó shin"
|
||||
msgstr[1] "%d lá ó shin"
|
||||
msgstr[2] "%d lá ó shin"
|
||||
msgstr[3] "%d lá ó shin"
|
||||
msgstr[4] "%d lá ó shin"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d seachtain ó shin"
|
||||
msgstr[1] "%d sheachtain ó shin"
|
||||
msgstr[2] "%d sheachtain ó shin"
|
||||
msgstr[3] "%d seachtain ó shin"
|
||||
msgstr[4] "%d seachtain ó shin"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Anaithnid"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Ní féidir scáileán a chur faoi ghlas: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Ní féidir spárálaí scáileáin a shocrú chun scáileán a bhánú: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Ní féidir logáil amach: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Eolas Cuntais..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barra Taoibh"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Sainroghanna an Chórais..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Cuir Scáileán Faoi Ghlas"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Athraigh Úsáideoir"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Logáil Amach..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Múch..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Fillteán Baile"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Córas Comhad"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Cuardaigh"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
194
po/gl.po
Normal file
@ -0,0 +1,194 @@
|
||||
# Galician 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.
|
||||
# Fran Diéguez <fran.dieguez@mabishu.com>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-09-15 23:06+0200\n"
|
||||
"PO-Revision-Date: 2009-09-10 22:32+0100\n"
|
||||
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
|
||||
"Language-Team: Galician <gnome@mancomun.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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Xestor de xanelas e lanzado de aplicativos"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Actividades"
|
||||
|
||||
#. 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 "Buscar..."
|
||||
|
||||
#: ../js/ui/dash.js:400
|
||||
msgid "Browse"
|
||||
msgstr "Explorar"
|
||||
|
||||
#: ../js/ui/dash.js:536
|
||||
msgid "(see all)"
|
||||
msgstr "(ver todos)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICATIVOS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:773
|
||||
msgid "PLACES"
|
||||
msgstr "LUGARES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTOS RECENTES"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RESULTADOS DA BÚSQUEDA"
|
||||
|
||||
#: ../js/ui/dash.js:814
|
||||
msgid "PREFERENCES"
|
||||
msgstr ""
|
||||
|
||||
#: ../js/ui/runDialog.js:96
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Insira unha orde:"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Menos de un minuto"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "fai %d minuto"
|
||||
msgstr[1] "fai %d minutos"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "fai %d hora"
|
||||
msgstr[1] "fai %d horas"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "fai %d día"
|
||||
msgstr[1] "fai %d días"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "fai %d semana"
|
||||
msgstr[1] "fai %d semanas"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Descoñecido"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Non foi posíbel bloquear a pantalla: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr ""
|
||||
"Non foi posíbel establecer o salvapantallas a unha pantalla en branco: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Non foi posíbel pechar a sesión: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Información da conta..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barra lateral"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Preferenzas do sistema..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Bloquear 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 "Pechar sesión..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Apagar..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Cartafol persoal"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Sistema de ficheiros"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Atopar aplicativos ou documentos"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "DOCUMENTS"
|
||||
#~ msgstr "DOCUMENTOS RECENTES"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Xestor"
|
180
po/hu.po
Normal file
@ -0,0 +1,180 @@
|
||||
# Hungarian translation of gnome-shell
|
||||
# Copyright 2009. Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Gabor Kelemen <kelemeng at gnome dot hu>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-15 11:35+0200\n"
|
||||
"PO-Revision-Date: 2009-08-15 11:35+0200\n"
|
||||
"Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
|
||||
"Language-Team: Hungarian <gnome at fsf dot hu>\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"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr "Tevékenységek"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:412
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a., %k.%M"
|
||||
|
||||
#: ../js/ui/dash.js:235
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Alkalmazások vagy dokumentumok keresése"
|
||||
|
||||
#: ../js/ui/dash.js:336
|
||||
msgid "Browse"
|
||||
msgstr "Tallózás"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "ALKALMAZÁSOK"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "LEGUTÓBBI DOKUMENTUMOK"
|
||||
|
||||
#. **** Places ****
|
||||
#: ../js/ui/dash.js:563
|
||||
msgid "PLACES"
|
||||
msgstr "HELYEK"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Adjon meg egy parancsot:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:242
|
||||
msgid "Manager"
|
||||
msgstr "Kezelő"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "A felhasználót kezelő felhasználókezelő objektum."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Kevesebb, mint egy perce"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d perce"
|
||||
msgstr[1] "%d perce"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d órája"
|
||||
msgstr[1] "%d órája"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d napja"
|
||||
msgstr[1] "%d napja"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d hete"
|
||||
msgstr[1] "%d hete"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Ismeretlen"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Nem lehet zárolni a képernyőt: %s "
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr ""
|
||||
"Átmenetileg nem lehet beállítani a képernyővédőt a képernyő elsötétítésére: %"
|
||||
"s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Nem lehet kijelentkezni: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Fiókinformációk…"
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Oldalsáv"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Rendszerbeállítások…"
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Képernyő zárolása"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Felhasználóváltás"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Kijelentkezés…"
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Leállítás…"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Ablakkezelés és alkalmazásindítás"
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Saját mappa"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Fájlrendszer"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Oldalsáv"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
197
po/it.po
Normal file
@ -0,0 +1,197 @@
|
||||
# Italian translations for gnome-shell package.
|
||||
# Copyright (C) 2009 the gnome-shell copyright holder
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Milo Casagrande <milo@ubuntu.com>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-05 00:19+0000\n"
|
||||
"PO-Revision-Date: 2009-09-06 18:31+0200\n"
|
||||
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
|
||||
"Language-Team: Italian <tp@lists.linux.it>\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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestione finestre e avvio applicazioni"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Attività"
|
||||
|
||||
# (ndt) proviamo col k, se non funge, sappiamo il perché...
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %k.%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Trova..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Esplora"
|
||||
|
||||
#: ../js/ui/dash.js:511
|
||||
msgid "(see all)"
|
||||
msgstr "(vedi tutto)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "Applicazioni"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:725
|
||||
msgid "PLACES"
|
||||
msgstr "Risorse"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "Documenti recenti"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "Risultati ricerca"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Inserire un comando:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Meno di un minuto fa"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuto fa"
|
||||
msgstr[1] "%d minuti fa"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d ora fa"
|
||||
msgstr[1] "%d ore fa"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d giorno fa"
|
||||
msgstr[1] "%d giorni fa"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d settimana fa"
|
||||
msgstr[1] "%d settimane fa"
|
||||
|
||||
# (ndt) valutare se vada al femminile
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Sconosciuto"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Impossibile bloccare lo schermo: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr ""
|
||||
"Impossibile impostare temporaneamente il salva schermo a schermo nero: %s "
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Impossibile terminare la sessione: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Informazioni account..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barra laterale"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Preferenze di sistema..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Blocca schermo"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Cambia utente"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Termina sessione..."
|
||||
|
||||
# (ndt) da valutare... pare che ora anche Windows usi 'Arresta...'...
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Spegni..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Cartella home"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "File system"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
# (ndt) valutare...
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Trova programmi e documenti"
|
||||
|
||||
# (ndt) no idea...
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Manager"
|
||||
|
||||
# (ndt) no idea...
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "L'oggetto user manager che controlla questo utente."
|
166
po/ko.po
Normal file
@ -0,0 +1,166 @@
|
||||
# gnome-shell korean translation.
|
||||
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Young-Ho Cha <ganadist@gmail.com>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-21 10:09+0900\n"
|
||||
"PO-Revision-Date: 2009-08-21 10:10+0900\n"
|
||||
"Last-Translator: Young-Ho Cha <ganadist@gmail.com>\n"
|
||||
"Language-Team: GNOME Korea <gnome-kr-hackers@lists.kldp.net>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "그놈 쉘"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "창 관리와 프로그램 시작"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%A %p %l:%M"
|
||||
|
||||
#: ../js/ui/dash.js:250
|
||||
msgid "Find apps or documents"
|
||||
msgstr "프로그램과 문서를 찾습니다"
|
||||
|
||||
#: ../js/ui/dash.js:368
|
||||
msgid "Browse"
|
||||
msgstr "찾아보기"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:504 ../js/ui/dash.js:577
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "프로그램"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:509 ../js/ui/dash.js:604
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "최근 문서"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:597
|
||||
msgid "PLACES"
|
||||
msgstr "위치"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
msgid "Please enter a command:"
|
||||
msgstr "명령을 입력하십시오:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "1분 이내"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d분 전"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d시간 전"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d일 전"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d주 전"
|
||||
|
||||
#: ../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"
|
||||
msgstr "내 폴더"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "파일시스템"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%s: %s"
|
170
po/nb.po
Normal file
@ -0,0 +1,170 @@
|
||||
# Norwegian bokmål translation of gnome-shell.
|
||||
# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Kjartan Maraas <kmaraas@broadpark.no>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell 0.4\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-21 12:36+0200\n"
|
||||
"PO-Revision-Date: 2009-08-21 12:44+0200\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@broadpark.no>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Vindushåndtering og oppstart av programmer"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M"
|
||||
|
||||
#: ../js/ui/dash.js:250
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Finn programmer eller dokumenter"
|
||||
|
||||
#: ../js/ui/dash.js:368
|
||||
msgid "Browse"
|
||||
msgstr "Bla gjennom"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:504 ../js/ui/dash.js:577
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "PROGRAMMER"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:509 ../js/ui/dash.js:604
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "SISTE DOKUMENTER"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:597
|
||||
msgid "PLACES"
|
||||
msgstr "STEDER"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Oppgi en kommando:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mindre enn ett minutt siden"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minutt siden"
|
||||
msgstr[1] "%d minutter siden"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d time siden"
|
||||
msgstr[1] "%d timer siden"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag siden"
|
||||
msgstr[1] "%d dager siden"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d uke siden"
|
||||
msgstr[1] "%d uker siden"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Ukjent"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Kan ikke låse skjermen: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Kan ikke sette skjermsparer midlertidig til blank skjerm: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Kan ikke logge ut: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Kontoinformasjon..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Sidelinje"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Brukervalg for systemet..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Lås skjerm"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Bytt bruker"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Logg ut..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Slå av..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Hjemmemappe"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Filsystem"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Søk"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
179
po/nl.po
Normal file
@ -0,0 +1,179 @@
|
||||
# Dutch translation for gnome-shell
|
||||
#
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Sander Dijkhuis <sander.dijkhuis@gmail.com>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-29 14:37+0200\n"
|
||||
"PO-Revision-Date: 2009-08-29 15:10+0200\n"
|
||||
"Last-Translator: Sander Dijkhuis <sander.dijkhuis@gmail.com>\n"
|
||||
"Language-Team: Dutch <vertaling@vrijschrift.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 Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Vensterbeheer en toepassingen starten"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Activiteiten"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:451
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %k:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Zoeken…"
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Bladeren"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(alles tonen)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:634 ../js/ui/dash.js:682
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "TOEPASSINGEN"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:654
|
||||
msgid "PLACES"
|
||||
msgstr "LOCATIES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:661 ../js/ui/dash.js:694
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "RECENTE DOCUMENTEN"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:680
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "ZOEKRESULTATEN"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Voer een opdracht in:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Korter dan een minuut geleden"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuut geleden"
|
||||
msgstr[1] "%d minuten geleden"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d uur geleden"
|
||||
msgstr[1] "%d uur geleden"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag geleden"
|
||||
msgstr[1] "%d dagen geleden"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d week geleden"
|
||||
msgstr[1] "%d weken geleden"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Onbekend"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Kan het scherm niet vergrendelen: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Kan de schermbeveiliging niet tijdelijk als zwart scherm instellen: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Kan niet afmelden: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Account-informatie…"
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Zijbalk"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Systeemvoorkeuren…"
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Scherm vergrendelen"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Gebruiker wisselen"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Afmelden…"
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Afsluiten…"
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Persoonlijke map"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Bestandssysteem"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Zoeken"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
182
po/pa.po
Normal file
@ -0,0 +1,182 @@
|
||||
# Punjabi 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.
|
||||
#
|
||||
# A S Alam <aalam@users.sf.net>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
|
||||
"cgi?product=gnome-shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-08-31 22:31+0000\n"
|
||||
"PO-Revision-Date: 2009-09-01 06:51+0530\n"
|
||||
"Last-Translator: A S Alam <aalam@users.sf.net>\n"
|
||||
"Language-Team: Punjabi/Panjabi <punjabi-users@lists.sf.net>\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: Lokalize 1.0\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "ਗਨੋਮ ਸ਼ੈਲ"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "ਵਿੰਡੋ ਪਰਬੰਧ ਅਤੇ ਐਪਲੀਕੇਸ਼ਨ ਚਲਾਓ"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "ਸਰਗਰਮੀਆਂ"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "ਖੋਜ..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "ਝਲਕ"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(ਸਭ ਵੇਖੋ)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "ਥਾਵਾਂ"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "ਤਾਜ਼ਾ ਡੌਕੂਮੈਂਟ"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "ਖੋਜ ਨਤੀਜੇ"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "ਕਮਾਂਡ ਦਿਓ ਜੀ:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "ਇੱਕ ਮਿੰਟ ਤੋਂ ਘੱਟ ਚਿਰ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d ਘੰਟਾ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਘੰਟੇ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d ਦਿਨ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਦਿਨ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d ਹਫ਼ਤਾ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਹਫ਼ਤੇ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../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"
|
||||
msgstr "ਘਰ ਫੋਲਡਰ"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "ਫਾਇਲ ਸਿਸਟਮ"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
188
po/pl.po
Normal file
@ -0,0 +1,188 @@
|
||||
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
# Aviary.pl
|
||||
# Jeśli masz jakiekolwiek uwagi odnoszące się do tłumaczenia lub chcesz
|
||||
# pomóc w jego rozwijaniu i pielęgnowaniu, napisz do nas:
|
||||
# gnomepl@aviary.pl
|
||||
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-09-09 03:06+0200\n"
|
||||
"PO-Revision-Date: 2009-09-09 03:02+0100\n"
|
||||
"Last-Translator: Tomasz Dominikowski <dominikowski@gmail.com>\n"
|
||||
"Language-Team: Polish <gnomepl@aviary.pl>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
"X-Poedit-Language: Polish\n"
|
||||
"X-Poedit-Country: Poland\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "Powłoka środowiska GNOME"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Zarządzanie oknami i uruchamianiem programów"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Czynności"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a, %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:255
|
||||
msgid "Find..."
|
||||
msgstr "Znajdź..."
|
||||
|
||||
#: ../js/ui/dash.js:372
|
||||
msgid "Browse"
|
||||
msgstr "Przeglądaj"
|
||||
|
||||
#: ../js/ui/dash.js:508
|
||||
msgid "(see all)"
|
||||
msgstr "(wyświetl wszystko)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "Programy"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:720
|
||||
msgid "PLACES"
|
||||
msgstr "Miejsca"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "Ostatnie dokumenty"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "Wyniki wyszukiwania"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Proszę wprowadzić polecenie:"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mniej niż minutę temu"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuta temu"
|
||||
msgstr[1] "%d minuty temu"
|
||||
msgstr[2] "%d minut temu"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d godzina temu"
|
||||
msgstr[1] "%d godziny temu"
|
||||
msgstr[2] "%d godzin temu"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dzień temu"
|
||||
msgstr[1] "%d dni temu"
|
||||
msgstr[2] "%d dni temu"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d tydzień temu"
|
||||
msgstr[1] "%d tygodnie temu"
|
||||
msgstr[2] "%d tygodni temu"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Nieznane"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Nie można zablokować ekranu: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr ""
|
||||
"Nie można tymczasowo ustawić wygaszacza ekranu na wygaszenie ekranu: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Nie można się wylogować: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Informacje o koncie..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Panel boczny"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Preferencje systemu..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Zablokuj ekran"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Przełącz użytkownika"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Wyloguj się..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Wyłącz komputer..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Katalog domowy"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "System plików"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Wyszukaj"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
144
po/pt_BR.po
Normal file
@ -0,0 +1,144 @@
|
||||
# Portuguese translations for gnome-shell package.
|
||||
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Og Maciel <ogmaciel@gnome.org>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-14 17:53-0400\n"
|
||||
"PO-Revision-Date: 2009-08-14 17:53-0400\n"
|
||||
"Last-Translator: Og Maciel <ogmaciel@gnome.org>\n"
|
||||
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.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"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr "Atividades"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:412
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#: ../js/ui/dash.js:235
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Localizar aplicativos ou documentos"
|
||||
|
||||
#: ../js/ui/dash.js:336
|
||||
msgid "Browse"
|
||||
msgstr "Navegar"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICATIVOS"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTOS RECENTES"
|
||||
|
||||
#. **** Places ****
|
||||
#: ../js/ui/dash.js:563
|
||||
msgid "PLACES"
|
||||
msgstr "LOCAIS"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Por favor digite um comando:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:242
|
||||
msgid "Manager"
|
||||
msgstr "Gerenciador"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "O objeto gerenciador de usuários que controla este usuário."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Menos de um minuto atrás"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuto atrás"
|
||||
msgstr[1] "%d minutos atrás"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d hora atrás"
|
||||
msgstr[1] "%d horas atrás"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dia atrás"
|
||||
msgstr[1] "%d dias atrás"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d semana atrás"
|
||||
msgstr[1] "%d semanas atrás"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Desconhecido"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Não foi possível travar a tela: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Não foi possível definir a proteção de tela para uma tela vazia: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Não foi possível encerrar a sessão: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Informação da conta..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barra lateral"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Preferências do sistema..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Travar a tela"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Alternar usuário"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Encerrar sessão..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Desligar..."
|
191
po/sv.po
Normal file
@ -0,0 +1,191 @@
|
||||
# Swedish translation for gnome-shell.
|
||||
# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Daniel Nylander <po@danielnylander.se>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-09-01 00:31+0200\n"
|
||||
"PO-Revision-Date: 2009-09-01 00:31+0100\n"
|
||||
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
|
||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\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-skal"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Fönsterhantering och programstarter"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H.%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Sök..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Bläddra"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(se alla)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633
|
||||
#: ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "PROGRAM"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "PLATSER"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660
|
||||
#: ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "SENASTE DOKUMENT"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "SÖKRESULTAT"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Ange ett kommando:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mindre än en minut sedan"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minut sedan"
|
||||
msgstr[1] "%d minuter sedan"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d timme sedan"
|
||||
msgstr[1] "%d timmar sedan"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag sedan"
|
||||
msgstr[1] "%d dagar sedan"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d vecka sedan"
|
||||
msgstr[1] "%d veckor sedan"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Okänt"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Kan inte låsa skärmen: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Kan inte temporärt ställa in skärmsläckaren till blank skärm: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Kan inte logga ut: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Kontoinformation..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Sidopanel"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Systeminställningar..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Lås skärmen"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Växla användare"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Logga ut..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Stäng av..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Hemmapp"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Filsystem"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Sök"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Hitta program eller dokument"
|
||||
#~ msgid "DOCUMENTS"
|
||||
#~ msgstr "DOKUMENT"
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Hanterare"
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "Användarhanteringsobjektet som denna användare styrs av."
|
||||
|
166
po/tr.po
Normal file
@ -0,0 +1,166 @@
|
||||
# gnome-shell
|
||||
# Copyright (C) 2009
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Baris Cicek <baris@teamforce.name.tr>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-21 00:41+0300\n"
|
||||
"PO-Revision-Date: 2009-08-21 00:40+0300\n"
|
||||
"Last-Translator: Baris Cicek <baris@teamforce.name.tr>\n"
|
||||
"Language-Team: Turkish <gnome-turk@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Kabuğu"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Pencere yönetimi ve uygulama başlatma"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
msgid "Activities"
|
||||
msgstr "Etkinlikler"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:251
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Uygulamalar ve belgeler bul"
|
||||
|
||||
#: ../js/ui/dash.js:369
|
||||
msgid "Browse"
|
||||
msgstr "Göz at"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "UYGULAMALAR"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "SON ERİŞİLEN BELGELER"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:598
|
||||
msgid "PLACES"
|
||||
msgstr "YERLER"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Lütfen bir komut girin:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Bir dakikadan daha az süre önce"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d dakika önce"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d saat önce"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d gün önce"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d hafta önce"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Bilinmeyen"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Ekran kilitlenemedi: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Ekran koruyucu geçici olarak boş ekran olarak atanamadı: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Çıkış yapılamadı: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Hesap Bilgisi..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Kenar Çubuğu"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Sistem Tercihleri..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Ekrani Kilitle"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Kullanıcı Değiştir"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Çıkış..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Kapat..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Ev Klasörü"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Dosya Sistemi"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Arama"
|
||||
|
||||
#. 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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
176
po/zh_CN.po
Normal file
@ -0,0 +1,176 @@
|
||||
# Chinese (China) 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.
|
||||
# Ray Wang <raywang@gnome.org>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-08-29 19:32+0000\n"
|
||||
"PO-Revision-Date: 2009-08-30 00:08+0800\n"
|
||||
"Last-Translator: Ray Wang <raywang@gnome.org>\n"
|
||||
"Language-Team: Chinese (Simplified) <i18n-zh@googlegroups.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: utf-8\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "窗口管理和应用程序启动"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "活动"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%A %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "查找..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "浏览"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(查看所有)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "应用程序"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "位置"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "最近的文档"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "搜索结果"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "请输入一个命令:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "少于一分钟前"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d 分钟前"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d 小时前"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d 天前"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d 周前"
|
||||
|
||||
#: ../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"
|
||||
msgstr "主文件夹"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "文件系统"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
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:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
@ -33,21 +33,21 @@ big_source_c = \
|
||||
big-enum-types.h: stamp-big-enum-types.h Makefile
|
||||
@true
|
||||
stamp-big-enum-types.h: $(big_source_h) big/big-enum-types.h.in
|
||||
( cd $(srcdir) && \
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/big/big-enum-types.h.in \
|
||||
$(big_source_h) ) >> xgen-teth && \
|
||||
(cmp xgen-teth big-enum-types.h || cp xgen-teth big-enum-types.h) && \
|
||||
rm -f xgen-teth && \
|
||||
$(big_source_h) ) >> xgen-beth && \
|
||||
(cmp -s xgen-beth big-enum-types.h || cp xgen-beth big-enum-types.h) && \
|
||||
rm -f xgen-beth && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
big-enum-types.c: stamp-big-enum-types.h big/big-enum-types.c.in
|
||||
( cd $(srcdir) && \
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/big/big-enum-types.c.in \
|
||||
$(big_source_h) ) >> xgen-tetc && \
|
||||
cp xgen-tetc big-enum-types.c && \
|
||||
rm -f xgen-tetc
|
||||
$(big_source_h) ) >> xgen-betc && \
|
||||
cp xgen-betc big-enum-types.c && \
|
||||
rm -f xgen-betc
|
||||
|
||||
noinst_LTLIBRARIES += libbig-1.0.la
|
||||
|
||||
|
117
src/Makefile-nbtk.am
Normal file
@ -0,0 +1,117 @@
|
||||
nbtk_cflags = \
|
||||
-I$(top_srcdir)/src \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DG_LOG_DOMAIN=\"Nbtk\" \
|
||||
-DNBTK_COMPILATION \
|
||||
$(NBTK_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
nbtk_built_sources = \
|
||||
nbtk-enum-types.h \
|
||||
nbtk-enum-types.c \
|
||||
nbtk-marshal.h \
|
||||
nbtk-marshal.c
|
||||
|
||||
BUILT_SOURCES += $(nbtk_built_sources)
|
||||
|
||||
EXTRA_DIST += \
|
||||
nbtk/nbtk-marshal.list \
|
||||
nbtk/nbtk-enum-types.h.in \
|
||||
nbtk/nbtk-enum-types.c.in
|
||||
|
||||
CLEANFILES += stamp-nbtk-marshal.h stamp-nbtk-enum-types.h
|
||||
|
||||
nbtk-marshal.h: stamp-nbtk-marshal.h
|
||||
@true
|
||||
stamp-nbtk-marshal.h: Makefile nbtk/nbtk-marshal.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
|
||||
--prefix=_nbtk_marshal \
|
||||
--header \
|
||||
$(srcdir)/nbtk/nbtk-marshal.list > $@.tmp && \
|
||||
(cmp -s $@.tmp nbtk-marshal.h || cp -f $@.tmp nbtk-marshal.h) && \
|
||||
rm -f $@.tmp && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
nbtk-marshal.c: Makefile nbtk/nbtk-marshal.list
|
||||
$(AM_V_GEN) (echo "#include \"nbtk-marshal.h\"" ; \
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_nbtk_marshal \
|
||||
--body \
|
||||
$(srcdir)/nbtk/nbtk-marshal.list ) > $@.tmp && \
|
||||
cp -f $@.tmp nbtk-marshal.c && \
|
||||
rm -f $@.tmp
|
||||
|
||||
nbtk-enum-types.h: stamp-nbtk-enum-types.h Makefile
|
||||
@true
|
||||
stamp-nbtk-enum-types.h: $(source_h) nbtk/nbtk-enum-types.h.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template nbtk/nbtk-enum-types.h.in \
|
||||
$(nbtk_source_h) ) >> $@.tmp && \
|
||||
(cmp -s $@.tmp nbtk-enum-types.h || cp $@.tmp nbtk-enum-types.h) && \
|
||||
rm -f $@.tmp && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
nbtk-enum-types.c: stamp-nbtk-enum-types.h nbtk/nbtk-enum-types.c.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template nbtk/nbtk-enum-types.c.in \
|
||||
$(nbtk_source_h) ) >> $@.tmp && \
|
||||
cp $@.tmp $@ && \
|
||||
rm -f $@.tmp
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
nbtk_source_h = \
|
||||
nbtk/nbtk-adjustment.h \
|
||||
nbtk/nbtk-bin.h \
|
||||
nbtk/nbtk-box-layout.h \
|
||||
nbtk/nbtk-box-layout-child.h \
|
||||
nbtk/nbtk-button.h \
|
||||
nbtk/nbtk-clipboard.h \
|
||||
nbtk/nbtk-entry.h \
|
||||
nbtk/nbtk-label.h \
|
||||
nbtk/nbtk-private.h \
|
||||
nbtk/nbtk-scrollable.h \
|
||||
nbtk/nbtk-scroll-bar.h \
|
||||
nbtk/nbtk-scroll-view.h \
|
||||
nbtk/nbtk-subtexture.h \
|
||||
nbtk/nbtk-texture-cache.h \
|
||||
nbtk/nbtk-texture-frame.h \
|
||||
nbtk/nbtk-tooltip.h \
|
||||
nbtk/nbtk-types.h \
|
||||
nbtk/nbtk-widget.h \
|
||||
$(NULL)
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
nbtk_source_c = \
|
||||
nbtk/nbtk-adjustment.c \
|
||||
nbtk/nbtk-bin.c \
|
||||
nbtk/nbtk-box-layout.c \
|
||||
nbtk/nbtk-box-layout-child.c \
|
||||
nbtk/nbtk-button.c \
|
||||
nbtk/nbtk-clipboard.c \
|
||||
nbtk/nbtk-entry.c \
|
||||
nbtk/nbtk-label.c \
|
||||
nbtk/nbtk-private.c \
|
||||
nbtk/nbtk-scrollable.c \
|
||||
nbtk/nbtk-scroll-bar.c \
|
||||
nbtk/nbtk-scroll-view.c \
|
||||
nbtk/nbtk-subtexture.c \
|
||||
nbtk/nbtk-texture-cache.c \
|
||||
nbtk/nbtk-texture-frame.c \
|
||||
nbtk/nbtk-tooltip.c \
|
||||
nbtk/nbtk-widget.c \
|
||||
$(NULL)
|
||||
|
||||
noinst_LTLIBRARIES += libnbtk-1.0.la
|
||||
|
||||
libnbtk_1_0_la_LIBADD = $(NBTK_LIBS)
|
||||
libnbtk_1_0_la_SOURCES = \
|
||||
$(nbtk_source_c) \
|
||||
$(nbtk_source_h) \
|
||||
$(nbtk_built_sources) \
|
||||
$(NULL)
|
||||
libnbtk_1_0_la_CPPFLAGS = $(nbtk_cflags)
|
||||
libnbtk_1_0_la_LDFLAGS = $(LDADD)
|
@ -1,17 +0,0 @@
|
||||
gnomeshell_taskpanel_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DWNCK_I_KNOW_THIS_IS_UNSTABLE \
|
||||
-DG_LOG_DOMAIN=\"gnomeshell-taskpanel\" \
|
||||
$(TASKPANEL_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
gnomeshell_taskpanel_SOURCES = \
|
||||
gnomeshell-taskpanel.c \
|
||||
shell-panel-window.c \
|
||||
shell-panel-window.h \
|
||||
$(NULL)
|
||||
|
||||
gnomeshell_taskpanel_LDADD = $(TASKPANEL_LIBS)
|
||||
|
||||
libexec_PROGRAMS += gnomeshell-taskpanel
|
@ -1,89 +0,0 @@
|
||||
tidy_cflags = \
|
||||
-I$(top_srcdir)/src \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DG_LOG_DOMAIN=\"Tidy\" \
|
||||
$(MUTTER_PLUGIN_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
tidy_built_sources = \
|
||||
tidy-enum-types.h \
|
||||
tidy-enum-types.c \
|
||||
tidy-marshal.h \
|
||||
tidy-marshal.c
|
||||
|
||||
BUILT_SOURCES += $(tidy_built_sources)
|
||||
|
||||
TIDY_STAMP_FILES = stamp-tidy-marshal.h stamp-tidy-enum-types.h
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
tidy_source_h = \
|
||||
tidy/tidy-grid.h \
|
||||
$(NULL)
|
||||
|
||||
tidy_source_h_priv = \
|
||||
$(NULL)
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
tidy_source_c = \
|
||||
tidy/tidy-grid.c \
|
||||
$(NULL)
|
||||
|
||||
tidy-marshal.h: stamp-tidy-marshal.h
|
||||
@true
|
||||
stamp-tidy-marshal.h: Makefile tidy/tidy-marshal.list
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_tidy_marshal \
|
||||
--header \
|
||||
$(srcdir)/tidy/tidy-marshal.list > xgen-tmh && \
|
||||
(cmp -s xgen-tmh tidy-marshal.h || cp -f xgen-tmh tidy-marshal.h) && \
|
||||
rm -f xgen-tmh && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
tidy-marshal.c: Makefile tidy/tidy-marshal.list
|
||||
(echo "#include \"tidy-marshal.h\"" ; \
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_tidy_marshal \
|
||||
--body \
|
||||
$(srcdir)/tidy/tidy-marshal.list ) > xgen-tmc && \
|
||||
cp -f xgen-tmc tidy-marshal.c && \
|
||||
rm -f xgen-tmc
|
||||
|
||||
tidy-enum-types.h: stamp-tidy-enum-types.h Makefile
|
||||
@true
|
||||
stamp-tidy-enum-types.h: $(tidy_source_h) tidy/tidy-enum-types.h.in
|
||||
( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/tidy/tidy-enum-types.h.in \
|
||||
$(tidy_source_h) ) >> xgen-teth && \
|
||||
(cmp xgen-teth tidy-enum-types.h || cp xgen-teth tidy-enum-types.h) && \
|
||||
rm -f xgen-teth && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
tidy-enum-types.c: stamp-tidy-enum-types.h tidy/tidy-enum-types.c.in
|
||||
( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/tidy/tidy-enum-types.c.in \
|
||||
$(tidy_source_h) ) >> xgen-tetc && \
|
||||
cp xgen-tetc tidy-enum-types.c && \
|
||||
rm -f xgen-tetc
|
||||
|
||||
noinst_LTLIBRARIES += libtidy-1.0.la
|
||||
|
||||
libtidy_1_0_la_LIBADD = $(TIDY_LIBS)
|
||||
libtidy_1_0_la_SOURCES = \
|
||||
$(tidy_source_c) \
|
||||
$(tidy_source_h) \
|
||||
$(tidy_source_h_priv) \
|
||||
$(tidy_built_sources) \
|
||||
$(NULL)
|
||||
libtidy_1_0_la_CPPFLAGS = $(tidy_cflags)
|
||||
libtidy_1_0_la_LDFLAGS = $(LDADD)
|
||||
|
||||
CLEANFILES += $(TIDY_STAMP_FILES) $(BUILT_SOURCES)
|
||||
|
||||
EXTRA_DIST += \
|
||||
tidy/tidy-enum-types.h.in \
|
||||
tidy/tidy-enum-types.c.in \
|
||||
tidy/tidy-marshal.list
|
36
src/Makefile-toolkit.am
Normal file
@ -0,0 +1,36 @@
|
||||
toolkit_cflags = \
|
||||
-I$(top_srcdir)/src \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DG_LOG_DOMAIN=\"Shell\" \
|
||||
$(TOOLKIT_CFLAGS)
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
toolkit_sources = \
|
||||
toolkit/shell-border-image.c \
|
||||
toolkit/shell-border-image.h \
|
||||
toolkit/shell-theme.c \
|
||||
toolkit/shell-theme.h \
|
||||
toolkit/shell-theme-context.c \
|
||||
toolkit/shell-theme-context.h \
|
||||
toolkit/shell-theme-node.c \
|
||||
toolkit/shell-theme-node.h \
|
||||
toolkit/shell-theme-private.h
|
||||
|
||||
non_gir_toolkit_sources = \
|
||||
toolkit/shell-theme-private.h
|
||||
|
||||
noinst_LTLIBRARIES += libshell-toolkit.la
|
||||
|
||||
libshell_toolkit_la_LIBADD = $(TOOLKIT_LIBS)
|
||||
libshell_toolkit_la_SOURCES = $(toolkit_sources) $(toolkit_built_sources)
|
||||
libshell_toolkit_la_CPPFLAGS = $(toolkit_cflags)
|
||||
libshell_toolkit_la_LDFLAGS = $(LDADD)
|
||||
|
||||
noinst_PROGRAMS += test-theme
|
||||
|
||||
test_theme_CPPFLAGS = $(toolkit_cflags)
|
||||
test_theme_LDADD = libshell-toolkit.la
|
||||
|
||||
test_theme_SOURCES = toolkit/test-theme.c
|
@ -24,7 +24,7 @@ tray_source = \
|
||||
na-marshal.h: stamp-na-marshal.h
|
||||
@true
|
||||
stamp-na-marshal.h: Makefile tray/na-marshal.list
|
||||
$(GLIB_GENMARSHAL) \
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
|
||||
--prefix=_na_marshal \
|
||||
--header \
|
||||
$(srcdir)/tray/na-marshal.list > xgen-tmh && \
|
||||
@ -33,7 +33,7 @@ stamp-na-marshal.h: Makefile tray/na-marshal.list
|
||||
echo timestamp > $(@F)
|
||||
|
||||
na-marshal.c: Makefile tray/na-marshal.list
|
||||
(echo "#include \"na-marshal.h\"" ; \
|
||||
$(AM_V_GEN) (echo "#include \"na-marshal.h\"" ; \
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_na_marshal \
|
||||
--body \
|
||||
|
153
src/Makefile.am
@ -1,34 +1,40 @@
|
||||
NULL =
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES =
|
||||
EXTRA_DIST =
|
||||
EXTRA_DIST =
|
||||
libexec_PROGRAMS =
|
||||
noinst_LTLIBRARIES =
|
||||
noinst_LTLIBRARIES =
|
||||
noinst_PROGRAMS =
|
||||
|
||||
.AUTOPARALLEL:
|
||||
|
||||
bin_SCRIPTS = gnome-shell
|
||||
|
||||
gnome-shell: gnome-shell.in
|
||||
sed -e "s|@MUTTER_BIN_DIR[@]|$(MUTTER_BIN_DIR)|" \
|
||||
$(AM_V_GEN) sed -e "s|@MUTTER_BIN_DIR[@]|$(MUTTER_BIN_DIR)|" \
|
||||
-e "s|@GJS_JS_DIR[@]|$(GJS_JS_DIR)|" \
|
||||
-e "s|@GJS_JS_NATIVE_DIR[@]|$(GJS_JS_NATIVE_DIR)|" \
|
||||
-e "s|@libexecdir[@]|$(libexecdir)|" \
|
||||
-e "s|@libdir[@]|$(libdir)|" \
|
||||
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
|
||||
-e "s|@PYTHON[@]|$(PYTHON)|" \
|
||||
-e "s|@sysconfdir[@]|$(sysconfdir)|" \
|
||||
$< > $@ && chmod a+x $@
|
||||
CLEANFILES += gnome-shell
|
||||
EXTRA_DIST += gnome-shell.in
|
||||
|
||||
include Makefile-tidy.am
|
||||
include Makefile-big.am
|
||||
include Makefile-gdmuser.am
|
||||
include Makefile-nbtk.am
|
||||
include Makefile-toolkit.am
|
||||
include Makefile-tray.am
|
||||
include Makefile-taskpanel.am
|
||||
|
||||
gnome_shell_cflags = \
|
||||
$(MUTTER_PLUGIN_CFLAGS) \
|
||||
$(LIBGNOMEUI_CFLAGS) \
|
||||
-I$(srcdir)/tray \
|
||||
-DGETTEXT_PACKAGE=gnome-shell \
|
||||
-DGETTEXT_PACKAGE=\"gnome-shell\" \
|
||||
-DLOCALEDIR=\"$(datadir)/locale\" \
|
||||
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
|
||||
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DJSDIR=\"$(pkgdatadir)/js\"
|
||||
@ -57,25 +63,43 @@ libgnome_shell_la_SOURCES = \
|
||||
shell-app-system.h \
|
||||
shell-arrow.c \
|
||||
shell-arrow.h \
|
||||
shell-button-box.c \
|
||||
shell-button-box.h \
|
||||
shell-drawing.c \
|
||||
shell-drawing.h \
|
||||
shell-drawing-area.c \
|
||||
shell-drawing-area.h \
|
||||
shell-embedded-window.c \
|
||||
shell-embedded-window.h \
|
||||
shell-embedded-window-private.h \
|
||||
shell-gconf.c \
|
||||
shell-gconf.h \
|
||||
shell-generic-container.c \
|
||||
shell-generic-container.h \
|
||||
shell-gtk-embed.c \
|
||||
shell-gtk-embed.h \
|
||||
shell-menu.c \
|
||||
shell-menu.h \
|
||||
shell-overflow-list.c \
|
||||
shell-overflow-list.h \
|
||||
shell-process.c \
|
||||
shell-process.h \
|
||||
shell-global.c \
|
||||
shell-global.h \
|
||||
shell-status-menu.c \
|
||||
shell-status-menu.h \
|
||||
shell-stack.c \
|
||||
shell-stack.h \
|
||||
shell-tray-manager.c \
|
||||
shell-tray-manager.h \
|
||||
shell-texture-cache.c \
|
||||
shell-texture-cache.h \
|
||||
shell-uri-util.c \
|
||||
shell-uri-util.h \
|
||||
shell-wm.c \
|
||||
shell-wm.h
|
||||
|
||||
non_gir_sources = \
|
||||
non_gir_sources = \
|
||||
shell-embedded-window-private.h
|
||||
|
||||
shell_recorder_sources = \
|
||||
@ -93,7 +117,7 @@ if BUILD_RECORDER
|
||||
libgnome_shell_la_SOURCES += $(shell_recorder_sources)
|
||||
non_gir_sources += $(shell_recorder_non_gir_sources)
|
||||
|
||||
noinst_PROGRAMS = test-recorder
|
||||
noinst_PROGRAMS += test-recorder
|
||||
|
||||
test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS)
|
||||
test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
|
||||
@ -104,50 +128,53 @@ test_recorder_SOURCES = \
|
||||
endif BUILD_RECORDER
|
||||
|
||||
libgnome_shell_la_gir_sources = \
|
||||
$(filter-out $(non_gir_sources), $(libgnome_shell_la_SOURCES))
|
||||
$(filter-out $(non_gir_sources) $(non_gir_toolkit_sources), $(libgnome_shell_la_SOURCES) $(toolkit_sources))
|
||||
|
||||
shell-marshal.h: stamp-shell-marshal.h
|
||||
@true
|
||||
stamp-shell-marshal.h: Makefile shell-marshal.list
|
||||
$(GLIB_GENMARSHAL) \
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
|
||||
--prefix=_shell_marshal \
|
||||
--header \
|
||||
$(srcdir)/shell-marshal.list > xgen-tmh && \
|
||||
(cmp -s xgen-tmh shell-marshal.h || cp -f xgen-tmh shell-marshal.h) && \
|
||||
rm -f xgen-tmh && \
|
||||
$(srcdir)/shell-marshal.list > xgen-smh && \
|
||||
(cmp -s xgen-smh shell-marshal.h || cp -f xgen-smh shell-marshal.h) && \
|
||||
rm -f xgen-smh && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
shell-marshal.c: Makefile shell-marshal.list
|
||||
(echo "#include \"shell-marshal.h\"" ; \
|
||||
$(AM_V_GEN) (echo "#include \"shell-marshal.h\"" ; \
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_shell_marshal \
|
||||
--body \
|
||||
$(srcdir)/shell-marshal.list ) > xgen-tmc && \
|
||||
cp -f xgen-tmc shell-marshal.c && \
|
||||
rm -f xgen-tmc
|
||||
$(srcdir)/shell-marshal.list ) > xgen-smc && \
|
||||
cp -f xgen-smc shell-marshal.c && \
|
||||
rm -f xgen-smc
|
||||
|
||||
libgnome_shell_la_LDFLAGS = -avoid-version -module
|
||||
libgnome_shell_la_LIBADD = \
|
||||
$(MUTTER_PLUGIN_LIBS) \
|
||||
$(LIBGNOMEUI_LIBS) \
|
||||
libbig-1.0.la \
|
||||
libnbtk-1.0.la \
|
||||
libgdmuser-1.0.la \
|
||||
libtidy-1.0.la \
|
||||
libshell-toolkit.la \
|
||||
libtray.la
|
||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||
|
||||
typelibdir = $(pkglibdir)
|
||||
typelib_DATA = Shell-0.1.typelib Tidy-1.0.typelib Big-1.0.typelib
|
||||
typelib_DATA = Shell-0.1.typelib Big-1.0.typelib Nbtk-1.0.typelib
|
||||
|
||||
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile
|
||||
$(G_IR_SCANNER) \
|
||||
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir Nbtk-1.0.gir libgnome-shell.la Makefile
|
||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||
--namespace=Shell \
|
||||
--nsversion=0.1 \
|
||||
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
|
||||
--include=Clutter-0.9 \
|
||||
--include=Clutter-1.0 \
|
||||
--include=Meta-2.27 \
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--add-include-path=$(builddir) \
|
||||
--include=Big-1.0 \
|
||||
--include=Nbtk-1.0 \
|
||||
--program=mutter \
|
||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||
$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \
|
||||
@ -158,33 +185,20 @@ CLEANFILES += Shell-0.1.gir
|
||||
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
||||
# (not the fake library, since we've already done the rewriting)
|
||||
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
|
||||
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler --includedir=$(builddir) --includedir=$(MUTTER_LIB_DIR)/mutter/ Shell-0.1.gir -o $@
|
||||
$(AM_V_GEN) \
|
||||
$(G_IR_COMPILER) \
|
||||
--includedir=. \
|
||||
--includedir=$(MUTTER_LIB_DIR)/mutter/ \
|
||||
Shell-0.1.gir -o $@
|
||||
CLEANFILES += Shell-0.1.typelib
|
||||
|
||||
Tidy-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libtidy-1.0.la Makefile
|
||||
$(G_IR_SCANNER) \
|
||||
--namespace=Tidy \
|
||||
--nsversion=1.0 \
|
||||
--include=Clutter-0.9 \
|
||||
--program=mutter \
|
||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||
$(addprefix $(srcdir)/,$(tidy_source_h)) \
|
||||
$(addprefix $(srcdir)/,$(tidy_source_c)) \
|
||||
$(srcdir)/tidy-enum-types.h \
|
||||
$(tidy_cflags) \
|
||||
-o $@
|
||||
CLEANFILES += Tidy-1.0.gir
|
||||
|
||||
Tidy-1.0.typelib: libtidy-1.0.la Tidy-1.0.gir
|
||||
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler Tidy-1.0.gir -o $@
|
||||
CLEANFILES += Tidy-1.0.typelib
|
||||
|
||||
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
|
||||
$(G_IR_SCANNER) \
|
||||
--namespace=Big \
|
||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||
--namespace=Big \
|
||||
--nsversion=1.0 \
|
||||
--include=Clutter-0.9 \
|
||||
--include=Clutter-1.0 \
|
||||
--include=GdkPixbuf-2.0 \
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--program=mutter \
|
||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||
$(addprefix $(srcdir)/,$(big_source_h)) \
|
||||
@ -195,5 +209,54 @@ Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
|
||||
CLEANFILES += Big-1.0.gir
|
||||
|
||||
Big-1.0.typelib: libbig-1.0.la Big-1.0.gir
|
||||
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler Big-1.0.gir -o $@
|
||||
$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@
|
||||
CLEANFILES += Big-1.0.typelib
|
||||
|
||||
toolkit_gir_sources = \
|
||||
$(filter-out $(non_gir_toolkit_sources), $(toolkit_sources))
|
||||
|
||||
# Since the Shell namepace includes both the code in toolkit/ that our fork of
|
||||
# NBTK depends upon and the code in this directory that depends on NBTK, We have a
|
||||
# circular dependency when generating the girs and typelibs. We work around this
|
||||
# by generating a Toolkit gir, using it to build the Nbtk gir then sed'ing the
|
||||
# reference out of the generated gir.
|
||||
Toolkit-0.1.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libshell-toolkit.la Makefile
|
||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||
--namespace=Shell \
|
||||
--nsversion=0.1 \
|
||||
--include=Clutter-1.0 \
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--program=mutter \
|
||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||
$(addprefix $(srcdir)/,$(toolkit_gir_sources)) \
|
||||
$(TOOLKIT_CFLAGS) \
|
||||
-o $@
|
||||
CLEANFILES += Toolkit-1.0.gir
|
||||
|
||||
Nbtk-1.0.gir: $(mutter) $(G_IR_SCANNER) Toolkit-0.1.gir libgnome-shell.la libnbtk-1.0.la Makefile
|
||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||
--namespace=Nbtk \
|
||||
--nsversion=1.0 \
|
||||
--include=Clutter-1.0 \
|
||||
--include=Gtk-2.0 \
|
||||
--add-include-path=$(builddir) \
|
||||
--include=Toolkit-0.1 \
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--program=mutter \
|
||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||
-DNBTK_COMPILATION \
|
||||
$(addprefix $(srcdir)/,$(nbtk_source_h)) \
|
||||
$(addprefix $(srcdir)/,$(nbtk_source_c)) \
|
||||
$(srcdir)/nbtk-enum-types.h \
|
||||
$(NBTK_CFLAGS) \
|
||||
-o $@.tmp && \
|
||||
sed -e '/"Toolkit"/d' < $@.tmp > $@
|
||||
CLEANFILES += Nbtk-1.0.gir
|
||||
|
||||
Nbtk-1.0.typelib: Nbtk-1.0.gir
|
||||
$(AM_V_GEN) $(G_IR_COMPILER) \
|
||||
--includedir=. \
|
||||
--includedir=$(MUTTER_LIB_DIR)/mutter/ \
|
||||
$< -o $@
|
||||
|
||||
CLEANFILES += Nbtk-1.0.typelib
|
||||
|
@ -268,6 +268,52 @@ corner_get(guint radius,
|
||||
return corner;
|
||||
}
|
||||
|
||||
/* To match the CSS specification, we want the border to look like it was
|
||||
* drawn over the background. But actually drawing the border over the
|
||||
* background will produce slightly bad antialiasing at the edges, so
|
||||
* compute the effective border color instead.
|
||||
*/
|
||||
#define NORM(x) (t = (x) + 127, (t + (t >> 8)) >> 8)
|
||||
#define MULT(c,a) NORM(c*a)
|
||||
|
||||
static void
|
||||
premultiply (ClutterColor *color)
|
||||
{
|
||||
guint t;
|
||||
color->red = MULT (color->red, color->alpha);
|
||||
color->green = MULT (color->green, color->alpha);
|
||||
color->blue = MULT (color->blue, color->alpha);
|
||||
}
|
||||
|
||||
static void
|
||||
unpremultiply (ClutterColor *color)
|
||||
{
|
||||
if (color->alpha != 0) {
|
||||
color->red = (color->red * 255 + 127) / color->alpha;
|
||||
color->green = (color->green * 255 + 127) / color->alpha;
|
||||
color->blue = (color->blue * 255 + 127) / color->alpha;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
over (const ClutterColor *source,
|
||||
const ClutterColor *destination,
|
||||
ClutterColor *result)
|
||||
{
|
||||
guint t;
|
||||
ClutterColor src = *source;
|
||||
ClutterColor dst = *destination;
|
||||
premultiply (&src);
|
||||
premultiply (&dst);
|
||||
|
||||
result->alpha = src.alpha + NORM ((255 - src.alpha) * dst.alpha);
|
||||
result->red = src.red + NORM ((255 - src.alpha) * dst.red);
|
||||
result->green = src.green + NORM ((255 - src.alpha) * dst.green);
|
||||
result->blue = src.blue + NORM ((255 - src.alpha) * dst.blue);
|
||||
|
||||
unpremultiply (result);
|
||||
}
|
||||
|
||||
static void
|
||||
big_rectangle_update_corners(BigRectangle *rectangle)
|
||||
{
|
||||
@ -278,6 +324,7 @@ big_rectangle_update_corners(BigRectangle *rectangle)
|
||||
if (rectangle->radius != 0) {
|
||||
ClutterColor *color;
|
||||
ClutterColor *border_color;
|
||||
ClutterColor effective_border;
|
||||
guint border_width;
|
||||
|
||||
g_object_get(rectangle,
|
||||
@ -286,10 +333,12 @@ big_rectangle_update_corners(BigRectangle *rectangle)
|
||||
"color", &color,
|
||||
NULL);
|
||||
|
||||
over (border_color, color, &effective_border);
|
||||
|
||||
corner = corner_get(rectangle->radius,
|
||||
color,
|
||||
border_width,
|
||||
border_color);
|
||||
&effective_border);
|
||||
|
||||
clutter_color_free(border_color);
|
||||
clutter_color_free(color);
|
||||
@ -329,12 +378,10 @@ big_rectangle_paint(ClutterActor *actor)
|
||||
|
||||
rectangle = BIG_RECTANGLE(actor);
|
||||
|
||||
if (rectangle->radius == 0) {
|
||||
/* In that case we are no different than our parent class,
|
||||
* so don't bother */
|
||||
CLUTTER_ACTOR_CLASS(big_rectangle_parent_class)->paint(actor);
|
||||
return;
|
||||
}
|
||||
/* We can't chain up, even when we the radius is 0, because of the different
|
||||
* interpretation of the border/background relationship here than for
|
||||
* ClutterRectangle.
|
||||
*/
|
||||
|
||||
if (rectangle->corners_dirty)
|
||||
big_rectangle_update_corners(rectangle);
|
||||
@ -345,6 +392,9 @@ big_rectangle_paint(ClutterActor *actor)
|
||||
"color", &color,
|
||||
NULL);
|
||||
|
||||
if (border_color->alpha == 0 && color->alpha == 0)
|
||||
goto out;
|
||||
|
||||
actor_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
clutter_actor_get_allocation_box(actor, &box);
|
||||
@ -358,6 +408,11 @@ big_rectangle_paint(ClutterActor *actor)
|
||||
|
||||
radius = rectangle->radius;
|
||||
|
||||
/* Optimization; if the border is transparent, it just looks like part of
|
||||
* the background */
|
||||
if (radius == 0 && border_color->alpha == 0)
|
||||
border_width = 0;
|
||||
|
||||
max = MAX(border_width, radius);
|
||||
|
||||
if (radius != 0) {
|
||||
@ -393,33 +448,54 @@ big_rectangle_paint(ClutterActor *actor)
|
||||
}
|
||||
|
||||
if (border_width != 0) {
|
||||
ClutterColor effective_border;
|
||||
over (border_color, color, &effective_border);
|
||||
|
||||
if (!rectangle->border_material)
|
||||
rectangle->border_material = cogl_material_new ();
|
||||
|
||||
cogl_color_set_from_4ub(&tmp_color,
|
||||
border_color->red,
|
||||
border_color->green,
|
||||
border_color->blue,
|
||||
actor_opacity * border_color->alpha / 255);
|
||||
effective_border.red,
|
||||
effective_border.green,
|
||||
effective_border.blue,
|
||||
actor_opacity * effective_border.alpha / 255);
|
||||
cogl_color_premultiply (&tmp_color);
|
||||
cogl_material_set_color(rectangle->border_material, &tmp_color);
|
||||
cogl_set_source(rectangle->border_material);
|
||||
|
||||
/* NORTH */
|
||||
cogl_rectangle(max, 0,
|
||||
width - max, border_width);
|
||||
if (radius > 0) { /* skip corners */
|
||||
/* NORTH */
|
||||
cogl_rectangle(max, 0,
|
||||
width - max, border_width);
|
||||
|
||||
/* EAST */
|
||||
cogl_rectangle(width - border_width, max,
|
||||
width, height - max);
|
||||
/* EAST */
|
||||
cogl_rectangle(width - border_width, max,
|
||||
width, height - max);
|
||||
|
||||
/* SOUTH */
|
||||
cogl_rectangle(max, height - border_width,
|
||||
width - max, height);
|
||||
/* SOUTH */
|
||||
cogl_rectangle(max, height - border_width,
|
||||
width - max, height);
|
||||
|
||||
/* WEST */
|
||||
cogl_rectangle(0, max,
|
||||
border_width, height - max);
|
||||
/* WEST */
|
||||
cogl_rectangle(0, max,
|
||||
border_width, height - max);
|
||||
} else { /* include corners */
|
||||
/* NORTH */
|
||||
cogl_rectangle(0, 0,
|
||||
width, border_width);
|
||||
|
||||
/* EAST */
|
||||
cogl_rectangle(width - border_width, border_width,
|
||||
width, height - border_width);
|
||||
|
||||
/* SOUTH */
|
||||
cogl_rectangle(0, height - border_width,
|
||||
width, height);
|
||||
|
||||
/* WEST */
|
||||
cogl_rectangle(0, border_width,
|
||||
border_width, height - border_width);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rectangle->background_material)
|
||||
@ -455,6 +531,7 @@ big_rectangle_paint(ClutterActor *actor)
|
||||
cogl_rectangle(border_width, max,
|
||||
width - border_width, height - max);
|
||||
|
||||
out:
|
||||
clutter_color_free(border_color);
|
||||
clutter_color_free(color);
|
||||
}
|
||||
|
@ -1,208 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||
*
|
||||
* This program is free software; 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.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gdm-user-chooser-widget.h"
|
||||
#include "gdm-user-chooser-dialog.h"
|
||||
|
||||
#define GDM_USER_CHOOSER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogPrivate))
|
||||
|
||||
struct GdmUserChooserDialogPrivate
|
||||
{
|
||||
GtkWidget *chooser_widget;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
};
|
||||
|
||||
static void gdm_user_chooser_dialog_class_init (GdmUserChooserDialogClass *klass);
|
||||
static void gdm_user_chooser_dialog_init (GdmUserChooserDialog *user_chooser_dialog);
|
||||
static void gdm_user_chooser_dialog_finalize (GObject *object);
|
||||
|
||||
G_DEFINE_TYPE (GdmUserChooserDialog, gdm_user_chooser_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
char *
|
||||
gdm_user_chooser_dialog_get_chosen_user_name (GdmUserChooserDialog *dialog)
|
||||
{
|
||||
char *user_name;
|
||||
|
||||
g_return_val_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog), NULL);
|
||||
|
||||
user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget));
|
||||
|
||||
return user_name;
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_dialog_set_show_user_other (GdmUserChooserDialog *dialog,
|
||||
gboolean show_user)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
|
||||
|
||||
gdm_user_chooser_widget_set_show_user_other (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_dialog_set_show_user_guest (GdmUserChooserDialog *dialog,
|
||||
gboolean show_user)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
|
||||
|
||||
gdm_user_chooser_widget_set_show_user_guest (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_dialog_set_show_user_auto (GdmUserChooserDialog *dialog,
|
||||
gboolean show_user)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
|
||||
|
||||
gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_dialog_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gdm_user_chooser_dialog_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
GdmUserChooserDialog *user_chooser_dialog;
|
||||
|
||||
user_chooser_dialog = GDM_USER_CHOOSER_DIALOG (G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_properties));
|
||||
|
||||
return G_OBJECT (user_chooser_dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_dialog_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_dialog_class_init (GdmUserChooserDialogClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gdm_user_chooser_dialog_get_property;
|
||||
object_class->set_property = gdm_user_chooser_dialog_set_property;
|
||||
object_class->constructor = gdm_user_chooser_dialog_constructor;
|
||||
object_class->dispose = gdm_user_chooser_dialog_dispose;
|
||||
object_class->finalize = gdm_user_chooser_dialog_finalize;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GdmUserChooserDialogPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
on_response (GdmUserChooserDialog *dialog,
|
||||
gint response_id)
|
||||
{
|
||||
switch (response_id) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_dialog_init (GdmUserChooserDialog *dialog)
|
||||
{
|
||||
|
||||
dialog->priv = GDM_USER_CHOOSER_DIALOG_GET_PRIVATE (dialog);
|
||||
|
||||
dialog->priv->chooser_widget = gdm_user_chooser_widget_new ();
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), dialog->priv->chooser_widget);
|
||||
|
||||
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
g_signal_connect (dialog,
|
||||
"response",
|
||||
G_CALLBACK (on_response),
|
||||
dialog);
|
||||
|
||||
gtk_widget_show_all (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_dialog_finalize (GObject *object)
|
||||
{
|
||||
GdmUserChooserDialog *user_chooser_dialog;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (object));
|
||||
|
||||
user_chooser_dialog = GDM_USER_CHOOSER_DIALOG (object);
|
||||
|
||||
g_return_if_fail (user_chooser_dialog->priv != NULL);
|
||||
|
||||
G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gdm_user_chooser_dialog_new (void)
|
||||
{
|
||||
GObject *object;
|
||||
|
||||
object = g_object_new (GDM_TYPE_USER_CHOOSER_DIALOG,
|
||||
NULL);
|
||||
|
||||
return GTK_WIDGET (object);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||
*
|
||||
* This program is free software; 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.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GDM_USER_CHOOSER_DIALOG_H
|
||||
#define __GDM_USER_CHOOSER_DIALOG_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtkdialog.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDM_TYPE_USER_CHOOSER_DIALOG (gdm_user_chooser_dialog_get_type ())
|
||||
#define GDM_USER_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialog))
|
||||
#define GDM_USER_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogClass))
|
||||
#define GDM_IS_USER_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_CHOOSER_DIALOG))
|
||||
#define GDM_IS_USER_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_CHOOSER_DIALOG))
|
||||
#define GDM_USER_CHOOSER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogClass))
|
||||
|
||||
typedef struct GdmUserChooserDialogPrivate GdmUserChooserDialogPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkDialog parent;
|
||||
GdmUserChooserDialogPrivate *priv;
|
||||
} GdmUserChooserDialog;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
} GdmUserChooserDialogClass;
|
||||
|
||||
GType gdm_user_chooser_dialog_get_type (void);
|
||||
|
||||
GtkWidget * gdm_user_chooser_dialog_new (void);
|
||||
|
||||
char * gdm_user_chooser_dialog_get_chosen_user_name (GdmUserChooserDialog *dialog);
|
||||
void gdm_user_chooser_dialog_set_show_other_user (GdmUserChooserDialog *dialog,
|
||||
gboolean show);
|
||||
void gdm_user_chooser_dialog_set_show_user_guest (GdmUserChooserDialog *dialog,
|
||||
gboolean show);
|
||||
void gdm_user_chooser_dialog_set_show_user_auto (GdmUserChooserDialog *dialog,
|
||||
gboolean show);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDM_USER_CHOOSER_DIALOG_H */
|
@ -1,723 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||
* Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
|
||||
*
|
||||
* This program is free software; 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.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gconf/gconf-client.h>
|
||||
|
||||
#include "gdm-user-manager.h"
|
||||
#include "gdm-user-chooser-widget.h"
|
||||
|
||||
|
||||
#define KEY_DISABLE_USER_LIST "/apps/gdm/simple-greeter/disable_user_list"
|
||||
|
||||
enum {
|
||||
USER_NO_DISPLAY = 1 << 0,
|
||||
USER_ACCOUNT_DISABLED = 1 << 1,
|
||||
};
|
||||
|
||||
#define DEFAULT_USER_ICON "stock_person"
|
||||
|
||||
#define GDM_USER_CHOOSER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetPrivate))
|
||||
|
||||
#define MAX_ICON_SIZE 128
|
||||
|
||||
struct GdmUserChooserWidgetPrivate
|
||||
{
|
||||
GdmUserManager *manager;
|
||||
GtkIconTheme *icon_theme;
|
||||
|
||||
GdkPixbuf *logged_in_pixbuf;
|
||||
GdkPixbuf *stock_person_pixbuf;
|
||||
|
||||
guint loaded : 1;
|
||||
guint show_user_other : 1;
|
||||
guint show_user_guest : 1;
|
||||
guint show_user_auto : 1;
|
||||
guint show_normal_users : 1;
|
||||
|
||||
guint load_idle_id;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SHOW_USER_GUEST,
|
||||
PROP_SHOW_USER_AUTO,
|
||||
PROP_SHOW_USER_OTHER,
|
||||
};
|
||||
|
||||
static void gdm_user_chooser_widget_class_init (GdmUserChooserWidgetClass *klass);
|
||||
static void gdm_user_chooser_widget_init (GdmUserChooserWidget *user_chooser_widget);
|
||||
static void gdm_user_chooser_widget_finalize (GObject *object);
|
||||
|
||||
G_DEFINE_TYPE (GdmUserChooserWidget, gdm_user_chooser_widget, GDM_TYPE_CHOOSER_WIDGET)
|
||||
|
||||
static int
|
||||
get_font_height_for_widget (GtkWidget *widget)
|
||||
{
|
||||
PangoFontMetrics *metrics;
|
||||
PangoContext *context;
|
||||
int ascent;
|
||||
int descent;
|
||||
int height;
|
||||
|
||||
gtk_widget_ensure_style (widget);
|
||||
context = gtk_widget_get_pango_context (widget);
|
||||
metrics = pango_context_get_metrics (context,
|
||||
widget->style->font_desc,
|
||||
pango_context_get_language (context));
|
||||
|
||||
ascent = pango_font_metrics_get_ascent (metrics);
|
||||
descent = pango_font_metrics_get_descent (metrics);
|
||||
height = PANGO_PIXELS (ascent + descent);
|
||||
pango_font_metrics_unref (metrics);
|
||||
return height;
|
||||
}
|
||||
|
||||
static int
|
||||
get_icon_height_for_widget (GtkWidget *widget)
|
||||
{
|
||||
int font_height;
|
||||
int height;
|
||||
|
||||
font_height = get_font_height_for_widget (widget);
|
||||
height = 3 * font_height;
|
||||
if (height > MAX_ICON_SIZE) {
|
||||
height = MAX_ICON_SIZE;
|
||||
}
|
||||
|
||||
g_debug ("GdmUserChooserWidget: font height %d; using icon size %d", font_height, height);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
static void
|
||||
add_user_other (GdmUserChooserWidget *widget)
|
||||
{
|
||||
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_USER_CHOOSER_USER_OTHER,
|
||||
NULL,
|
||||
_("Other..."),
|
||||
_("Choose a different account"),
|
||||
0,
|
||||
FALSE,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
add_user_guest (GdmUserChooserWidget *widget)
|
||||
{
|
||||
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_USER_CHOOSER_USER_GUEST,
|
||||
widget->priv->stock_person_pixbuf,
|
||||
_("Guest"),
|
||||
_("Login as a temporary guest"),
|
||||
0,
|
||||
FALSE,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
add_user_auto (GdmUserChooserWidget *widget)
|
||||
{
|
||||
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_USER_CHOOSER_USER_AUTO,
|
||||
NULL,
|
||||
_("Automatic Login"),
|
||||
_("Automatically login to the system after selecting options"),
|
||||
0,
|
||||
FALSE,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_user_other (GdmUserChooserWidget *widget)
|
||||
{
|
||||
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_USER_CHOOSER_USER_OTHER);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_user_guest (GdmUserChooserWidget *widget)
|
||||
{
|
||||
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_USER_CHOOSER_USER_GUEST);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_user_auto (GdmUserChooserWidget *widget)
|
||||
{
|
||||
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_USER_CHOOSER_USER_AUTO);
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_widget_set_show_user_other (GdmUserChooserWidget *widget,
|
||||
gboolean show_user)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||
|
||||
if (widget->priv->show_user_other != show_user) {
|
||||
widget->priv->show_user_other = show_user;
|
||||
if (show_user) {
|
||||
add_user_other (widget);
|
||||
} else {
|
||||
remove_user_other (widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_widget_set_show_user_guest (GdmUserChooserWidget *widget,
|
||||
gboolean show_user)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||
|
||||
if (widget->priv->show_user_guest != show_user) {
|
||||
widget->priv->show_user_guest = show_user;
|
||||
if (show_user) {
|
||||
add_user_guest (widget);
|
||||
} else {
|
||||
remove_user_guest (widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget,
|
||||
gboolean show_user)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||
|
||||
if (widget->priv->show_user_auto != show_user) {
|
||||
widget->priv->show_user_auto = show_user;
|
||||
if (show_user) {
|
||||
add_user_auto (widget);
|
||||
} else {
|
||||
remove_user_auto (widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL);
|
||||
|
||||
return gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget));
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_widget_set_chosen_user_name (GdmUserChooserWidget *widget,
|
||||
const char *name)
|
||||
{
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||
|
||||
gdm_chooser_widget_set_active_item (GDM_CHOOSER_WIDGET (widget), name);
|
||||
}
|
||||
|
||||
void
|
||||
gdm_user_chooser_widget_set_show_only_chosen (GdmUserChooserWidget *widget,
|
||||
gboolean show_only) {
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||
|
||||
gdm_chooser_widget_set_hide_inactive_items (GDM_CHOOSER_WIDGET (widget),
|
||||
show_only);
|
||||
|
||||
}
|
||||
static void
|
||||
gdm_user_chooser_widget_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdmUserChooserWidget *self;
|
||||
|
||||
self = GDM_USER_CHOOSER_WIDGET (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_SHOW_USER_AUTO:
|
||||
gdm_user_chooser_widget_set_show_user_auto (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_SHOW_USER_GUEST:
|
||||
gdm_user_chooser_widget_set_show_user_guest (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_SHOW_USER_OTHER:
|
||||
gdm_user_chooser_widget_set_show_user_other (self, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_widget_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdmUserChooserWidget *self;
|
||||
|
||||
self = GDM_USER_CHOOSER_WIDGET (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_SHOW_USER_AUTO:
|
||||
g_value_set_boolean (value, self->priv->show_user_auto);
|
||||
break;
|
||||
case PROP_SHOW_USER_GUEST:
|
||||
g_value_set_boolean (value, self->priv->show_user_guest);
|
||||
break;
|
||||
case PROP_SHOW_USER_OTHER:
|
||||
g_value_set_boolean (value, self->priv->show_user_other);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_user_list_disabled (GdmUserChooserWidget *widget)
|
||||
{
|
||||
GConfClient *client;
|
||||
GError *error;
|
||||
gboolean result;
|
||||
|
||||
client = gconf_client_get_default ();
|
||||
error = NULL;
|
||||
result = gconf_client_get_bool (client, KEY_DISABLE_USER_LIST, &error);
|
||||
if (error != NULL) {
|
||||
g_debug ("GdmUserChooserWidget: unable to get disable-user-list configuration: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_object_unref (client);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
add_user (GdmUserChooserWidget *widget,
|
||||
GdmUser *user)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
char *tooltip;
|
||||
gboolean is_logged_in;
|
||||
int size;
|
||||
|
||||
if (!widget->priv->show_normal_users) {
|
||||
return;
|
||||
}
|
||||
|
||||
size = get_icon_height_for_widget (widget);
|
||||
pixbuf = gdm_user_render_icon (user, size);
|
||||
if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) {
|
||||
pixbuf = g_object_ref (widget->priv->stock_person_pixbuf);
|
||||
}
|
||||
|
||||
tooltip = g_strdup_printf (_("Log in as %s"),
|
||||
gdm_user_get_user_name (user));
|
||||
|
||||
is_logged_in = gdm_user_get_num_sessions (user) > 0;
|
||||
|
||||
g_debug ("GdmUserChooserWidget: User added name:%s logged-in:%d pixbuf:%p",
|
||||
gdm_user_get_user_name (user),
|
||||
is_logged_in,
|
||||
pixbuf);
|
||||
|
||||
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||
gdm_user_get_user_name (user),
|
||||
pixbuf,
|
||||
gdm_user_get_real_name (user),
|
||||
tooltip,
|
||||
gdm_user_get_login_frequency (user),
|
||||
is_logged_in,
|
||||
FALSE);
|
||||
g_free (tooltip);
|
||||
|
||||
if (pixbuf != NULL) {
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_user_added (GdmUserManager *manager,
|
||||
GdmUser *user,
|
||||
GdmUserChooserWidget *widget)
|
||||
{
|
||||
/* wait for all users to be loaded */
|
||||
if (! widget->priv->loaded) {
|
||||
return;
|
||||
}
|
||||
add_user (widget, user);
|
||||
}
|
||||
|
||||
static void
|
||||
on_user_removed (GdmUserManager *manager,
|
||||
GdmUser *user,
|
||||
GdmUserChooserWidget *widget)
|
||||
{
|
||||
const char *user_name;
|
||||
|
||||
g_debug ("GdmUserChooserWidget: User removed: %s", gdm_user_get_user_name (user));
|
||||
/* wait for all users to be loaded */
|
||||
if (! widget->priv->loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
user_name = gdm_user_get_user_name (user);
|
||||
|
||||
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||
user_name);
|
||||
}
|
||||
|
||||
static void
|
||||
on_user_is_logged_in_changed (GdmUserManager *manager,
|
||||
GdmUser *user,
|
||||
GdmUserChooserWidget *widget)
|
||||
{
|
||||
const char *user_name;
|
||||
gboolean is_logged_in;
|
||||
|
||||
g_debug ("GdmUserChooserWidget: User logged in changed: %s", gdm_user_get_user_name (user));
|
||||
|
||||
user_name = gdm_user_get_user_name (user);
|
||||
is_logged_in = gdm_user_get_num_sessions (user) > 0;
|
||||
|
||||
gdm_chooser_widget_set_item_in_use (GDM_CHOOSER_WIDGET (widget),
|
||||
user_name,
|
||||
is_logged_in);
|
||||
}
|
||||
|
||||
static void
|
||||
on_user_login_frequency_changed (GdmUserManager *manager,
|
||||
GdmUser *user,
|
||||
GdmUserChooserWidget *widget)
|
||||
{
|
||||
const char *user_name;
|
||||
gulong freq;
|
||||
|
||||
g_debug ("GdmUserChooserWidget: User login frequency changed: %s", gdm_user_get_user_name (user));
|
||||
|
||||
user_name = gdm_user_get_user_name (user);
|
||||
freq = gdm_user_get_login_frequency (user);
|
||||
|
||||
gdm_chooser_widget_set_item_priority (GDM_CHOOSER_WIDGET (widget),
|
||||
user_name,
|
||||
freq);
|
||||
}
|
||||
|
||||
static void
|
||||
on_users_loaded (GdmUserManager *manager,
|
||||
GdmUserChooserWidget *widget)
|
||||
{
|
||||
GSList *users;
|
||||
|
||||
widget->priv->loaded = TRUE;
|
||||
|
||||
g_debug ("GdmUserChooserWidget: Users loaded");
|
||||
|
||||
users = gdm_user_manager_list_users (manager);
|
||||
while (users != NULL) {
|
||||
add_user (widget, users->data);
|
||||
users = g_slist_delete_link (users, users);
|
||||
}
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (widget));
|
||||
|
||||
gdm_chooser_widget_loaded (GDM_CHOOSER_WIDGET (widget));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_users (GdmUserChooserWidget *widget)
|
||||
{
|
||||
|
||||
if (widget->priv->show_normal_users) {
|
||||
widget->priv->manager = gdm_user_manager_ref_default ();
|
||||
g_signal_connect (widget->priv->manager,
|
||||
"user-added",
|
||||
G_CALLBACK (on_user_added),
|
||||
widget);
|
||||
g_signal_connect (widget->priv->manager,
|
||||
"user-removed",
|
||||
G_CALLBACK (on_user_removed),
|
||||
widget);
|
||||
g_signal_connect (widget->priv->manager,
|
||||
"users-loaded",
|
||||
G_CALLBACK (on_users_loaded),
|
||||
widget);
|
||||
g_signal_connect (widget->priv->manager,
|
||||
"user-is-logged-in-changed",
|
||||
G_CALLBACK (on_user_is_logged_in_changed),
|
||||
widget);
|
||||
g_signal_connect (widget->priv->manager,
|
||||
"user-login-frequency-changed",
|
||||
G_CALLBACK (on_user_login_frequency_changed),
|
||||
widget);
|
||||
} else {
|
||||
gdm_chooser_widget_loaded (GDM_CHOOSER_WIDGET (widget));
|
||||
}
|
||||
|
||||
widget->priv->load_idle_id = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gdm_user_chooser_widget_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
GdmUserChooserWidget *widget;
|
||||
|
||||
widget = GDM_USER_CHOOSER_WIDGET (G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_properties));
|
||||
|
||||
widget->priv->show_normal_users = !is_user_list_disabled (widget);
|
||||
|
||||
widget->priv->load_idle_id = g_idle_add ((GSourceFunc)load_users, widget);
|
||||
|
||||
return G_OBJECT (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_widget_dispose (GObject *object)
|
||||
{
|
||||
GdmUserChooserWidget *widget;
|
||||
|
||||
widget = GDM_USER_CHOOSER_WIDGET (object);
|
||||
|
||||
G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->dispose (object);
|
||||
|
||||
if (widget->priv->load_idle_id > 0) {
|
||||
g_source_remove (widget->priv->load_idle_id);
|
||||
widget->priv->load_idle_id = 0;
|
||||
}
|
||||
|
||||
if (widget->priv->logged_in_pixbuf != NULL) {
|
||||
g_object_unref (widget->priv->logged_in_pixbuf);
|
||||
widget->priv->logged_in_pixbuf = NULL;
|
||||
}
|
||||
|
||||
if (widget->priv->stock_person_pixbuf != NULL) {
|
||||
g_object_unref (widget->priv->stock_person_pixbuf);
|
||||
widget->priv->stock_person_pixbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_widget_class_init (GdmUserChooserWidgetClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gdm_user_chooser_widget_get_property;
|
||||
object_class->set_property = gdm_user_chooser_widget_set_property;
|
||||
object_class->constructor = gdm_user_chooser_widget_constructor;
|
||||
object_class->dispose = gdm_user_chooser_widget_dispose;
|
||||
object_class->finalize = gdm_user_chooser_widget_finalize;
|
||||
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SHOW_USER_AUTO,
|
||||
g_param_spec_boolean ("show-user-auto",
|
||||
"show user auto",
|
||||
"show user auto",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SHOW_USER_GUEST,
|
||||
g_param_spec_boolean ("show-user-guest",
|
||||
"show user guest",
|
||||
"show user guest",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SHOW_USER_OTHER,
|
||||
g_param_spec_boolean ("show-user-other",
|
||||
"show user other",
|
||||
"show user other",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GdmUserChooserWidgetPrivate));
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
get_stock_person_pixbuf (GdmUserChooserWidget *widget)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
int size;
|
||||
|
||||
size = get_icon_height_for_widget (widget);
|
||||
|
||||
pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme,
|
||||
DEFAULT_USER_ICON,
|
||||
size,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
get_logged_in_pixbuf (GdmUserChooserWidget *widget)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
int size;
|
||||
|
||||
size = get_icon_height_for_widget (widget);
|
||||
|
||||
pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme,
|
||||
"emblem-default",
|
||||
size / 3,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GdkPixbuf *old_icon;
|
||||
GdkPixbuf *new_icon;
|
||||
} IconUpdateData;
|
||||
|
||||
static gboolean
|
||||
update_icons (GdmChooserWidget *widget,
|
||||
const char *id,
|
||||
GdkPixbuf **image,
|
||||
char **name,
|
||||
char **comment,
|
||||
gulong *priority,
|
||||
gboolean *is_in_use,
|
||||
gboolean *is_separate,
|
||||
IconUpdateData *data)
|
||||
{
|
||||
if (data->old_icon == *image) {
|
||||
*image = data->new_icon;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
load_icons (GdmUserChooserWidget *widget)
|
||||
{
|
||||
GdkPixbuf *old_pixbuf;
|
||||
IconUpdateData data;
|
||||
|
||||
if (widget->priv->logged_in_pixbuf != NULL) {
|
||||
g_object_unref (widget->priv->logged_in_pixbuf);
|
||||
}
|
||||
widget->priv->logged_in_pixbuf = get_logged_in_pixbuf (widget);
|
||||
|
||||
old_pixbuf = widget->priv->stock_person_pixbuf;
|
||||
widget->priv->stock_person_pixbuf = get_stock_person_pixbuf (widget);
|
||||
/* update the icons in the model */
|
||||
data.old_icon = old_pixbuf;
|
||||
data.new_icon = widget->priv->stock_person_pixbuf;
|
||||
gdm_chooser_widget_update_foreach_item (GDM_CHOOSER_WIDGET (widget),
|
||||
(GdmChooserUpdateForeachFunc)update_icons,
|
||||
&data);
|
||||
if (old_pixbuf != NULL) {
|
||||
g_object_unref (old_pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_icon_theme_changed (GtkIconTheme *icon_theme,
|
||||
GdmUserChooserWidget *widget)
|
||||
{
|
||||
g_debug ("GdmUserChooserWidget: icon theme changed");
|
||||
load_icons (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_icons (GdmUserChooserWidget *widget)
|
||||
{
|
||||
if (gtk_widget_has_screen (GTK_WIDGET (widget))) {
|
||||
widget->priv->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (widget)));
|
||||
} else {
|
||||
widget->priv->icon_theme = gtk_icon_theme_get_default ();
|
||||
}
|
||||
|
||||
if (widget->priv->icon_theme != NULL) {
|
||||
g_signal_connect (widget->priv->icon_theme,
|
||||
"changed",
|
||||
G_CALLBACK (on_icon_theme_changed),
|
||||
widget);
|
||||
}
|
||||
|
||||
load_icons (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_widget_init (GdmUserChooserWidget *widget)
|
||||
{
|
||||
widget->priv = GDM_USER_CHOOSER_WIDGET_GET_PRIVATE (widget);
|
||||
|
||||
gdm_chooser_widget_set_separator_position (GDM_CHOOSER_WIDGET (widget),
|
||||
GDM_CHOOSER_WIDGET_POSITION_BOTTOM);
|
||||
gdm_chooser_widget_set_in_use_message (GDM_CHOOSER_WIDGET (widget),
|
||||
_("Currently logged in"));
|
||||
|
||||
setup_icons (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_chooser_widget_finalize (GObject *object)
|
||||
{
|
||||
GdmUserChooserWidget *widget;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (object));
|
||||
|
||||
widget = GDM_USER_CHOOSER_WIDGET (object);
|
||||
|
||||
g_return_if_fail (widget->priv != NULL);
|
||||
|
||||
G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gdm_user_chooser_widget_new (void)
|
||||
{
|
||||
GObject *object;
|
||||
|
||||
object = g_object_new (GDM_TYPE_USER_CHOOSER_WIDGET,
|
||||
NULL);
|
||||
|
||||
return GTK_WIDGET (object);
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||
*
|
||||
* This program is free software; 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.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GDM_USER_CHOOSER_WIDGET_H
|
||||
#define __GDM_USER_CHOOSER_WIDGET_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "gdm-chooser-widget.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDM_TYPE_USER_CHOOSER_WIDGET (gdm_user_chooser_widget_get_type ())
|
||||
#define GDM_USER_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidget))
|
||||
#define GDM_USER_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetClass))
|
||||
#define GDM_IS_USER_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_CHOOSER_WIDGET))
|
||||
#define GDM_IS_USER_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_CHOOSER_WIDGET))
|
||||
#define GDM_USER_CHOOSER_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetClass))
|
||||
|
||||
typedef struct GdmUserChooserWidgetPrivate GdmUserChooserWidgetPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdmChooserWidget parent;
|
||||
GdmUserChooserWidgetPrivate *priv;
|
||||
} GdmUserChooserWidget;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdmChooserWidgetClass parent_class;
|
||||
} GdmUserChooserWidgetClass;
|
||||
|
||||
#define GDM_USER_CHOOSER_USER_OTHER "__other"
|
||||
#define GDM_USER_CHOOSER_USER_GUEST "__guest"
|
||||
#define GDM_USER_CHOOSER_USER_AUTO "__auto"
|
||||
|
||||
GType gdm_user_chooser_widget_get_type (void);
|
||||
GtkWidget * gdm_user_chooser_widget_new (void);
|
||||
|
||||
char * gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget);
|
||||
void gdm_user_chooser_widget_set_chosen_user_name (GdmUserChooserWidget *widget,
|
||||
const char *user_name);
|
||||
void gdm_user_chooser_widget_set_show_only_chosen (GdmUserChooserWidget *widget,
|
||||
gboolean show_only);
|
||||
void gdm_user_chooser_widget_set_show_user_other (GdmUserChooserWidget *widget,
|
||||
gboolean show);
|
||||
void gdm_user_chooser_widget_set_show_user_guest (GdmUserChooserWidget *widget,
|
||||
gboolean show);
|
||||
void gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget,
|
||||
gboolean show);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDM_USER_CHOOSER_WIDGET_H */
|
@ -35,7 +35,8 @@
|
||||
#endif /* HAVE_PATHS_H */
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
/* Note on sync with gdm; need to use -lib here */
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
@ -20,12 +20,14 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
/* Note on sync with gdm; need to use -lib here */
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
@ -238,8 +240,8 @@ gdm_user_class_init (GdmUserClass *class)
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_MANAGER,
|
||||
g_param_spec_object ("manager",
|
||||
_("Manager"),
|
||||
_("The user manager object this user is controlled by."),
|
||||
"Manager",
|
||||
"The user manager object this user is controlled by.",
|
||||
GDM_TYPE_USER_MANAGER,
|
||||
(G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY)));
|
||||
@ -411,13 +413,16 @@ _gdm_user_update (GdmUser *user,
|
||||
/* Display Name */
|
||||
if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') {
|
||||
gchar *first_comma;
|
||||
gchar *real_name_utf8;
|
||||
|
||||
first_comma = strchr (pwent->pw_gecos, ',');
|
||||
real_name_utf8 = g_locale_to_utf8 (pwent->pw_gecos, -1, NULL, NULL, NULL);
|
||||
|
||||
first_comma = strchr (real_name_utf8, ',');
|
||||
if (first_comma) {
|
||||
real_name = g_strndup (pwent->pw_gecos,
|
||||
(first_comma - pwent->pw_gecos));
|
||||
real_name = g_strndup (real_name_utf8, first_comma - real_name_utf8);
|
||||
g_free (real_name_utf8);
|
||||
} else {
|
||||
real_name = g_strdup (pwent->pw_gecos);
|
||||
real_name = real_name_utf8;
|
||||
}
|
||||
|
||||
if (real_name[0] == '\0') {
|
||||
@ -881,7 +886,7 @@ curved_rectangle (cairo_t *cr,
|
||||
x1 = x0 + width;
|
||||
y1 = y0 + height;
|
||||
|
||||
if (!width || !height) {
|
||||
if (width < FLT_EPSILON || height < FLT_EPSILON) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1156,8 +1161,8 @@ gdm_user_render_icon (GdmUser *user,
|
||||
} else {
|
||||
pixbuf = NULL;
|
||||
}
|
||||
out:
|
||||
g_free (path);
|
||||
out:
|
||||
|
||||
if (pixbuf != NULL) {
|
||||
framed = frame_pixbuf (pixbuf);
|
||||
|
@ -153,6 +153,9 @@ gnome_shell_plugin_constructed (GObject *object)
|
||||
ClutterBackend *backend;
|
||||
cairo_font_options_t *font_options;
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
|
||||
/* Disable text mipmapping; it causes problems on pre-GEM Intel
|
||||
* drivers and we should just be rendering text at the right
|
||||
* size rather than scaling it. If we do effects where we dynamically
|
||||
|
161
src/gnome-shell.in
Executable file → Normal file
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!@PYTHON@
|
||||
|
||||
import atexit
|
||||
import optparse
|
||||
@ -14,43 +14,6 @@ import termios
|
||||
import time
|
||||
import errno
|
||||
|
||||
def find_cmd (cmd_list):
|
||||
"""
|
||||
Takes a list of command candidates and returns the first one that exists.
|
||||
Raises a system exit if none of the commands exist.
|
||||
"""
|
||||
for cmd in cmd_list:
|
||||
if os.path.exists(cmd):
|
||||
return cmd
|
||||
|
||||
raise SystemExit("None of the commands %s exist" % cmd_list)
|
||||
|
||||
def pidof(command):
|
||||
pidof_cmd = find_cmd(["/sbin/pidof", "/bin/pidof", "/usr/bin/pidof"])
|
||||
pidof = subprocess.Popen([pidof_cmd, command], stdout=subprocess.PIPE)
|
||||
pids = pidof.communicate()[0].split()
|
||||
pidof.wait()
|
||||
|
||||
# pidof doesn't have a "current user only" option, so we may have
|
||||
# gotten the pids of other users' processes. Fix that.
|
||||
for pid in pids:
|
||||
try:
|
||||
os.kill(int(pid), 0)
|
||||
return pid
|
||||
except Exception, e:
|
||||
pass
|
||||
return None
|
||||
|
||||
def kill_gnome_panel(pid):
|
||||
if options.verbose:
|
||||
print "Terminating panel process %s" % pid
|
||||
devnull = open("/dev/null", "w")
|
||||
subprocess.call(["gdb", "-batch-silent",
|
||||
"-ex", "call panel_session_do_not_restart()",
|
||||
"-ex", "call exit(0)",
|
||||
"-p", pid], stdout=devnull, stderr=devnull)
|
||||
devnull.close()
|
||||
|
||||
def start_xephyr():
|
||||
tmpdir = tempfile.mkdtemp("", "gnome-shell.")
|
||||
atexit.register(shutil.rmtree, tmpdir)
|
||||
@ -122,25 +85,27 @@ def start_shell():
|
||||
top_dir = os.path.dirname(bin_dir)
|
||||
plugin = os.path.join(top_dir, 'src', 'libgnome-shell.la')
|
||||
typelib_dir = os.path.join(top_dir, "src")
|
||||
taskpanel_dir = os.path.join(top_dir, "src")
|
||||
js_dir = os.path.join(top_dir, "js")
|
||||
data_dir = os.path.join(top_dir, "data")
|
||||
else:
|
||||
running_from_source_tree = False
|
||||
plugin = 'libgnome-shell'
|
||||
js_dir = os.path.join('@pkgdatadir@', 'js')
|
||||
taskpanel_dir = '@libexecdir@'
|
||||
|
||||
# Set up environment
|
||||
env = dict(os.environ)
|
||||
env.update({'GNOME_SHELL_JS' : '@GJS_JS_DIR@:@GJS_JS_NATIVE_DIR@:' + js_dir,
|
||||
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', '') + ':' + taskpanel_dir,
|
||||
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''),
|
||||
'GNOME_DISABLE_CRASH_DIALOG' : '1'})
|
||||
|
||||
if running_from_source_tree:
|
||||
env.update({'GNOME_SHELL_DATADIR' : data_dir,
|
||||
'GI_TYPELIB_PATH' : typelib_dir})
|
||||
|
||||
jhbuild_gconf_source = os.path.join('@sysconfdir@', 'gconf/2/path.jhbuild')
|
||||
if os.path.exists(jhbuild_gconf_source):
|
||||
env['GCONF_DEFAULT_SOURCE_PATH'] = jhbuild_gconf_source
|
||||
|
||||
# Work around Ubuntu xulrunner bug,
|
||||
# http://bugzilla.gnome.org/show_bug.cgi?id=573413
|
||||
pkgconfig = subprocess.Popen(['pkg-config', '--variable=sdkdir', 'mozilla-js'],
|
||||
@ -187,11 +152,47 @@ def start_shell():
|
||||
else:
|
||||
args = []
|
||||
|
||||
args.extend(['mutter', '--mutter-plugins=' + plugin, '--replace'])
|
||||
args.extend(['mutter', '--mutter-plugins=' + plugin])
|
||||
if options.replace:
|
||||
args.append('--replace')
|
||||
if options.sync:
|
||||
args.append('--sync')
|
||||
return subprocess.Popen(args, env=env)
|
||||
|
||||
def restore_gnome():
|
||||
# Do imports lazily to save time and memory
|
||||
import gio
|
||||
import gconf
|
||||
|
||||
# We don't want to start the new gnome-panel in the current
|
||||
# directory; $HOME is better for stuff launched from it
|
||||
os.chdir(os.path.expanduser("~"))
|
||||
|
||||
def launch_component(gconf_path):
|
||||
client = gconf.client_get_default()
|
||||
component = client.get_string(gconf_path)
|
||||
|
||||
if component == None or component == "":
|
||||
return
|
||||
|
||||
# See gnome-session/gsm-util.c:gsm_util_find_desktop_file_for_app_name()
|
||||
# The one difference is that we don't search the autostart directories,
|
||||
# and just search normal application search path. (Gio doesnt' know
|
||||
# how to search the autostart dirs, so we'd have to do that ourselves.)
|
||||
appinfo = None
|
||||
try:
|
||||
appinfo = gio.unix.DesktopAppInfo(component + ".desktop")
|
||||
except:
|
||||
try:
|
||||
appinfo = gio.unix.DesktopAppInfo("gnome-" + component + ".desktop")
|
||||
except:
|
||||
pass
|
||||
|
||||
if appinfo:
|
||||
appinfo.launch()
|
||||
|
||||
launch_component("/desktop/gnome/session/required_components/windowmanager")
|
||||
launch_component("/desktop/gnome/session/required_components/panel")
|
||||
|
||||
# Main program
|
||||
|
||||
@ -204,6 +205,8 @@ parser.add_option("", "--debug-command", metavar="COMMAND",
|
||||
help="Command to use for debugging (defaults to 'gdb --args')")
|
||||
parser.add_option("-v", "--verbose", action="store_true")
|
||||
parser.add_option("", "--sync", action="store_true")
|
||||
parser.add_option("", "--xephyr", action="store_true",
|
||||
help="Run a debugging instance inside Xephyr")
|
||||
parser.add_option("", "--geometry", metavar="GEOMETRY",
|
||||
help="Specify Xephyr screen geometry",
|
||||
default="1024x768");
|
||||
@ -224,18 +227,6 @@ elif options.debug:
|
||||
if options.wide:
|
||||
options.geometry = "1280x800"
|
||||
|
||||
metacity_pid = pidof("metacity")
|
||||
compiz_pid = pidof("compiz.real") or pidof("compiz")
|
||||
gnome_panel_pid = pidof("gnome-panel")
|
||||
|
||||
# Run in Xephyr if gnome-panel is already running and the user didn't
|
||||
# specify --replace. Otherwise, run fullscreen
|
||||
if options.replace:
|
||||
run_in_xephyr = False
|
||||
else:
|
||||
run_in_xephyr = (metacity_pid != None or compiz_pid != None or
|
||||
gnome_panel_pid != None)
|
||||
|
||||
# Figure out whether or not to use GL_EXT_texture_from_pixmap. By default
|
||||
# we use it iff we aren't running Xephyr, but we allow the user to
|
||||
# explicitly disable it.
|
||||
@ -246,7 +237,7 @@ if 'GNOME_SHELL_DISABLE_TFP' in os.environ and \
|
||||
use_tfp = False
|
||||
else:
|
||||
# tfp does not work correctly in Xephyr
|
||||
use_tfp = not run_in_xephyr
|
||||
use_tfp = not options.xephyr
|
||||
|
||||
if options.verbose:
|
||||
print "Starting shell"
|
||||
@ -256,21 +247,26 @@ if options.debug:
|
||||
# later, in case we kill gdb at a bad time
|
||||
termattrs = termios.tcgetattr(0);
|
||||
|
||||
# We only respawn the previous environment on abnormal exit;
|
||||
# for a clean exit, we assume that gnome-shell was replaced with
|
||||
# something else.
|
||||
normal_exit = False
|
||||
|
||||
try:
|
||||
if run_in_xephyr:
|
||||
shell = start_xephyr()
|
||||
start_shell()
|
||||
shell = None
|
||||
if options.xephyr:
|
||||
xephyr = start_xephyr()
|
||||
# This makes us not grab the org.gnome.Panel name
|
||||
os.environ['GNOME_SHELL_NO_REPLACE_PANEL'] = '1'
|
||||
shell = start_shell()
|
||||
else:
|
||||
if gnome_panel_pid is not None:
|
||||
kill_gnome_panel(gnome_panel_pid)
|
||||
xephyr = None
|
||||
shell = start_shell()
|
||||
|
||||
# Wait for shell to exit
|
||||
if options.verbose:
|
||||
print "Waiting for shell to exit"
|
||||
shell.wait()
|
||||
if options.verbose:
|
||||
print "Shell is dead"
|
||||
|
||||
except KeyboardInterrupt, e:
|
||||
try:
|
||||
@ -278,24 +274,31 @@ except KeyboardInterrupt, e:
|
||||
except:
|
||||
pass
|
||||
shell.wait()
|
||||
if options.verbose:
|
||||
print "Shell killed"
|
||||
|
||||
finally:
|
||||
# Clean up Xephyr if it outlived the shell
|
||||
if xephyr:
|
||||
try:
|
||||
os.kill(xephyr.pid, signal.SIGKILL)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if shell is None:
|
||||
print "Failed to start shell"
|
||||
elif shell.returncode == 0:
|
||||
normal_exit = True
|
||||
if options.verbose:
|
||||
print "Shell exited normally"
|
||||
elif shell.returncode < 0:
|
||||
# Python has no mapping for strsignal; not worth using
|
||||
# ctypes for this.
|
||||
print "Shell killed with signal %d" % - shell.returncode
|
||||
else:
|
||||
# Normal reason here would be losing connection the X server
|
||||
if options.verbose:
|
||||
print "Shell exited with return code %d" % shell.returncode
|
||||
|
||||
if options.debug:
|
||||
termios.tcsetattr(0, termios.TCSANOW, termattrs);
|
||||
|
||||
if not run_in_xephyr:
|
||||
# Restart gnome-panel and window manager
|
||||
if metacity_pid:
|
||||
if options.verbose:
|
||||
print "Restarting Metacity"
|
||||
subprocess.Popen(["/usr/bin/metacity"])
|
||||
elif compiz_pid:
|
||||
if options.verbose:
|
||||
print "Restarting Compiz"
|
||||
subprocess.Popen(["/usr/bin/compiz"])
|
||||
if gnome_panel_pid:
|
||||
if options.verbose:
|
||||
print "Restarting gnome-panel"
|
||||
subprocess.Popen(["/usr/bin/gnome-panel"])
|
||||
if not options.xephyr and options.replace and not normal_exit:
|
||||
restore_gnome()
|
||||
|
@ -1,90 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include "shell-panel-window.h"
|
||||
#include <libwnck/libwnck.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
|
||||
static void
|
||||
on_name_owner_changed (DBusGProxy *proxy,
|
||||
const char *name,
|
||||
const char *prev_owner,
|
||||
const char *new_owner,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (strcmp (name, "org.gnome.Shell") == 0 && new_owner[0] == '\0')
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static void
|
||||
monitor_main_shell (const char *shell_name)
|
||||
{
|
||||
DBusGConnection *session;
|
||||
DBusGProxy *driver;
|
||||
GError *error = NULL;
|
||||
gboolean have_shell;
|
||||
|
||||
session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
|
||||
|
||||
driver = dbus_g_proxy_new_for_name (session,
|
||||
DBUS_SERVICE_DBUS,
|
||||
DBUS_PATH_DBUS,
|
||||
DBUS_INTERFACE_DBUS);
|
||||
|
||||
if (!dbus_g_proxy_call (driver, "NameHasOwner", &error, G_TYPE_STRING,
|
||||
shell_name, G_TYPE_INVALID, G_TYPE_BOOLEAN,
|
||||
&have_shell, G_TYPE_INVALID))
|
||||
{
|
||||
/* Shouldn't happen */
|
||||
exit (1);
|
||||
}
|
||||
if (!have_shell)
|
||||
{
|
||||
/* Shell doesn't exist; either crashed or was restarted. Just abort. */
|
||||
exit (0);
|
||||
}
|
||||
|
||||
dbus_g_proxy_add_signal (driver,
|
||||
"NameOwnerChanged",
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_INVALID);
|
||||
|
||||
dbus_g_proxy_connect_signal (driver,
|
||||
"NameOwnerChanged",
|
||||
G_CALLBACK (on_name_owner_changed),
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
ShellPanelWindow *panel;
|
||||
WnckScreen *screen;
|
||||
WnckTasklist *tasks;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_printerr ("Usage: gnomeshell-taskpanel [PARENT_DBUS_SERVICE]\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
monitor_main_shell (argv[1]);
|
||||
|
||||
panel = shell_panel_window_new ();
|
||||
|
||||
screen = wnck_screen_get_default();
|
||||
tasks = WNCK_TASKLIST (wnck_tasklist_new (screen));
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (panel), GTK_WIDGET (tasks));
|
||||
|
||||
gtk_widget_show_all (GTK_WIDGET (panel));
|
||||
|
||||
gtk_main ();
|
||||
|
||||
exit (0);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <mutter-plugin.h>
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_stage (MutterPlugin *plugin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GList *
|
||||
mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_query_screen_size (MutterPlugin *plugin,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
}
|
||||
|
||||
MetaScreen *
|
||||
mutter_plugin_get_screen (MutterPlugin *plugin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_window_group (MutterPlugin *plugin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Display *
|
||||
meta_display_get_xdisplay (MetaDisplay *display)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaDisplay *
|
||||
meta_screen_get_display (MetaScreen *display)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_screen_get_xroot (MetaScreen *display)
|
||||
{
|
||||
return None;
|
||||
}
|
768
src/nbtk/nbtk-adjustment.c
Normal file
@ -0,0 +1,768 @@
|
||||
/*
|
||||
* nbtk-adjustment.c: Adjustment object
|
||||
*
|
||||
* Copyright (C) 2008 OpenedHand
|
||||
* Copyright (c) 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment
|
||||
* Port to Nbtk by: Robert Staudinger <robsta@openedhand.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "nbtk-adjustment.h"
|
||||
#include "nbtk-marshal.h"
|
||||
#include "nbtk-private.h"
|
||||
|
||||
G_DEFINE_TYPE (NbtkAdjustment, nbtk_adjustment, G_TYPE_OBJECT)
|
||||
|
||||
#define ADJUSTMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentPrivate))
|
||||
|
||||
struct _NbtkAdjustmentPrivate
|
||||
{
|
||||
/* Do not sanity-check values while constructing,
|
||||
* not all properties may be set yet. */
|
||||
gboolean is_constructing : 1;
|
||||
|
||||
gdouble lower;
|
||||
gdouble upper;
|
||||
gdouble value;
|
||||
gdouble step_increment;
|
||||
gdouble page_increment;
|
||||
gdouble page_size;
|
||||
|
||||
/* For interpolation */
|
||||
ClutterTimeline *interpolation;
|
||||
gdouble old_position;
|
||||
gdouble new_position;
|
||||
|
||||
/* For elasticity */
|
||||
gboolean elastic;
|
||||
guint bounce_source;
|
||||
ClutterAlpha *bounce_alpha;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_LOWER,
|
||||
PROP_UPPER,
|
||||
PROP_VALUE,
|
||||
PROP_STEP_INC,
|
||||
PROP_PAGE_INC,
|
||||
PROP_PAGE_SIZE,
|
||||
|
||||
PROP_ELASTIC,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static gboolean nbtk_adjustment_set_lower (NbtkAdjustment *adjustment,
|
||||
gdouble lower);
|
||||
static gboolean nbtk_adjustment_set_upper (NbtkAdjustment *adjustment,
|
||||
gdouble upper);
|
||||
static gboolean nbtk_adjustment_set_step_increment (NbtkAdjustment *adjustment,
|
||||
gdouble step);
|
||||
static gboolean nbtk_adjustment_set_page_increment (NbtkAdjustment *adjustment,
|
||||
gdouble page);
|
||||
static gboolean nbtk_adjustment_set_page_size (NbtkAdjustment *adjustment,
|
||||
gdouble size);
|
||||
|
||||
static void
|
||||
nbtk_adjustment_constructed (GObject *object)
|
||||
{
|
||||
GObjectClass *g_class;
|
||||
NbtkAdjustment *self = NBTK_ADJUSTMENT (object);
|
||||
|
||||
g_class = G_OBJECT_CLASS (nbtk_adjustment_parent_class);
|
||||
/* The docs say we're suppose to chain up, but would crash without
|
||||
* some extra care. */
|
||||
if (g_class && g_class->constructed &&
|
||||
g_class->constructed != nbtk_adjustment_constructed)
|
||||
{
|
||||
g_class->constructed (object);
|
||||
}
|
||||
|
||||
NBTK_ADJUSTMENT (self)->priv->is_constructing = FALSE;
|
||||
nbtk_adjustment_clamp_page (self, self->priv->lower, self->priv->upper);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_adjustment_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = NBTK_ADJUSTMENT (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LOWER:
|
||||
g_value_set_double (value, priv->lower);
|
||||
break;
|
||||
|
||||
case PROP_UPPER:
|
||||
g_value_set_double (value, priv->upper);
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
g_value_set_double (value, priv->value);
|
||||
break;
|
||||
|
||||
case PROP_STEP_INC:
|
||||
g_value_set_double (value, priv->step_increment);
|
||||
break;
|
||||
|
||||
case PROP_PAGE_INC:
|
||||
g_value_set_double (value, priv->page_increment);
|
||||
break;
|
||||
|
||||
case PROP_PAGE_SIZE:
|
||||
g_value_set_double (value, priv->page_size);
|
||||
break;
|
||||
|
||||
case PROP_ELASTIC:
|
||||
g_value_set_boolean (value, priv->elastic);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_adjustment_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NbtkAdjustment *adj = NBTK_ADJUSTMENT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LOWER:
|
||||
nbtk_adjustment_set_lower (adj, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_UPPER:
|
||||
nbtk_adjustment_set_upper (adj, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
nbtk_adjustment_set_value (adj, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_STEP_INC:
|
||||
nbtk_adjustment_set_step_increment (adj, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_PAGE_INC:
|
||||
nbtk_adjustment_set_page_increment (adj, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_PAGE_SIZE:
|
||||
nbtk_adjustment_set_page_size (adj, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_ELASTIC:
|
||||
nbtk_adjustment_set_elastic (adj, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_interpolation (NbtkAdjustment *adjustment)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
if (priv->interpolation)
|
||||
{
|
||||
clutter_timeline_stop (priv->interpolation);
|
||||
g_object_unref (priv->interpolation);
|
||||
priv->interpolation = NULL;
|
||||
|
||||
if (priv->bounce_alpha)
|
||||
{
|
||||
g_object_unref (priv->bounce_alpha);
|
||||
priv->bounce_alpha = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->bounce_source)
|
||||
{
|
||||
g_source_remove (priv->bounce_source);
|
||||
priv->bounce_source = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_adjustment_dispose (GObject *object)
|
||||
{
|
||||
stop_interpolation (NBTK_ADJUSTMENT (object));
|
||||
|
||||
G_OBJECT_CLASS (nbtk_adjustment_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_adjustment_class_init (NbtkAdjustmentClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NbtkAdjustmentPrivate));
|
||||
|
||||
object_class->constructed = nbtk_adjustment_constructed;
|
||||
object_class->get_property = nbtk_adjustment_get_property;
|
||||
object_class->set_property = nbtk_adjustment_set_property;
|
||||
object_class->dispose = nbtk_adjustment_dispose;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LOWER,
|
||||
g_param_spec_double ("lower",
|
||||
"Lower",
|
||||
"Lower bound",
|
||||
-G_MAXDOUBLE,
|
||||
G_MAXDOUBLE,
|
||||
0.0,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_UPPER,
|
||||
g_param_spec_double ("upper",
|
||||
"Upper",
|
||||
"Upper bound",
|
||||
-G_MAXDOUBLE,
|
||||
G_MAXDOUBLE,
|
||||
0.0,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_VALUE,
|
||||
g_param_spec_double ("value",
|
||||
"Value",
|
||||
"Current value",
|
||||
-G_MAXDOUBLE,
|
||||
G_MAXDOUBLE,
|
||||
0.0,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_STEP_INC,
|
||||
g_param_spec_double ("step-increment",
|
||||
"Step Increment",
|
||||
"Step increment",
|
||||
0.0,
|
||||
G_MAXDOUBLE,
|
||||
0.0,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_PAGE_INC,
|
||||
g_param_spec_double ("page-increment",
|
||||
"Page Increment",
|
||||
"Page increment",
|
||||
0.0,
|
||||
G_MAXDOUBLE,
|
||||
0.0,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_PAGE_SIZE,
|
||||
g_param_spec_double ("page-size",
|
||||
"Page Size",
|
||||
"Page size",
|
||||
0.0,
|
||||
G_MAXDOUBLE,
|
||||
0.0,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ELASTIC,
|
||||
g_param_spec_boolean ("elastic",
|
||||
"Elastic",
|
||||
"Make interpolation "
|
||||
"behave in an "
|
||||
"'elastic' way and "
|
||||
"stop clamping value.",
|
||||
FALSE,
|
||||
NBTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
/**
|
||||
* NbtkAdjustment::changed:
|
||||
*
|
||||
* Emitted when any of the adjustment values have changed
|
||||
*/
|
||||
signals[CHANGED] =
|
||||
g_signal_new ("changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NbtkAdjustmentClass, changed),
|
||||
NULL, NULL,
|
||||
_nbtk_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_adjustment_init (NbtkAdjustment *self)
|
||||
{
|
||||
self->priv = ADJUSTMENT_PRIVATE (self);
|
||||
|
||||
self->priv->is_constructing = TRUE;
|
||||
}
|
||||
|
||||
NbtkAdjustment *
|
||||
nbtk_adjustment_new (gdouble value,
|
||||
gdouble lower,
|
||||
gdouble upper,
|
||||
gdouble step_increment,
|
||||
gdouble page_increment,
|
||||
gdouble page_size)
|
||||
{
|
||||
return g_object_new (NBTK_TYPE_ADJUSTMENT,
|
||||
"value", value,
|
||||
"lower", lower,
|
||||
"upper", upper,
|
||||
"step-increment", step_increment,
|
||||
"page-increment", page_increment,
|
||||
"page-size", page_size,
|
||||
NULL);
|
||||
}
|
||||
|
||||
gdouble
|
||||
nbtk_adjustment_get_value (NbtkAdjustment *adjustment)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NBTK_IS_ADJUSTMENT (adjustment), 0);
|
||||
|
||||
priv = adjustment->priv;
|
||||
|
||||
if (priv->interpolation)
|
||||
{
|
||||
return MAX (priv->lower,
|
||||
MIN (priv->upper - priv->page_size,
|
||||
priv->new_position));
|
||||
}
|
||||
else
|
||||
return priv->value;
|
||||
}
|
||||
|
||||
void
|
||||
nbtk_adjustment_set_value (NbtkAdjustment *adjustment,
|
||||
gdouble value)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv;
|
||||
|
||||
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
|
||||
|
||||
priv = adjustment->priv;
|
||||
|
||||
stop_interpolation (adjustment);
|
||||
|
||||
/* Defer clamp until after construction. */
|
||||
if (!priv->is_constructing)
|
||||
{
|
||||
if (!priv->elastic)
|
||||
value = CLAMP (value,
|
||||
priv->lower,
|
||||
MAX (priv->lower, priv->upper - priv->page_size));
|
||||
}
|
||||
|
||||
if (priv->value != value)
|
||||
{
|
||||
priv->value = value;
|
||||
|
||||
g_object_notify (G_OBJECT (adjustment), "value");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nbtk_adjustment_clamp_page (NbtkAdjustment *adjustment,
|
||||
gdouble lower,
|
||||
gdouble upper)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv;
|
||||
gboolean changed;
|
||||
|
||||
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
|
||||
|
||||
priv = adjustment->priv;
|
||||
|
||||
stop_interpolation (adjustment);
|
||||
|
||||
lower = CLAMP (lower, priv->lower, priv->upper - priv->page_size);
|
||||
upper = CLAMP (upper, priv->lower + priv->page_size, priv->upper);
|
||||
|
||||
changed = FALSE;
|
||||
|
||||
if (priv->value + priv->page_size > upper)
|
||||
{
|
||||
priv->value = upper - priv->page_size;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->value < lower)
|
||||
{
|
||||
priv->value = lower;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
g_object_notify (G_OBJECT (adjustment), "value");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_adjustment_set_lower (NbtkAdjustment *adjustment,
|
||||
gdouble lower)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
if (priv->lower != lower)
|
||||
{
|
||||
priv->lower = lower;
|
||||
|
||||
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (adjustment), "lower");
|
||||
|
||||
/* Defer clamp until after construction. */
|
||||
if (!priv->is_constructing)
|
||||
nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_adjustment_set_upper (NbtkAdjustment *adjustment,
|
||||
gdouble upper)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
if (priv->upper != upper)
|
||||
{
|
||||
priv->upper = upper;
|
||||
|
||||
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (adjustment), "upper");
|
||||
|
||||
/* Defer clamp until after construction. */
|
||||
if (!priv->is_constructing)
|
||||
nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_adjustment_set_step_increment (NbtkAdjustment *adjustment,
|
||||
gdouble step)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
if (priv->step_increment != step)
|
||||
{
|
||||
priv->step_increment = step;
|
||||
|
||||
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (adjustment), "step-increment");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_adjustment_set_page_increment (NbtkAdjustment *adjustment,
|
||||
gdouble page)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
if (priv->page_increment != page)
|
||||
{
|
||||
priv->page_increment = page;
|
||||
|
||||
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (adjustment), "page-increment");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_adjustment_set_page_size (NbtkAdjustment *adjustment,
|
||||
gdouble size)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
if (priv->page_size != size)
|
||||
{
|
||||
priv->page_size = size;
|
||||
|
||||
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (adjustment), "page_size");
|
||||
|
||||
/* Well explicitely clamp after construction. */
|
||||
if (!priv->is_constructing)
|
||||
nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nbtk_adjustment_set_values (NbtkAdjustment *adjustment,
|
||||
gdouble value,
|
||||
gdouble lower,
|
||||
gdouble upper,
|
||||
gdouble step_increment,
|
||||
gdouble page_increment,
|
||||
gdouble page_size)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv;
|
||||
gboolean emit_changed = FALSE;
|
||||
|
||||
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
|
||||
g_return_if_fail (page_size >= 0 && page_size <= G_MAXDOUBLE);
|
||||
g_return_if_fail (step_increment >= 0 && step_increment <= G_MAXDOUBLE);
|
||||
g_return_if_fail (page_increment >= 0 && page_increment <= G_MAXDOUBLE);
|
||||
|
||||
priv = adjustment->priv;
|
||||
|
||||
stop_interpolation (adjustment);
|
||||
|
||||
emit_changed = FALSE;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (adjustment));
|
||||
|
||||
emit_changed |= nbtk_adjustment_set_lower (adjustment, lower);
|
||||
emit_changed |= nbtk_adjustment_set_upper (adjustment, upper);
|
||||
emit_changed |= nbtk_adjustment_set_step_increment (adjustment, step_increment);
|
||||
emit_changed |= nbtk_adjustment_set_page_increment (adjustment, page_increment);
|
||||
emit_changed |= nbtk_adjustment_set_page_size (adjustment, page_size);
|
||||
|
||||
if (value != priv->value)
|
||||
{
|
||||
nbtk_adjustment_set_value (adjustment, value);
|
||||
emit_changed = TRUE;
|
||||
}
|
||||
|
||||
if (emit_changed)
|
||||
g_signal_emit (G_OBJECT (adjustment), signals[CHANGED], 0);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (adjustment));
|
||||
}
|
||||
|
||||
void
|
||||
nbtk_adjustment_get_values (NbtkAdjustment *adjustment,
|
||||
gdouble *value,
|
||||
gdouble *lower,
|
||||
gdouble *upper,
|
||||
gdouble *step_increment,
|
||||
gdouble *page_increment,
|
||||
gdouble *page_size)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv;
|
||||
|
||||
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
|
||||
|
||||
priv = adjustment->priv;
|
||||
|
||||
if (lower)
|
||||
*lower = priv->lower;
|
||||
|
||||
if (upper)
|
||||
*upper = priv->upper;
|
||||
|
||||
if (value)
|
||||
*value = nbtk_adjustment_get_value (adjustment);
|
||||
|
||||
if (step_increment)
|
||||
*step_increment = priv->step_increment;
|
||||
|
||||
if (page_increment)
|
||||
*page_increment = priv->page_increment;
|
||||
|
||||
if (page_size)
|
||||
*page_size = priv->page_size;
|
||||
}
|
||||
|
||||
static void
|
||||
interpolation_new_frame_cb (ClutterTimeline *timeline,
|
||||
guint msecs,
|
||||
NbtkAdjustment *adjustment)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
priv->interpolation = NULL;
|
||||
|
||||
if (priv->elastic)
|
||||
{
|
||||
gdouble progress = clutter_alpha_get_alpha (priv->bounce_alpha) / 1.0;
|
||||
gdouble dx = priv->old_position
|
||||
+ (priv->new_position - priv->old_position)
|
||||
* progress;
|
||||
|
||||
nbtk_adjustment_set_value (adjustment, dx);
|
||||
}
|
||||
else
|
||||
nbtk_adjustment_set_value (adjustment,
|
||||
priv->old_position +
|
||||
(priv->new_position - priv->old_position) *
|
||||
clutter_timeline_get_progress (timeline));
|
||||
|
||||
priv->interpolation = timeline;
|
||||
}
|
||||
|
||||
static void
|
||||
interpolation_completed_cb (ClutterTimeline *timeline,
|
||||
NbtkAdjustment *adjustment)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
stop_interpolation (adjustment);
|
||||
nbtk_adjustment_set_value (adjustment, priv->new_position);
|
||||
}
|
||||
|
||||
/* Note, there's super-optimal code that does a similar thing in
|
||||
* clutter-alpha.c
|
||||
*
|
||||
* Tried this instead of CLUTTER_ALPHA_SINE_INC, but I think SINE_INC looks
|
||||
* better. Leaving code here in case this is revisited.
|
||||
*/
|
||||
/*
|
||||
static guint32
|
||||
bounce_alpha_func (ClutterAlpha *alpha,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterFixed progress, angle;
|
||||
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
|
||||
|
||||
progress = clutter_timeline_get_progressx (timeline);
|
||||
angle = clutter_qmulx (CFX_PI_2 + CFX_PI_4/2, progress);
|
||||
|
||||
return clutter_sinx (angle) +
|
||||
(CFX_ONE - clutter_sinx (CFX_PI_2 + CFX_PI_4/2));
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
nbtk_adjustment_interpolate (NbtkAdjustment *adjustment,
|
||||
gdouble value,
|
||||
guint duration)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
|
||||
stop_interpolation (adjustment);
|
||||
|
||||
if (duration <= 1)
|
||||
{
|
||||
nbtk_adjustment_set_value (adjustment, value);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->old_position = priv->value;
|
||||
priv->new_position = value;
|
||||
|
||||
priv->interpolation = clutter_timeline_new (duration);
|
||||
|
||||
if (priv->elastic)
|
||||
priv->bounce_alpha = clutter_alpha_new_full (priv->interpolation,
|
||||
CLUTTER_LINEAR);
|
||||
|
||||
g_signal_connect (priv->interpolation,
|
||||
"new-frame",
|
||||
G_CALLBACK (interpolation_new_frame_cb),
|
||||
adjustment);
|
||||
g_signal_connect (priv->interpolation,
|
||||
"completed",
|
||||
G_CALLBACK (interpolation_completed_cb),
|
||||
adjustment);
|
||||
|
||||
clutter_timeline_start (priv->interpolation);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nbtk_adjustment_get_elastic (NbtkAdjustment *adjustment)
|
||||
{
|
||||
return adjustment->priv->elastic;
|
||||
}
|
||||
|
||||
void
|
||||
nbtk_adjustment_set_elastic (NbtkAdjustment *adjustment,
|
||||
gboolean elastic)
|
||||
{
|
||||
adjustment->priv->elastic = elastic;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nbtk_adjustment_clamp (NbtkAdjustment *adjustment,
|
||||
gboolean interpolate,
|
||||
guint duration)
|
||||
{
|
||||
NbtkAdjustmentPrivate *priv = adjustment->priv;
|
||||
gdouble dest = priv->value;
|
||||
|
||||
if (priv->value < priv->lower)
|
||||
dest = priv->lower;
|
||||
|
||||
if (priv->value > priv->upper - priv->page_size)
|
||||
dest = priv->upper - priv->page_size;
|
||||
|
||||
if (dest != priv->value)
|
||||
{
|
||||
if (interpolate)
|
||||
nbtk_adjustment_interpolate (adjustment, dest, duration);
|
||||
else
|
||||
nbtk_adjustment_set_value (adjustment, dest);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
121
src/nbtk/nbtk-adjustment.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* nbtk-adjustment.h: Adjustment object
|
||||
*
|
||||
* Copyright 2008 OpenedHand
|
||||
* Copyright 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment
|
||||
* Port to Nbtk by: Robert Staudinger <robsta@openedhand.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
|
||||
#error "Only <nbtk/nbtk.h> can be included directly.h"
|
||||
#endif
|
||||
|
||||
#ifndef __NBTK_ADJUSTMENT_H__
|
||||
#define __NBTK_ADJUSTMENT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NBTK_TYPE_ADJUSTMENT (nbtk_adjustment_get_type())
|
||||
#define NBTK_ADJUSTMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_ADJUSTMENT, NbtkAdjustment))
|
||||
#define NBTK_IS_ADJUSTMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_ADJUSTMENT))
|
||||
#define NBTK_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentClass))
|
||||
#define NBTK_IS_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_ADJUSTMENT))
|
||||
#define NBTK_ADJUSTMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentClass))
|
||||
|
||||
typedef struct _NbtkAdjustment NbtkAdjustment;
|
||||
typedef struct _NbtkAdjustmentPrivate NbtkAdjustmentPrivate;
|
||||
typedef struct _NbtkAdjustmentClass NbtkAdjustmentClass;
|
||||
|
||||
/**
|
||||
* NbtkAdjustment:
|
||||
*
|
||||
* Class for handling an interval between to values. The contents of
|
||||
* the #NbtkAdjustment are private and should be accessed using the
|
||||
* public API.
|
||||
*/
|
||||
struct _NbtkAdjustment
|
||||
{
|
||||
/*< private >*/
|
||||
GObject parent_instance;
|
||||
|
||||
NbtkAdjustmentPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* NbtkAdjustmentClass
|
||||
* @changed: Class handler for the ::changed signal.
|
||||
*
|
||||
* Base class for #NbtkAdjustment.
|
||||
*/
|
||||
struct _NbtkAdjustmentClass
|
||||
{
|
||||
/*< private >*/
|
||||
GObjectClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (* changed) (NbtkAdjustment *adjustment);
|
||||
};
|
||||
|
||||
GType nbtk_adjustment_get_type (void) G_GNUC_CONST;
|
||||
|
||||
NbtkAdjustment *nbtk_adjustment_new (gdouble value,
|
||||
gdouble lower,
|
||||
gdouble upper,
|
||||
gdouble step_increment,
|
||||
gdouble page_increment,
|
||||
gdouble page_size);
|
||||
gdouble nbtk_adjustment_get_value (NbtkAdjustment *adjustment);
|
||||
void nbtk_adjustment_set_value (NbtkAdjustment *adjustment,
|
||||
gdouble value);
|
||||
void nbtk_adjustment_clamp_page (NbtkAdjustment *adjustment,
|
||||
gdouble lower,
|
||||
gdouble upper);
|
||||
void nbtk_adjustment_set_values (NbtkAdjustment *adjustment,
|
||||
gdouble value,
|
||||
gdouble lower,
|
||||
gdouble upper,
|
||||
gdouble step_increment,
|
||||
gdouble page_increment,
|
||||
gdouble page_size);
|
||||
void nbtk_adjustment_get_values (NbtkAdjustment *adjustment,
|
||||
gdouble *value,
|
||||
gdouble *lower,
|
||||
gdouble *upper,
|
||||
gdouble *step_increment,
|
||||
gdouble *page_increment,
|
||||
gdouble *page_size);
|
||||
|
||||
void nbtk_adjustment_interpolate (NbtkAdjustment *adjustment,
|
||||
gdouble value,
|
||||
guint duration);
|
||||
|
||||
gboolean nbtk_adjustment_get_elastic (NbtkAdjustment *adjustment);
|
||||
void nbtk_adjustment_set_elastic (NbtkAdjustment *adjustment,
|
||||
gboolean elastic);
|
||||
|
||||
gboolean nbtk_adjustment_clamp (NbtkAdjustment *adjustment,
|
||||
gboolean interpolate,
|
||||
guint duration);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NBTK_ADJUSTMENT_H__ */
|
739
src/nbtk/nbtk-bin.c
Normal file
@ -0,0 +1,739 @@
|
||||
/*
|
||||
* nbtk-bin.c: Basic container actor
|
||||
*
|
||||
* Copyright (c) 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:nbtk-bin
|
||||
* @short_description: a simple container with one actor
|
||||
*
|
||||
* #NbtkBin is a simple container capable of having only one
|
||||
* #ClutterActor as a child.
|
||||
*
|
||||
* #NbtkBin inherits from #NbtkWidget, so it is fully themable.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "nbtk-bin.h"
|
||||
#include "nbtk-enum-types.h"
|
||||
#include "nbtk-private.h"
|
||||
|
||||
#define NBTK_BIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BIN, NbtkBinPrivate))
|
||||
|
||||
struct _NbtkBinPrivate
|
||||
{
|
||||
ClutterActor *child;
|
||||
|
||||
NbtkAlignment x_align;
|
||||
NbtkAlignment y_align;
|
||||
|
||||
guint x_fill : 1;
|
||||
guint y_fill : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_CHILD,
|
||||
PROP_X_ALIGN,
|
||||
PROP_Y_ALIGN,
|
||||
PROP_X_FILL,
|
||||
PROP_Y_FILL
|
||||
};
|
||||
|
||||
static void clutter_container_iface_init (ClutterContainerIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (NbtkBin, nbtk_bin, NBTK_TYPE_WIDGET,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||
clutter_container_iface_init));
|
||||
|
||||
void
|
||||
_nbtk_bin_get_align_factors (NbtkBin *bin,
|
||||
gdouble *x_align,
|
||||
gdouble *y_align)
|
||||
{
|
||||
NbtkBinPrivate *priv = bin->priv;
|
||||
gdouble factor;
|
||||
|
||||
switch (priv->x_align)
|
||||
{
|
||||
case NBTK_ALIGN_LEFT:
|
||||
factor = 0.0;
|
||||
break;
|
||||
|
||||
case NBTK_ALIGN_CENTER:
|
||||
factor = 0.5;
|
||||
break;
|
||||
|
||||
case NBTK_ALIGN_RIGHT:
|
||||
factor = 1.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
factor = 0.0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (x_align)
|
||||
*x_align = factor;
|
||||
|
||||
switch (priv->y_align)
|
||||
{
|
||||
case NBTK_ALIGN_TOP:
|
||||
factor = 0.0;
|
||||
break;
|
||||
|
||||
case NBTK_ALIGN_CENTER:
|
||||
factor = 0.5;
|
||||
break;
|
||||
|
||||
case NBTK_ALIGN_BOTTOM:
|
||||
factor = 1.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
factor = 0.0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (y_align)
|
||||
*y_align = factor;
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_add (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
nbtk_bin_set_child (NBTK_BIN (container), actor);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_remove (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (container)->priv;
|
||||
|
||||
if (priv->child == actor)
|
||||
nbtk_bin_set_child (NBTK_BIN (container), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_foreach (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (container)->priv;
|
||||
|
||||
if (priv->child)
|
||||
callback (priv->child, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_container_iface_init (ClutterContainerIface *iface)
|
||||
{
|
||||
iface->add = nbtk_bin_add;
|
||||
iface->remove = nbtk_bin_remove;
|
||||
iface->foreach = nbtk_bin_foreach;
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_paint (ClutterActor *self)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
|
||||
|
||||
/* allow NbtkWidget to paint the background */
|
||||
CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->paint (self);
|
||||
|
||||
/* the pain our child */
|
||||
if (priv->child)
|
||||
clutter_actor_paint (priv->child);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_pick (ClutterActor *self,
|
||||
const ClutterColor *pick_color)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
|
||||
|
||||
/* get the default pick implementation */
|
||||
CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->pick (self, pick_color);
|
||||
|
||||
if (priv->child)
|
||||
clutter_actor_paint (priv->child);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->allocate (self, box,
|
||||
flags);
|
||||
|
||||
if (priv->child)
|
||||
{
|
||||
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
|
||||
gfloat natural_width, natural_height;
|
||||
gfloat min_width, min_height;
|
||||
gfloat child_width, child_height;
|
||||
gfloat available_width, available_height;
|
||||
ClutterRequestMode request;
|
||||
ClutterActorBox content_box;
|
||||
ClutterActorBox allocation = { 0, };
|
||||
gdouble x_align, y_align;
|
||||
|
||||
shell_theme_node_get_content_box (theme_node, box, &content_box);
|
||||
|
||||
_nbtk_bin_get_align_factors (NBTK_BIN (self), &x_align, &y_align);
|
||||
|
||||
available_width = content_box.x2 - content_box.x1;
|
||||
available_height = content_box.y2 - content_box.y1;
|
||||
|
||||
if (available_width < 0)
|
||||
available_width = 0;
|
||||
|
||||
if (available_height < 0)
|
||||
available_height = 0;
|
||||
|
||||
if (priv->x_fill)
|
||||
{
|
||||
allocation.x1 = (int) content_box.x1;
|
||||
allocation.x2 = (int) content_box.x2;
|
||||
}
|
||||
|
||||
if (priv->y_fill)
|
||||
{
|
||||
allocation.y1 = (int) content_box.y1;
|
||||
allocation.y2 = (int) content_box.y2;
|
||||
}
|
||||
|
||||
/* if we are filling horizontally and vertically then we're done */
|
||||
if (priv->x_fill && priv->y_fill)
|
||||
{
|
||||
clutter_actor_allocate (priv->child, &allocation, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
|
||||
g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL);
|
||||
|
||||
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
|
||||
{
|
||||
clutter_actor_get_preferred_width (priv->child, available_height,
|
||||
&min_width,
|
||||
&natural_width);
|
||||
|
||||
child_width = CLAMP (natural_width, min_width, available_width);
|
||||
|
||||
clutter_actor_get_preferred_height (priv->child, child_width,
|
||||
&min_height,
|
||||
&natural_height);
|
||||
|
||||
child_height = CLAMP (natural_height, min_height, available_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_get_preferred_height (priv->child, available_width,
|
||||
&min_height,
|
||||
&natural_height);
|
||||
|
||||
child_height = CLAMP (natural_height, min_height, available_height);
|
||||
|
||||
clutter_actor_get_preferred_width (priv->child, child_height,
|
||||
&min_width,
|
||||
&natural_width);
|
||||
|
||||
child_width = CLAMP (natural_width, min_width, available_width);
|
||||
}
|
||||
|
||||
if (!priv->x_fill)
|
||||
{
|
||||
allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align);
|
||||
allocation.x2 = allocation.x1 + child_width;
|
||||
}
|
||||
|
||||
if (!priv->y_fill)
|
||||
{
|
||||
allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align);
|
||||
allocation.y2 = allocation.y1 + child_height;
|
||||
}
|
||||
|
||||
clutter_actor_allocate (priv->child, &allocation, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
|
||||
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
|
||||
|
||||
shell_theme_node_adjust_for_height (theme_node, &for_height);
|
||||
|
||||
if (priv->child == NULL)
|
||||
{
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_get_preferred_width (priv->child, for_height,
|
||||
min_width_p,
|
||||
natural_width_p);
|
||||
}
|
||||
|
||||
shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
|
||||
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
|
||||
|
||||
shell_theme_node_adjust_for_width (theme_node, &for_width);
|
||||
|
||||
if (priv->child == NULL)
|
||||
{
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_get_preferred_height (priv->child, for_width,
|
||||
min_height_p,
|
||||
natural_height_p);
|
||||
}
|
||||
|
||||
shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_dispose (GObject *gobject)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (gobject)->priv;
|
||||
|
||||
if (priv->child)
|
||||
{
|
||||
clutter_actor_unparent (priv->child);
|
||||
priv->child = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nbtk_bin_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NbtkBin *bin = NBTK_BIN (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CHILD:
|
||||
nbtk_bin_set_child (bin, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_X_ALIGN:
|
||||
nbtk_bin_set_alignment (bin,
|
||||
g_value_get_enum (value),
|
||||
bin->priv->y_align);
|
||||
break;
|
||||
|
||||
case PROP_Y_ALIGN:
|
||||
nbtk_bin_set_alignment (bin,
|
||||
bin->priv->x_align,
|
||||
g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_X_FILL:
|
||||
nbtk_bin_set_fill (bin,
|
||||
g_value_get_boolean (value),
|
||||
bin->priv->y_fill);
|
||||
break;
|
||||
|
||||
case PROP_Y_FILL:
|
||||
nbtk_bin_set_fill (bin,
|
||||
bin->priv->y_fill,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NbtkBinPrivate *priv = NBTK_BIN (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CHILD:
|
||||
g_value_set_object (value, priv->child);
|
||||
break;
|
||||
|
||||
case PROP_X_FILL:
|
||||
g_value_set_boolean (value, priv->x_fill);
|
||||
break;
|
||||
|
||||
case PROP_Y_FILL:
|
||||
g_value_set_boolean (value, priv->y_fill);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_class_init (NbtkBinClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NbtkBinPrivate));
|
||||
|
||||
gobject_class->set_property = nbtk_bin_set_property;
|
||||
gobject_class->get_property = nbtk_bin_get_property;
|
||||
gobject_class->dispose = nbtk_bin_dispose;
|
||||
|
||||
actor_class->get_preferred_width = nbtk_bin_get_preferred_width;
|
||||
actor_class->get_preferred_height = nbtk_bin_get_preferred_height;
|
||||
actor_class->allocate = nbtk_bin_allocate;
|
||||
actor_class->paint = nbtk_bin_paint;
|
||||
actor_class->pick = nbtk_bin_pick;
|
||||
|
||||
/**
|
||||
* NbtkBin:child:
|
||||
*
|
||||
* The child #ClutterActor of the #NbtkBin container.
|
||||
*/
|
||||
pspec = g_param_spec_object ("child",
|
||||
"Child",
|
||||
"The child of the Bin",
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_CHILD, pspec);
|
||||
|
||||
/**
|
||||
* NbtkBin:x-align:
|
||||
*
|
||||
* The horizontal alignment of the #NbtkBin child.
|
||||
*/
|
||||
pspec = g_param_spec_enum ("x-align",
|
||||
"X Align",
|
||||
"The horizontal alignment",
|
||||
NBTK_TYPE_ALIGNMENT,
|
||||
NBTK_ALIGN_CENTER,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_X_ALIGN, pspec);
|
||||
|
||||
/**
|
||||
* NbtkBin:y-align:
|
||||
*
|
||||
* The vertical alignment of the #NbtkBin child.
|
||||
*/
|
||||
pspec = g_param_spec_enum ("y-align",
|
||||
"Y Align",
|
||||
"The vertical alignment",
|
||||
NBTK_TYPE_ALIGNMENT,
|
||||
NBTK_ALIGN_CENTER,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_Y_ALIGN, pspec);
|
||||
|
||||
/**
|
||||
* NbtkBin:x-fill:
|
||||
*
|
||||
* Whether the child should fill the horizontal allocation
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("x-fill",
|
||||
"X Fill",
|
||||
"Whether the child should fill the "
|
||||
"horizontal allocation",
|
||||
FALSE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_X_FILL, pspec);
|
||||
|
||||
/**
|
||||
* NbtkBin:y-fill:
|
||||
*
|
||||
* Whether the child should fill the vertical allocation
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("y-fill",
|
||||
"Y Fill",
|
||||
"Whether the child should fill the "
|
||||
"vertical allocation",
|
||||
FALSE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_Y_FILL, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_bin_init (NbtkBin *bin)
|
||||
{
|
||||
bin->priv = NBTK_BIN_GET_PRIVATE (bin);
|
||||
|
||||
bin->priv->x_align = NBTK_ALIGN_CENTER;
|
||||
bin->priv->y_align = NBTK_ALIGN_CENTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_new:
|
||||
*
|
||||
* Creates a new #NbtkBin, a simple container for one child.
|
||||
*
|
||||
* Return value: the newly created #NbtkBin actor
|
||||
*/
|
||||
NbtkWidget *
|
||||
nbtk_bin_new (void)
|
||||
{
|
||||
return g_object_new (NBTK_TYPE_BIN, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_set_child:
|
||||
* @bin: a #NbtkBin
|
||||
* @child: a #ClutterActor, or %NULL
|
||||
*
|
||||
* Sets @child as the child of @bin.
|
||||
*
|
||||
* If @bin already has a child, the previous child is removed.
|
||||
*/
|
||||
void
|
||||
nbtk_bin_set_child (NbtkBin *bin,
|
||||
ClutterActor *child)
|
||||
{
|
||||
NbtkBinPrivate *priv;
|
||||
|
||||
g_return_if_fail (NBTK_IS_BIN (bin));
|
||||
g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
|
||||
|
||||
priv = bin->priv;
|
||||
|
||||
if (priv->child == child)
|
||||
return;
|
||||
|
||||
if (priv->child)
|
||||
{
|
||||
ClutterActor *old_child = priv->child;
|
||||
|
||||
g_object_ref (old_child);
|
||||
|
||||
priv->child = NULL;
|
||||
clutter_actor_unparent (old_child);
|
||||
|
||||
g_signal_emit_by_name (bin, "actor-removed", old_child);
|
||||
|
||||
g_object_unref (old_child);
|
||||
}
|
||||
|
||||
if (child)
|
||||
{
|
||||
priv->child = child;
|
||||
clutter_actor_set_parent (child, CLUTTER_ACTOR (bin));
|
||||
|
||||
g_signal_emit_by_name (bin, "actor-added", priv->child);
|
||||
}
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
|
||||
|
||||
g_object_notify (G_OBJECT (bin), "child");
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_get_child:
|
||||
* @bin: a #NbtkBin
|
||||
*
|
||||
* Retrieves a pointer to the child of @bin.
|
||||
*
|
||||
* Return value: (transfer none): a #ClutterActor, or %NULL
|
||||
*/
|
||||
ClutterActor *
|
||||
nbtk_bin_get_child (NbtkBin *bin)
|
||||
{
|
||||
g_return_val_if_fail (NBTK_IS_BIN (bin), NULL);
|
||||
|
||||
return bin->priv->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_set_alignment:
|
||||
* @bin: a #NbtkBin
|
||||
* @x_align: horizontal alignment
|
||||
* @y_align: vertical alignment
|
||||
*
|
||||
* Sets the horizontal and vertical alignment of the child
|
||||
* inside a #NbtkBin.
|
||||
*/
|
||||
void
|
||||
nbtk_bin_set_alignment (NbtkBin *bin,
|
||||
NbtkAlignment x_align,
|
||||
NbtkAlignment y_align)
|
||||
{
|
||||
NbtkBinPrivate *priv;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_return_if_fail (NBTK_IS_BIN (bin));
|
||||
|
||||
priv = bin->priv;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (bin));
|
||||
|
||||
if (priv->x_align != x_align)
|
||||
{
|
||||
priv->x_align = x_align;
|
||||
g_object_notify (G_OBJECT (bin), "x-align");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->y_align != y_align)
|
||||
{
|
||||
priv->y_align = y_align;
|
||||
g_object_notify (G_OBJECT (bin), "y-align");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (bin));
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_get_alignment:
|
||||
* @bin: a #NbtkBin
|
||||
* @x_align: return location for the horizontal alignment, or %NULL
|
||||
* @y_align: return location for the vertical alignment, or %NULL
|
||||
*
|
||||
* Retrieves the horizontal and vertical alignment of the child
|
||||
* inside a #NbtkBin, as set by nbtk_bin_set_alignment().
|
||||
*/
|
||||
void
|
||||
nbtk_bin_get_alignment (NbtkBin *bin,
|
||||
NbtkAlignment *x_align,
|
||||
NbtkAlignment *y_align)
|
||||
{
|
||||
NbtkBinPrivate *priv;
|
||||
|
||||
g_return_if_fail (NBTK_IS_BIN (bin));
|
||||
|
||||
priv = bin->priv;
|
||||
|
||||
if (x_align)
|
||||
*x_align = priv->x_align;
|
||||
|
||||
if (y_align)
|
||||
*y_align = priv->y_align;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_set_fill:
|
||||
* @bin: a #NbtkBin
|
||||
* @x_fill: %TRUE if the child should fill horizontally the @bin
|
||||
* @y_fill: %TRUE if the child should fill vertically the @bin
|
||||
*
|
||||
* Sets whether the child of @bin should fill out the horizontal
|
||||
* and/or vertical allocation of the parent
|
||||
*/
|
||||
void
|
||||
nbtk_bin_set_fill (NbtkBin *bin,
|
||||
gboolean x_fill,
|
||||
gboolean y_fill)
|
||||
{
|
||||
NbtkBinPrivate *priv;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_return_if_fail (NBTK_IS_BIN (bin));
|
||||
|
||||
priv = bin->priv;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (bin));
|
||||
|
||||
if (priv->x_fill != x_fill)
|
||||
{
|
||||
priv->x_fill = x_fill;
|
||||
changed = TRUE;
|
||||
|
||||
g_object_notify (G_OBJECT (bin), "x-fill");
|
||||
}
|
||||
|
||||
if (priv->y_fill != y_fill)
|
||||
{
|
||||
priv->y_fill = y_fill;
|
||||
changed = TRUE;
|
||||
|
||||
g_object_notify (G_OBJECT (bin), "y-fill");
|
||||
}
|
||||
|
||||
if (changed)
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (bin));
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_bin_get_fill:
|
||||
* @bin: a #NbtkBin
|
||||
* @x_fill: (out): return location for the horizontal fill, or %NULL
|
||||
* @y_fill: (out): return location for the vertical fill, or %NULL
|
||||
*
|
||||
* Retrieves the horizontal and vertical fill settings
|
||||
*/
|
||||
void
|
||||
nbtk_bin_get_fill (NbtkBin *bin,
|
||||
gboolean *x_fill,
|
||||
gboolean *y_fill)
|
||||
{
|
||||
g_return_if_fail (NBTK_IS_BIN (bin));
|
||||
|
||||
if (x_fill)
|
||||
*x_fill = bin->priv->x_fill;
|
||||
|
||||
if (y_fill)
|
||||
*y_fill = bin->priv->y_fill;
|
||||
}
|
92
src/nbtk/nbtk-bin.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* nbtk-bin.h: Basic container actor
|
||||
*
|
||||
* Copyright 2009, 2008 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Written by: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
|
||||
#error "Only <nbtk/nbtk.h> can be included directly.h"
|
||||
#endif
|
||||
|
||||
#ifndef __NBTK_BIN_H__
|
||||
#define __NBTK_BIN_H__
|
||||
|
||||
#include <nbtk/nbtk-types.h>
|
||||
#include <nbtk/nbtk-widget.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NBTK_TYPE_BIN (nbtk_bin_get_type ())
|
||||
#define NBTK_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_BIN, NbtkBin))
|
||||
#define NBTK_IS_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_BIN))
|
||||
#define NBTK_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_BIN, NbtkBinClass))
|
||||
#define NBTK_IS_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_BIN))
|
||||
#define NBTK_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_BIN, NbtkBinClass))
|
||||
|
||||
typedef struct _NbtkBin NbtkBin;
|
||||
typedef struct _NbtkBinPrivate NbtkBinPrivate;
|
||||
typedef struct _NbtkBinClass NbtkBinClass;
|
||||
|
||||
/**
|
||||
* NbtkBin:
|
||||
*
|
||||
* The #NbtkBin struct contains only private data
|
||||
*/
|
||||
struct _NbtkBin
|
||||
{
|
||||
/*< private >*/
|
||||
NbtkWidget parent_instance;
|
||||
|
||||
NbtkBinPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* NbtkBinClass:
|
||||
*
|
||||
* The #NbtkBinClass struct contains only private data
|
||||
*/
|
||||
struct _NbtkBinClass
|
||||
{
|
||||
/*< private >*/
|
||||
NbtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
GType nbtk_bin_get_type (void) G_GNUC_CONST;
|
||||
|
||||
NbtkWidget *nbtk_bin_new (void);
|
||||
void nbtk_bin_set_child (NbtkBin *bin,
|
||||
ClutterActor *child);
|
||||
ClutterActor *nbtk_bin_get_child (NbtkBin *bin);
|
||||
void nbtk_bin_set_alignment (NbtkBin *bin,
|
||||
NbtkAlignment x_align,
|
||||
NbtkAlignment y_align);
|
||||
void nbtk_bin_get_alignment (NbtkBin *bin,
|
||||
NbtkAlignment *x_align,
|
||||
NbtkAlignment *y_align);
|
||||
void nbtk_bin_set_fill (NbtkBin *bin,
|
||||
gboolean x_fill,
|
||||
gboolean y_fill);
|
||||
void nbtk_bin_get_fill (NbtkBin *bin,
|
||||
gboolean *x_fill,
|
||||
gboolean *y_fill);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NBTK_BIN_H__ */
|
176
src/nbtk/nbtk-box-layout-child.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* nbtk-box-layout-child.c: box layout child actor
|
||||
*
|
||||
* Copyright 2009 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||
*/
|
||||
|
||||
#include "nbtk-box-layout-child.h"
|
||||
#include "nbtk-private.h"
|
||||
|
||||
G_DEFINE_TYPE (NbtkBoxLayoutChild, nbtk_box_layout_child, CLUTTER_TYPE_CHILD_META)
|
||||
|
||||
#define BOX_LAYOUT_CHILD_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildPrivate))
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_EXPAND,
|
||||
PROP_X_FILL,
|
||||
PROP_Y_FILL,
|
||||
PROP_X_ALIGN,
|
||||
PROP_Y_ALIGN
|
||||
};
|
||||
|
||||
static void
|
||||
nbtk_box_layout_child_get_property (GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NbtkBoxLayoutChild *child = NBTK_BOX_LAYOUT_CHILD (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_EXPAND:
|
||||
g_value_set_boolean (value, child->expand);
|
||||
break;
|
||||
case PROP_X_FILL:
|
||||
g_value_set_boolean (value, child->x_fill);
|
||||
break;
|
||||
case PROP_Y_FILL:
|
||||
g_value_set_boolean (value, child->y_fill);
|
||||
break;
|
||||
case PROP_X_ALIGN:
|
||||
g_value_set_enum (value, child->x_align);
|
||||
break;
|
||||
case PROP_Y_ALIGN:
|
||||
g_value_set_enum (value, child->y_align);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_box_layout_child_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NbtkBoxLayoutChild *child = NBTK_BOX_LAYOUT_CHILD (object);
|
||||
NbtkBoxLayout *box = NBTK_BOX_LAYOUT (CLUTTER_CHILD_META (object)->container);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_EXPAND:
|
||||
child->expand = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_X_FILL:
|
||||
child->x_fill = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_Y_FILL:
|
||||
child->y_fill = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_X_ALIGN:
|
||||
child->x_align = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_Y_ALIGN:
|
||||
child->y_align = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
|
||||
clutter_actor_queue_relayout ((ClutterActor*) box);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_box_layout_child_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (nbtk_box_layout_child_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_box_layout_child_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (nbtk_box_layout_child_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_box_layout_child_class_init (NbtkBoxLayoutChildClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
object_class->get_property = nbtk_box_layout_child_get_property;
|
||||
object_class->set_property = nbtk_box_layout_child_set_property;
|
||||
object_class->dispose = nbtk_box_layout_child_dispose;
|
||||
object_class->finalize = nbtk_box_layout_child_finalize;
|
||||
|
||||
|
||||
pspec = g_param_spec_boolean ("expand", "Expand",
|
||||
"Allocate the child extra space",
|
||||
FALSE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_EXPAND, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("x-fill", "x-fill",
|
||||
"Whether the child should receive priority "
|
||||
"when the container is allocating spare space "
|
||||
"on the horizontal axis",
|
||||
TRUE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_X_FILL, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("y-fill", "y-fill",
|
||||
"Whether the child should receive priority "
|
||||
"when the container is allocating spare space "
|
||||
"on the vertical axis",
|
||||
TRUE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_Y_FILL, pspec);
|
||||
|
||||
pspec = g_param_spec_enum ("x-align",
|
||||
"X Alignment",
|
||||
"X alignment of the widget within the cell",
|
||||
NBTK_TYPE_ALIGN,
|
||||
NBTK_ALIGN_MIDDLE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_X_ALIGN, pspec);
|
||||
|
||||
pspec = g_param_spec_enum ("y-align",
|
||||
"Y Alignment",
|
||||
"Y alignment of the widget within the cell",
|
||||
NBTK_TYPE_ALIGN,
|
||||
NBTK_ALIGN_MIDDLE,
|
||||
NBTK_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_Y_ALIGN, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_box_layout_child_init (NbtkBoxLayoutChild *self)
|
||||
{
|
||||
self->expand = FALSE;
|
||||
|
||||
self->x_fill = TRUE;
|
||||
self->y_fill = TRUE;
|
||||
|
||||
self->x_align = NBTK_ALIGN_CENTER;
|
||||
self->y_align = NBTK_ALIGN_CENTER;
|
||||
}
|
84
src/nbtk/nbtk-box-layout-child.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* nbtk-box-layout-child.h: box layout child actor
|
||||
*
|
||||
* Copyright 2009 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NBTK_BOX_LAYOUT_CHILD_H
|
||||
#define _NBTK_BOX_LAYOUT_CHILD_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "nbtk-enum-types.h"
|
||||
#include "nbtk-box-layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NBTK_TYPE_BOX_LAYOUT_CHILD nbtk_box_layout_child_get_type()
|
||||
|
||||
#define NBTK_BOX_LAYOUT_CHILD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChild))
|
||||
|
||||
#define NBTK_BOX_LAYOUT_CHILD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildClass))
|
||||
|
||||
#define NBTK_IS_BOX_LAYOUT_CHILD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
NBTK_TYPE_BOX_LAYOUT_CHILD))
|
||||
|
||||
#define NBTK_IS_BOX_LAYOUT_CHILD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
NBTK_TYPE_BOX_LAYOUT_CHILD))
|
||||
|
||||
#define NBTK_BOX_LAYOUT_CHILD_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildClass))
|
||||
|
||||
typedef struct _NbtkBoxLayoutChild NbtkBoxLayoutChild;
|
||||
typedef struct _NbtkBoxLayoutChildClass NbtkBoxLayoutChildClass;
|
||||
typedef struct _NbtkBoxLayoutChildPrivate NbtkBoxLayoutChildPrivate;
|
||||
|
||||
/**
|
||||
* NbtkBoxLayoutChild:
|
||||
*
|
||||
* The contents of this structure are private and should only be accessed
|
||||
* through the public API.
|
||||
*/
|
||||
struct _NbtkBoxLayoutChild
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterChildMeta parent;
|
||||
|
||||
gboolean expand;
|
||||
gboolean x_fill : 1;
|
||||
gboolean y_fill : 1;
|
||||
NbtkAlign x_align;
|
||||
NbtkAlign y_align;
|
||||
};
|
||||
|
||||
struct _NbtkBoxLayoutChildClass
|
||||
{
|
||||
ClutterChildMetaClass parent_class;
|
||||
};
|
||||
|
||||
GType nbtk_box_layout_child_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _NBTK_BOX_LAYOUT_CHILD_H */
|
1252
src/nbtk/nbtk-box-layout.c
Normal file
91
src/nbtk/nbtk-box-layout.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* nbtk-box-layout.h: box layout actor
|
||||
*
|
||||
* Copyright 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NBTK_BOX_LAYOUT_H
|
||||
#define _NBTK_BOX_LAYOUT_H
|
||||
|
||||
#include <nbtk/nbtk-widget.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NBTK_TYPE_BOX_LAYOUT nbtk_box_layout_get_type()
|
||||
|
||||
#define NBTK_BOX_LAYOUT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayout))
|
||||
|
||||
#define NBTK_BOX_LAYOUT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayoutClass))
|
||||
|
||||
#define NBTK_IS_BOX_LAYOUT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
NBTK_TYPE_BOX_LAYOUT))
|
||||
|
||||
#define NBTK_IS_BOX_LAYOUT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
NBTK_TYPE_BOX_LAYOUT))
|
||||
|
||||
#define NBTK_BOX_LAYOUT_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayoutClass))
|
||||
|
||||
typedef struct _NbtkBoxLayout NbtkBoxLayout;
|
||||
typedef struct _NbtkBoxLayoutClass NbtkBoxLayoutClass;
|
||||
typedef struct _NbtkBoxLayoutPrivate NbtkBoxLayoutPrivate;
|
||||
|
||||
/**
|
||||
* NbtkBoxLayout:
|
||||
*
|
||||
* The contents of this structure are private and should only be accessed
|
||||
* through the public API.
|
||||
*/
|
||||
struct _NbtkBoxLayout
|
||||
{
|
||||
/*< private >*/
|
||||
NbtkWidget parent;
|
||||
|
||||
NbtkBoxLayoutPrivate *priv;
|
||||
};
|
||||
|
||||
struct _NbtkBoxLayoutClass
|
||||
{
|
||||
NbtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
GType nbtk_box_layout_get_type (void);
|
||||
|
||||
NbtkWidget *nbtk_box_layout_new (void);
|
||||
|
||||
void nbtk_box_layout_set_vertical (NbtkBoxLayout *box, gboolean vertical);
|
||||
gboolean nbtk_box_layout_get_vertical (NbtkBoxLayout *box);
|
||||
|
||||
void nbtk_box_layout_set_pack_start (NbtkBoxLayout *box, gboolean pack_start);
|
||||
gboolean nbtk_box_layout_get_pack_start (NbtkBoxLayout *box);
|
||||
|
||||
void nbtk_box_layout_set_spacing (NbtkBoxLayout *box, guint spacing);
|
||||
guint nbtk_box_layout_get_spacing (NbtkBoxLayout *box);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _NBTK_BOX_LAYOUT_H */
|
690
src/nbtk/nbtk-button.c
Normal file
@ -0,0 +1,690 @@
|
||||
/*-button.c: Plain button actor
|
||||
* Copyright 2007 OpenedHand
|
||||
* Copyright , 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Emmanuele Bassi <ebassi@openedhand.com>
|
||||
* Thomas Wood <thomas@linux.intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:nbtk-button
|
||||
* @short_description: Button widget
|
||||
*
|
||||
* A button widget with support for either a text label or icon, toggle mode
|
||||
* and transitions effects between states.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "nbtk-button.h"
|
||||
|
||||
#include "nbtk-marshal.h"
|
||||
#include "nbtk-texture-frame.h"
|
||||
#include "nbtk-texture-cache.h"
|
||||
#include "nbtk-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_LABEL,
|
||||
PROP_TOGGLE,
|
||||
PROP_ACTIVE,
|
||||
PROP_TRANSITION
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CLICKED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
#define NBTK_BUTTON_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BUTTON, NbtkButtonPrivate))
|
||||
|
||||
struct _NbtkButtonPrivate
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
ClutterActor *old_bg;
|
||||
gboolean old_bg_parented; /* TRUE if we have adopted old_bg */
|
||||
|
||||
guint8 old_opacity;
|
||||
|
||||
guint is_pressed : 1;
|
||||
guint is_hover : 1;
|
||||
guint is_checked : 1;
|
||||
guint is_toggle : 1;
|
||||
|
||||
gint transition_duration;
|
||||
|
||||
ClutterAnimation *animation;
|
||||
|
||||
gint spacing;
|
||||
};
|
||||
|
||||
static guint button_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE (NbtkButton, nbtk_button, NBTK_TYPE_BIN);
|
||||
|
||||
static void
|
||||
nbtk_button_update_label_style (NbtkButton *button)
|
||||
{
|
||||
ClutterActor *label;
|
||||
ShellThemeNode *theme_node;
|
||||
ClutterColor color;
|
||||
const PangoFontDescription *font;
|
||||
gchar *font_string = NULL;
|
||||
|
||||
label = nbtk_bin_get_child ((NbtkBin*) button);
|
||||
|
||||
/* check the child is really a label */
|
||||
if (!CLUTTER_IS_TEXT (label))
|
||||
return;
|
||||
|
||||
theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button));
|
||||
|
||||
shell_theme_node_get_foreground_color (theme_node, &color);
|
||||
clutter_text_set_color (CLUTTER_TEXT (label), &color);
|
||||
|
||||
font = shell_theme_node_get_font (theme_node);
|
||||
font_string = pango_font_description_to_string (font);
|
||||
clutter_text_set_font_name (CLUTTER_TEXT (label), font_string);
|
||||
g_free (font_string);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_dispose_old_bg (NbtkButton *button)
|
||||
{
|
||||
NbtkButtonPrivate *priv = button->priv;
|
||||
|
||||
if (priv->old_bg)
|
||||
{
|
||||
if (priv->old_bg_parented)
|
||||
{
|
||||
clutter_actor_unparent (priv->old_bg);
|
||||
priv->old_bg_parented = FALSE;
|
||||
}
|
||||
g_object_unref (priv->old_bg);
|
||||
priv->old_bg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_animation_completed (ClutterAnimation *animation,
|
||||
NbtkButton *button)
|
||||
{
|
||||
nbtk_button_dispose_old_bg (button);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_style_changed (NbtkWidget *widget)
|
||||
{
|
||||
NbtkButton *button = NBTK_BUTTON (widget);
|
||||
NbtkButtonPrivate *priv = button->priv;
|
||||
NbtkButtonClass *button_class = NBTK_BUTTON_GET_CLASS (button);
|
||||
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button));
|
||||
ClutterActor *bg_image;
|
||||
double spacing;
|
||||
|
||||
nbtk_button_dispose_old_bg (button);
|
||||
|
||||
bg_image = nbtk_widget_get_border_image ((NbtkWidget*) button);
|
||||
if (bg_image)
|
||||
button->priv->old_bg = g_object_ref (bg_image);
|
||||
|
||||
NBTK_WIDGET_CLASS (nbtk_button_parent_class)->style_changed (widget);
|
||||
|
||||
spacing = 6;
|
||||
shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);
|
||||
priv->spacing = round (spacing);
|
||||
|
||||
/* update the label styling */
|
||||
nbtk_button_update_label_style (button);
|
||||
|
||||
/* run a transition if applicable */
|
||||
if (button_class->transition)
|
||||
{
|
||||
button_class->transition (button, priv->old_bg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->old_bg &&
|
||||
(!nbtk_widget_get_style_pseudo_class (widget)))
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
if (!clutter_actor_get_parent (priv->old_bg))
|
||||
{
|
||||
clutter_actor_set_parent (priv->old_bg, (ClutterActor*) widget);
|
||||
priv->old_bg_parented = TRUE;
|
||||
}
|
||||
if (priv->transition_duration > 0)
|
||||
{
|
||||
animation = clutter_actor_animate (priv->old_bg,
|
||||
CLUTTER_LINEAR,
|
||||
priv->transition_duration,
|
||||
"opacity", 0,
|
||||
NULL);
|
||||
g_signal_connect (animation, "completed",
|
||||
G_CALLBACK (nbtk_animation_completed), button);
|
||||
}
|
||||
else
|
||||
{
|
||||
nbtk_button_dispose_old_bg (button);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_real_pressed (NbtkButton *button)
|
||||
{
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "active");
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_real_released (NbtkButton *button)
|
||||
{
|
||||
NbtkButtonPrivate *priv = button->priv;
|
||||
|
||||
if (priv->is_checked)
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked");
|
||||
else if (!priv->is_hover)
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL);
|
||||
else
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover");
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_button_button_press (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
nbtk_widget_hide_tooltip (NBTK_WIDGET (actor));
|
||||
|
||||
if (event->button == 1)
|
||||
{
|
||||
NbtkButton *button = NBTK_BUTTON (actor);
|
||||
NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button);
|
||||
|
||||
button->priv->is_pressed = TRUE;
|
||||
|
||||
clutter_grab_pointer (actor);
|
||||
|
||||
if (klass->pressed)
|
||||
klass->pressed (button);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_button_button_release (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
if (event->button == 1)
|
||||
{
|
||||
NbtkButton *button = NBTK_BUTTON (actor);
|
||||
NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button);
|
||||
|
||||
if (!button->priv->is_pressed)
|
||||
return FALSE;
|
||||
|
||||
clutter_ungrab_pointer ();
|
||||
|
||||
if (button->priv->is_toggle)
|
||||
{
|
||||
nbtk_button_set_checked (button, !button->priv->is_checked);
|
||||
}
|
||||
|
||||
button->priv->is_pressed = FALSE;
|
||||
|
||||
if (klass->released)
|
||||
klass->released (button);
|
||||
|
||||
g_signal_emit (button, button_signals[CLICKED], 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_button_enter (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
{
|
||||
NbtkButton *button = NBTK_BUTTON (actor);
|
||||
|
||||
if (!button->priv->is_checked)
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover");
|
||||
|
||||
button->priv->is_hover = 1;
|
||||
|
||||
return CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->enter_event (actor, event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nbtk_button_leave (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
{
|
||||
NbtkButton *button = NBTK_BUTTON (actor);
|
||||
|
||||
button->priv->is_hover = 0;
|
||||
|
||||
if (button->priv->is_pressed)
|
||||
{
|
||||
NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button);
|
||||
|
||||
clutter_ungrab_pointer ();
|
||||
|
||||
button->priv->is_pressed = FALSE;
|
||||
|
||||
if (klass->released)
|
||||
klass->released (button);
|
||||
}
|
||||
|
||||
if (button->priv->is_checked)
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked");
|
||||
else
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL);
|
||||
|
||||
return CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->leave_event (actor, event);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NbtkButton *button = NBTK_BUTTON (gobject);
|
||||
NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LABEL:
|
||||
nbtk_button_set_label (button, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_TOGGLE:
|
||||
nbtk_button_set_toggle_mode (button, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
nbtk_button_set_checked (button, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_TRANSITION:
|
||||
priv->transition_duration = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LABEL:
|
||||
g_value_set_string (value, priv->text);
|
||||
break;
|
||||
case PROP_TOGGLE:
|
||||
g_value_set_boolean (value, priv->is_toggle);
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
g_value_set_boolean (value, priv->is_checked);
|
||||
break;
|
||||
case PROP_TRANSITION:
|
||||
g_value_set_int (value, priv->transition_duration);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_finalize (GObject *gobject)
|
||||
{
|
||||
NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv;
|
||||
|
||||
g_free (priv->text);
|
||||
|
||||
G_OBJECT_CLASS (nbtk_button_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_dispose (GObject *gobject)
|
||||
{
|
||||
nbtk_button_dispose_old_bg (NBTK_BUTTON (gobject));
|
||||
|
||||
G_OBJECT_CLASS (nbtk_button_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_map (ClutterActor *self)
|
||||
{
|
||||
NbtkButtonPrivate *priv = NBTK_BUTTON (self)->priv;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->map (self);
|
||||
|
||||
if (priv->old_bg && priv->old_bg_parented)
|
||||
clutter_actor_map (priv->old_bg);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_unmap (ClutterActor *self)
|
||||
{
|
||||
NbtkButtonPrivate *priv = NBTK_BUTTON (self)->priv;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->unmap (self);
|
||||
|
||||
if (priv->old_bg && priv->old_bg_parented)
|
||||
clutter_actor_unmap (priv->old_bg);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_draw_background (NbtkWidget *widget)
|
||||
{
|
||||
NbtkButtonPrivate *priv;
|
||||
|
||||
NBTK_WIDGET_CLASS (nbtk_button_parent_class)->draw_background (widget);
|
||||
|
||||
priv = NBTK_BUTTON (widget)->priv;
|
||||
|
||||
if (priv->old_bg && priv->old_bg_parented)
|
||||
clutter_actor_paint (priv->old_bg);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_class_init (NbtkButtonClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NbtkButtonPrivate));
|
||||
|
||||
klass->pressed = nbtk_button_real_pressed;
|
||||
klass->released = nbtk_button_real_released;
|
||||
|
||||
gobject_class->set_property = nbtk_button_set_property;
|
||||
gobject_class->get_property = nbtk_button_get_property;
|
||||
gobject_class->dispose = nbtk_button_dispose;
|
||||
gobject_class->finalize = nbtk_button_finalize;
|
||||
|
||||
actor_class->button_press_event = nbtk_button_button_press;
|
||||
actor_class->button_release_event = nbtk_button_button_release;
|
||||
actor_class->enter_event = nbtk_button_enter;
|
||||
actor_class->leave_event = nbtk_button_leave;
|
||||
|
||||
actor_class->map = nbtk_button_map;
|
||||
actor_class->unmap = nbtk_button_unmap;
|
||||
|
||||
widget_class->draw_background = nbtk_button_draw_background;
|
||||
widget_class->style_changed = nbtk_button_style_changed;
|
||||
|
||||
pspec = g_param_spec_string ("label",
|
||||
"Label",
|
||||
"Label of the button",
|
||||
NULL, G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("toggle-mode",
|
||||
"Toggle Mode",
|
||||
"Enable or disable toggling",
|
||||
FALSE, G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_TOGGLE, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("checked",
|
||||
"Checked",
|
||||
"Indicates if a toggle button is \"on\""
|
||||
" or \"off\"",
|
||||
FALSE, G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_ACTIVE, pspec);
|
||||
|
||||
pspec = g_param_spec_int ("transition-duration",
|
||||
"Transition Duration",
|
||||
"Duration of the state transition effect",
|
||||
0, G_MAXINT, 120, G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_TRANSITION, pspec);
|
||||
|
||||
|
||||
/**
|
||||
* NbtkButton::clicked:
|
||||
* @button: the object that received the signal
|
||||
*
|
||||
* Emitted when the user activates the button, either with a mouse press and
|
||||
* release or with the keyboard.
|
||||
*/
|
||||
|
||||
button_signals[CLICKED] =
|
||||
g_signal_new ("clicked",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NbtkButtonClass, clicked),
|
||||
NULL, NULL,
|
||||
_nbtk_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_button_init (NbtkButton *button)
|
||||
{
|
||||
button->priv = NBTK_BUTTON_GET_PRIVATE (button);
|
||||
button->priv->transition_duration = 120;
|
||||
button->priv->spacing = 6;
|
||||
|
||||
clutter_actor_set_reactive ((ClutterActor *) button, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_new:
|
||||
*
|
||||
* Create a new button
|
||||
*
|
||||
* Returns: a new #NbtkButton
|
||||
*/
|
||||
NbtkWidget *
|
||||
nbtk_button_new (void)
|
||||
{
|
||||
return g_object_new (NBTK_TYPE_BUTTON, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_new_with_label:
|
||||
* @text: text to set the label to
|
||||
*
|
||||
* Create a new #NbtkButton with the specified label
|
||||
*
|
||||
* Returns: a new #NbtkButton
|
||||
*/
|
||||
NbtkWidget *
|
||||
nbtk_button_new_with_label (const gchar *text)
|
||||
{
|
||||
return g_object_new (NBTK_TYPE_BUTTON, "label", text, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_get_label:
|
||||
* @button: a #NbtkButton
|
||||
*
|
||||
* Get the text displayed on the button
|
||||
*
|
||||
* Returns: the text for the button. This must not be freed by the application
|
||||
*/
|
||||
G_CONST_RETURN gchar *
|
||||
nbtk_button_get_label (NbtkButton *button)
|
||||
{
|
||||
g_return_val_if_fail (NBTK_IS_BUTTON (button), NULL);
|
||||
|
||||
return button->priv->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_set_label:
|
||||
* @button: a #Nbtkbutton
|
||||
* @text: text to set the label to
|
||||
*
|
||||
* Sets the text displayed on the button
|
||||
*/
|
||||
void
|
||||
nbtk_button_set_label (NbtkButton *button,
|
||||
const gchar *text)
|
||||
{
|
||||
NbtkButtonPrivate *priv;
|
||||
ClutterActor *label;
|
||||
|
||||
g_return_if_fail (NBTK_IS_BUTTON (button));
|
||||
|
||||
priv = button->priv;
|
||||
|
||||
g_free (priv->text);
|
||||
|
||||
if (text)
|
||||
priv->text = g_strdup (text);
|
||||
else
|
||||
priv->text = g_strdup ("");
|
||||
|
||||
label = nbtk_bin_get_child ((NbtkBin*) button);
|
||||
|
||||
if (label && CLUTTER_IS_TEXT (label))
|
||||
{
|
||||
clutter_text_set_text (CLUTTER_TEXT (label), priv->text);
|
||||
}
|
||||
else
|
||||
{
|
||||
label = g_object_new (CLUTTER_TYPE_TEXT,
|
||||
"text", priv->text,
|
||||
"line-alignment", PANGO_ALIGN_CENTER,
|
||||
"ellipsize", PANGO_ELLIPSIZE_END,
|
||||
"use-markup", TRUE,
|
||||
NULL);
|
||||
nbtk_bin_set_child ((NbtkBin*) button, label);
|
||||
}
|
||||
|
||||
/* Fake a style change so that we reset the style properties on the label */
|
||||
nbtk_widget_style_changed (NBTK_WIDGET (button));
|
||||
|
||||
g_object_notify (G_OBJECT (button), "label");
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_get_toggle_mode:
|
||||
* @button: a #NbtkButton
|
||||
*
|
||||
* Get the toggle mode status of the button.
|
||||
*
|
||||
* Returns: #TRUE if toggle mode is set, otherwise #FALSE
|
||||
*/
|
||||
gboolean
|
||||
nbtk_button_get_toggle_mode (NbtkButton *button)
|
||||
{
|
||||
g_return_val_if_fail (NBTK_IS_BUTTON (button), FALSE);
|
||||
|
||||
return button->priv->is_toggle;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_set_toggle_mode:
|
||||
* @button: a #Nbtkbutton
|
||||
* @toggle: #TRUE or #FALSE
|
||||
*
|
||||
* Enables or disables toggle mode for the button. In toggle mode, the active
|
||||
* state will be "toggled" when the user clicks the button.
|
||||
*/
|
||||
void
|
||||
nbtk_button_set_toggle_mode (NbtkButton *button,
|
||||
gboolean toggle)
|
||||
{
|
||||
g_return_if_fail (NBTK_IS_BUTTON (button));
|
||||
|
||||
button->priv->is_toggle = toggle;
|
||||
|
||||
g_object_notify (G_OBJECT (button), "toggle-mode");
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_get_checked:
|
||||
* @button: a #NbtkButton
|
||||
*
|
||||
* Get the state of the button that is in toggle mode.
|
||||
*
|
||||
* Returns: #TRUE if the button is checked, or #FALSE if not
|
||||
*/
|
||||
gboolean
|
||||
nbtk_button_get_checked (NbtkButton *button)
|
||||
{
|
||||
g_return_val_if_fail (NBTK_IS_BUTTON (button), FALSE);
|
||||
|
||||
return button->priv->is_checked;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_button_set_checked:
|
||||
* @button: a #Nbtkbutton
|
||||
* @checked: #TRUE or #FALSE
|
||||
*
|
||||
* Sets the pressed state of the button. This is only really useful if the
|
||||
* button has #toggle-mode mode set to #TRUE.
|
||||
*/
|
||||
void
|
||||
nbtk_button_set_checked (NbtkButton *button,
|
||||
gboolean checked)
|
||||
{
|
||||
g_return_if_fail (NBTK_IS_BUTTON (button));
|
||||
|
||||
if (button->priv->is_checked != checked)
|
||||
{
|
||||
button->priv->is_checked = checked;
|
||||
|
||||
if (checked)
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked");
|
||||
else
|
||||
if (button->priv->is_hover)
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover");
|
||||
else
|
||||
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (button), "checked");
|
||||
}
|
90
src/nbtk/nbtk-button.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* nbtk-button.h: Plain button actor
|
||||
*
|
||||
* Copyright 2007 OpenedHand
|
||||
* Copyright 2008, 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Written by: Emmanuele Bassi <ebassi@openedhand.com>
|
||||
* Thomas Wood <thomas@linux.intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
|
||||
#error "Only <nbtk/nbtk.h> can be included directly.h"
|
||||
#endif
|
||||
|
||||
#ifndef __NBTK_BUTTON_H__
|
||||
#define __NBTK_BUTTON_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <nbtk/nbtk-bin.h>
|
||||
|
||||
#define NBTK_TYPE_BUTTON (nbtk_button_get_type ())
|
||||
#define NBTK_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_BUTTON, NbtkButton))
|
||||
#define NBTK_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_BUTTON))
|
||||
#define NBTK_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_BUTTON, NbtkButtonClass))
|
||||
#define NBTK_IS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_BUTTON))
|
||||
#define NBTK_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_BUTTON, NbtkButtonClass))
|
||||
|
||||
typedef struct _NbtkButton NbtkButton;
|
||||
typedef struct _NbtkButtonPrivate NbtkButtonPrivate;
|
||||
typedef struct _NbtkButtonClass NbtkButtonClass;
|
||||
|
||||
/**
|
||||
* NbtkButton:
|
||||
*
|
||||
* The contents of this structure is private and should only be accessed using
|
||||
* the provided API.
|
||||
*/
|
||||
|
||||
struct _NbtkButton
|
||||
{
|
||||
/*< private >*/
|
||||
NbtkBin parent_instance;
|
||||
|
||||
NbtkButtonPrivate *priv;
|
||||
};
|
||||
|
||||
struct _NbtkButtonClass
|
||||
{
|
||||
NbtkBinClass parent_class;
|
||||
|
||||
/* vfuncs, not signals */
|
||||
void (* pressed) (NbtkButton *button);
|
||||
void (* released) (NbtkButton *button);
|
||||
void (* transition) (NbtkButton *button, ClutterActor *old_bg);
|
||||
|
||||
/* signals */
|
||||
void (* clicked) (NbtkButton *button);
|
||||
};
|
||||
|
||||
GType nbtk_button_get_type (void) G_GNUC_CONST;
|
||||
|
||||
NbtkWidget * nbtk_button_new (void);
|
||||
NbtkWidget * nbtk_button_new_with_label (const gchar *text);
|
||||
G_CONST_RETURN gchar *nbtk_button_get_label (NbtkButton *button);
|
||||
void nbtk_button_set_label (NbtkButton *button,
|
||||
const gchar *text);
|
||||
void nbtk_button_set_toggle_mode (NbtkButton *button, gboolean toggle);
|
||||
gboolean nbtk_button_get_toggle_mode (NbtkButton *button);
|
||||
void nbtk_button_set_checked (NbtkButton *button, gboolean checked);
|
||||
gboolean nbtk_button_get_checked (NbtkButton *button);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NBTK_BUTTON_H__ */
|
367
src/nbtk/nbtk-clipboard.c
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* nbtk-clipboard.c: clipboard object
|
||||
*
|
||||
* Copyright 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "nbtk-clipboard.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#include <string.h>
|
||||
|
||||
G_DEFINE_TYPE (NbtkClipboard, nbtk_clipboard, G_TYPE_OBJECT)
|
||||
|
||||
#define CLIPBOARD_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_CLIPBOARD, NbtkClipboardPrivate))
|
||||
|
||||
struct _NbtkClipboardPrivate
|
||||
{
|
||||
Window clipboard_window;
|
||||
gchar *clipboard_text;
|
||||
|
||||
Atom *supported_targets;
|
||||
gint n_targets;
|
||||
};
|
||||
|
||||
typedef struct _EventFilterData EventFilterData;
|
||||
struct _EventFilterData
|
||||
{
|
||||
NbtkClipboard *clipboard;
|
||||
NbtkClipboardCallbackFunc callback;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
static Atom __atom_clip = None;
|
||||
static Atom __utf8_string = None;
|
||||
static Atom __atom_targets = None;
|
||||
|
||||
static void
|
||||
nbtk_clipboard_get_property (GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_clipboard_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_clipboard_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (nbtk_clipboard_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_clipboard_finalize (GObject *object)
|
||||
{
|
||||
NbtkClipboardPrivate *priv = ((NbtkClipboard *) object)->priv;
|
||||
|
||||
g_free (priv->clipboard_text);
|
||||
priv->clipboard_text = NULL;
|
||||
|
||||
g_free (priv->supported_targets);
|
||||
priv->supported_targets = NULL;
|
||||
priv->n_targets = 0;
|
||||
|
||||
G_OBJECT_CLASS (nbtk_clipboard_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static ClutterX11FilterReturn
|
||||
nbtk_clipboard_provider (XEvent *xev,
|
||||
ClutterEvent *cev,
|
||||
NbtkClipboard *clipboard)
|
||||
{
|
||||
XSelectionEvent notify_event;
|
||||
XSelectionRequestEvent *req_event;
|
||||
|
||||
if (xev->type != SelectionRequest)
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
|
||||
req_event = &xev->xselectionrequest;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
if (req_event->target == __atom_targets)
|
||||
{
|
||||
XChangeProperty (req_event->display,
|
||||
req_event->requestor,
|
||||
req_event->property,
|
||||
XA_ATOM,
|
||||
32,
|
||||
PropModeReplace,
|
||||
(guchar*) clipboard->priv->supported_targets,
|
||||
clipboard->priv->n_targets);
|
||||
}
|
||||
else
|
||||
{
|
||||
XChangeProperty (req_event->display,
|
||||
req_event->requestor,
|
||||
req_event->property,
|
||||
req_event->target,
|
||||
8,
|
||||
PropModeReplace,
|
||||
(guchar*) clipboard->priv->clipboard_text,
|
||||
strlen (clipboard->priv->clipboard_text));
|
||||
}
|
||||
|
||||
notify_event.type = SelectionNotify;
|
||||
notify_event.display = req_event->display;
|
||||
notify_event.requestor = req_event->requestor;
|
||||
notify_event.selection = req_event->selection;
|
||||
notify_event.target = req_event->target;
|
||||
notify_event.time = req_event->time;
|
||||
|
||||
if (req_event->property == None)
|
||||
notify_event.property = req_event->target;
|
||||
else
|
||||
notify_event.property = req_event->property;
|
||||
|
||||
/* notify the requestor that they have a copy of the selection */
|
||||
XSendEvent (req_event->display, req_event->requestor, False, 0,
|
||||
(XEvent *) ¬ify_event);
|
||||
/* Make it happen non async */
|
||||
XSync (clutter_x11_get_default_display(), FALSE);
|
||||
|
||||
clutter_x11_untrap_x_errors (); /* FIXME: Warn here on fail ? */
|
||||
|
||||
return CLUTTER_X11_FILTER_REMOVE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nbtk_clipboard_class_init (NbtkClipboardClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NbtkClipboardPrivate));
|
||||
|
||||
object_class->get_property = nbtk_clipboard_get_property;
|
||||
object_class->set_property = nbtk_clipboard_set_property;
|
||||
object_class->dispose = nbtk_clipboard_dispose;
|
||||
object_class->finalize = nbtk_clipboard_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
nbtk_clipboard_init (NbtkClipboard *self)
|
||||
{
|
||||
Display *dpy;
|
||||
NbtkClipboardPrivate *priv;
|
||||
|
||||
priv = self->priv = CLIPBOARD_PRIVATE (self);
|
||||
|
||||
priv->clipboard_window =
|
||||
XCreateSimpleWindow (clutter_x11_get_default_display (),
|
||||
clutter_x11_get_root_window (),
|
||||
-1, -1, 1, 1, 0, 0, 0);
|
||||
|
||||
dpy = clutter_x11_get_default_display ();
|
||||
|
||||
/* Only create once */
|
||||
if (__atom_clip == None)
|
||||
__atom_clip = XInternAtom (dpy, "CLIPBOARD", 0);
|
||||
|
||||
if (__utf8_string == None)
|
||||
__utf8_string = XInternAtom (dpy, "UTF8_STRING", 0);
|
||||
|
||||
if (__atom_targets == None)
|
||||
__atom_targets = XInternAtom (dpy, "TARGETS", 0);
|
||||
|
||||
priv->n_targets = 2;
|
||||
priv->supported_targets = g_new (Atom, priv->n_targets);
|
||||
|
||||
priv->supported_targets[0] = __utf8_string;
|
||||
priv->supported_targets[1] = __atom_targets;
|
||||
|
||||
clutter_x11_add_filter ((ClutterX11FilterFunc) nbtk_clipboard_provider,
|
||||
self);
|
||||
}
|
||||
|
||||
static ClutterX11FilterReturn
|
||||
nbtk_clipboard_x11_event_filter (XEvent *xev,
|
||||
ClutterEvent *cev,
|
||||
EventFilterData *filter_data)
|
||||
{
|
||||
Atom actual_type;
|
||||
int actual_format, result;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *data = NULL;
|
||||
|
||||
if(xev->type != SelectionNotify)
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
|
||||
if (xev->xselection.property == None)
|
||||
{
|
||||
/* clipboard empty */
|
||||
filter_data->callback (filter_data->clipboard,
|
||||
NULL,
|
||||
filter_data->user_data);
|
||||
|
||||
clutter_x11_remove_filter ((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter,
|
||||
filter_data);
|
||||
g_free (filter_data);
|
||||
return CLUTTER_X11_FILTER_REMOVE;
|
||||
}
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
result = XGetWindowProperty (xev->xselection.display,
|
||||
xev->xselection.requestor,
|
||||
xev->xselection.property,
|
||||
0L, G_MAXINT,
|
||||
True,
|
||||
AnyPropertyType,
|
||||
&actual_type,
|
||||
&actual_format,
|
||||
&nitems,
|
||||
&bytes_after,
|
||||
&data);
|
||||
|
||||
if (clutter_x11_untrap_x_errors () || result != Success)
|
||||
{
|
||||
/* FIXME: handle failure better */
|
||||
g_warning ("Clipboard: prop retrival failed");
|
||||
}
|
||||
|
||||
filter_data->callback (filter_data->clipboard, (char*) data,
|
||||
filter_data->user_data);
|
||||
|
||||
clutter_x11_remove_filter
|
||||
((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter,
|
||||
filter_data);
|
||||
|
||||
g_free (filter_data);
|
||||
|
||||
if (data)
|
||||
XFree (data);
|
||||
|
||||
return CLUTTER_X11_FILTER_REMOVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_clipboard_get_default:
|
||||
*
|
||||
* Get the global #NbtkClipboard object that represents the clipboard.
|
||||
*
|
||||
* Returns: (transfer none): a #NbtkClipboard owned by Nbtk and must not be
|
||||
* unrefferenced or freed.
|
||||
*/
|
||||
NbtkClipboard*
|
||||
nbtk_clipboard_get_default (void)
|
||||
{
|
||||
static NbtkClipboard *default_clipboard = NULL;
|
||||
|
||||
if (!default_clipboard)
|
||||
{
|
||||
default_clipboard = g_object_new (NBTK_TYPE_CLIPBOARD, NULL);
|
||||
}
|
||||
|
||||
return default_clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_clipboard_get_text:
|
||||
* @clipboard: A #NbtkCliboard
|
||||
* @callback: function to be called when the text is retreived
|
||||
* @user_data: data to be passed to the callback
|
||||
*
|
||||
* Request the data from the clipboard in text form. @callback is executed
|
||||
* when the data is retreived.
|
||||
*
|
||||
*/
|
||||
void
|
||||
nbtk_clipboard_get_text (NbtkClipboard *clipboard,
|
||||
NbtkClipboardCallbackFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
EventFilterData *data;
|
||||
|
||||
Display *dpy;
|
||||
|
||||
g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
data = g_new0 (EventFilterData, 1);
|
||||
data->clipboard = clipboard;
|
||||
data->callback = callback;
|
||||
data->user_data = user_data;
|
||||
|
||||
clutter_x11_add_filter ((ClutterX11FilterFunc)nbtk_clipboard_x11_event_filter,
|
||||
data);
|
||||
|
||||
dpy = clutter_x11_get_default_display ();
|
||||
|
||||
clutter_x11_trap_x_errors (); /* safety on */
|
||||
|
||||
XConvertSelection (dpy,
|
||||
__atom_clip,
|
||||
__utf8_string, __utf8_string,
|
||||
clipboard->priv->clipboard_window,
|
||||
CurrentTime);
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
}
|
||||
|
||||
/**
|
||||
* nbtk_clipboard_set_text:
|
||||
* @clipboard: A #NbtkClipboard
|
||||
* @text: text to copy to the clipboard
|
||||
*
|
||||
* Sets text as the current contents of the clipboard.
|
||||
*
|
||||
*/
|
||||
void
|
||||
nbtk_clipboard_set_text (NbtkClipboard *clipboard,
|
||||
const gchar *text)
|
||||
{
|
||||
NbtkClipboardPrivate *priv;
|
||||
Display *dpy;
|
||||
|
||||
g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
priv = clipboard->priv;
|
||||
|
||||
/* make a copy of the text */
|
||||
g_free (priv->clipboard_text);
|
||||
priv->clipboard_text = g_strdup (text);
|
||||
|
||||
/* tell X we own the clipboard selection */
|
||||
dpy = clutter_x11_get_default_display ();
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
XSetSelectionOwner (dpy, __atom_clip, priv->clipboard_window, CurrentTime);
|
||||
XSync (dpy, FALSE);
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
}
|