Compare commits

..

51 Commits
3.3.3 ... 3.2.2

Author SHA1 Message Date
f8c980cb22 Bump version to 3.2.2
Update NEWS
2012-01-18 10:22:09 -05:00
74ed3646ad workspaceThumbnail: fix window tracking bugs
- We should only call workspaceRemoved() for workspaces that are
  are actually being removed.
- When we have multiple monitors, a window on a secondary monitor is
  on all workspaces, so it ends up in all workspaces _allWindows
  lists, so we can't use previous presence in that list to determine
  whether we need to go ahead and add the actor; allWindows is simply
  the list of windows where we are listening  to notify::minimized.

https://bugzilla.gnome.org/show_bug.cgi?id=667652
2012-01-18 10:22:09 -05:00
80dfda17cd messageTray: use a "hot corner" to summon the tray
Instead of leaving the tray covering the whole last pixel row when it's
hidden, hide it completely. This avoids mouse events not being delivered to
application windows on the last pixel row.

To summon the tray we use a single reactive pixel on the corner.

https://bugzilla.gnome.org/show_bug.cgi?id=663366
2012-01-17 13:38:40 -05:00
3e98d47687 st: Fix typo
Commit c7846e1 introduced a small typo, fix.
2012-01-17 11:04:19 -05:00
3d3494a15b st-icon: Fix memory leak
We were never freeing the dup'd icon_name string for an StIcon.
2012-01-17 11:04:09 -05:00
3bf11dbd31 st-theme-node: Fix memory leak
We ref the icon_colors in st_theme_node_get_icon_colors, but never
unref it.
2012-01-17 11:03:59 -05:00
626e962e03 Network Menu: fix pulling out the first element from the More... submenu.
PopupMenu.firstMenuItem returns a PopupMenuItem, not an apObj. We
need to retrive the latter using the _apObj property.

Also, somehow the property from the number of elements in a menu
was changed from .length to .numMenuItems, and this broke the
destruction of the menu upon emptying it.

https://bugzilla.gnome.org/show_bug.cgi?id=659277
2012-01-17 11:00:56 -05:00
759de873b5 NetworkMenu: fix regression in access-point-removed
When changing _findNetwork with _findExistingNetwork, I changed
the return value to avoid searching twice for the access point,
and changed some names. I forgot to update all points where those
names were used.

https://bugzilla.gnome.org/show_bug.cgi?id=663278
2012-01-17 11:00:43 -05:00
552ae78557 NetworkMenu: don't query DBus properties of removed objects
Calling nm_access_point_get_ssid() in the handler of the
access-point-removed signal can result in DBus request, which will
then fail because the object was already removed at the server side.
Instead, use a difference function to retrieve the access point
object (the network), that compares directly by object identity.

https://bugzilla.gnome.org/show_bug.cgi?id=651378
2012-01-17 11:00:32 -05:00
d85a16589b messageTray: don't steal focus when popping under the pointer
We must look for the actor under the pointer in the whole message tray and not
just in the notification. This will avoid us to capture focus when a
notification comes up with the pointer on the whole tray area.

https://bugzilla.gnome.org/show_bug.cgi?id=661358
2012-01-17 11:00:04 -05:00
136c76dcbe gnome-shell-extension-tool: Use xdg-open
gnome-open is deprecated
2012-01-17 10:57:12 -05:00
2d95201af2 gnome-shell-extension-tool: Fix error after creating extension
Commit 7a8a00c705 cleaned up the code to move all
files to a dictionary, which accidentally left an undefined "extensionjs_path"
error. Fix that error.

https://bugzilla.gnome.org/show_bug.cgi?id=661623
2012-01-17 10:57:07 -05:00
039c683bac workspaceThumbnail: improve handling of notify::minimized signal
There were various cases where we could lose track of a window and
leave the notify::minimized signal connect after the actor was destroyed
or the workspace removed. This could result in operations on a removed
workspace and assertion failures inside Mutter.

https://bugzilla.redhat.com/show_bug.cgi?id=773059
https://bugzilla.gnome.org/show_bug.cgi?id=667652
2012-01-17 10:56:09 -05:00
d9ab2320d5 workspaceThumbnail: disconnect handlers when workspace is removed
We need to remove the handlers when the workspace is removed, not
when the animation of it being removed finishes, or we can access
a destroyed workspace and triggger an assertion failure in Mutter.

https://bugzilla.redhat.com/show_bug.cgi?id=705664
https://bugzilla.gnome.org/show_bug.cgi?id=667652
2012-01-17 10:55:58 -05:00
fa515328eb hotplug-sniffer: fix double free when setting D-Bus return value
g_dbus_method_invocation_return_value() adopts a floating reference,
so we don't also need to unreference it; fix by replacing the code
using a more compact form using the ^ convenience character in
GVariant type specifications. (Thanks to Ryan Lortie for the
suggestion.)

https://bugzilla.gnome.org/show_bug.cgi?id=667378
2012-01-17 10:55:21 -05:00
0cfedcaad6 theme-node-drawing: don't crash if st_theme_node_paint() is called on an empty area
When st_theme_node_paint() was called with zero width or height and a theme
node with a shadow, we'd crash because we'd fail to allocate a texture with
an empty size, then unreference the NULL pointer.

https://bugzilla.redhat.com/show_bug.cgi?id=748293
https://bugzilla.gnome.org/show_bug.cgi?id=668050
2012-01-16 17:38:02 -05:00
65230bfd7f st-theme-node-drawing: clear border buffer before drawing on it
A new texture has undefined contents - when we're creating a shadow,
we need to clear the contents of the texture before drawing the border
and background into it.

https://bugzilla.gnome.org/show_bug.cgi?id=668048
2012-01-16 17:37:51 -05:00
a5324462c3 iconGrid: avoid recreating icons unnecessarily
Add a short-circuit when the size doesn't change. Taken from part
of 26580f8f2c (Giovanni Campagna). This greatly reduces the reentrancy
of recreating icons that seems to be responsible for many crashers,
though the exact mechanism for the crashes isn't clear. See:

https://bugzilla.gnome.org/show_bug.cgi?id=648450
https://bugzilla.redhat.com/show_bug.cgi?id=707652
https://bugzilla.redhat.com/show_bug.cgi?id=781780
2012-01-16 17:28:40 -05:00
7e654ab3ca notificationDaemon: group sources based on a combination of pid and title
That way different system notifications, such as the ones about battery power
and the ones about software updates, are shown with separate message tray
sources.

https://bugzilla.gnome.org/show_bug.cgi?id=664138
2012-01-05 08:46:05 -05:00
9601908fca browser-plugin: Fix installation on WebKit-like browsers
I missed this use of raw UTF8Characters last time. Hopefully this
should be the last fix required for WebKit support.

https://bugzilla.gnome.org/show_bug.cgi?id=666444
2012-01-04 18:06:51 -05:00
ab4c160f9d browser-plugin: Fix memory leak when passing an invalid UUID
https://bugzilla.gnome.org/show_bug.cgi?id=665261
2012-01-04 18:06:51 -05:00
234882cbc6 browser-plugin: Fix crash if shell is not running 2012-01-04 18:06:51 -05:00
e890674e49 browser-plugin: Make sure to use the UTF8Length parameter
Some plugin hosts may have junk after the UTF8Characters that we need to strip
off. No current browsers that I know of do this, but it still helps to be
correct.
2012-01-04 18:06:51 -05:00
cd01e2fb25 browser-plugin: Move "entry points" comment
https://bugzilla.gnome.org/show_bug.cgi?id=663823
2012-01-04 18:06:51 -05:00
62027beb8e browser-plugin: Use g_strndup to get a string property
WebKit-based browsers like Chromium and Epiphany may insert extra junk at the
end of NPStrings, so we cannot depend on the strlen matching.

https://bugzilla.gnome.org/show_bug.cgi?id=663823
2012-01-04 18:06:51 -05:00
ee4d861a29 browser-plugin: Set that we need XEmbed
This makes the plugin work under WebKit-based browsers such as Chromium and
Epiphany. See http://code.google.com/p/chromium/issues/detail?id=38229 and
WindowedCreatePlugin() in
http://src.chromium.org/viewvc/chrome/trunk/src/webkit/plugins/npapi/webplugin_delegate_impl_gtk.cc?revision=86823&content-type=text%2Fplain
for more information.

https://bugzilla.gnome.org/show_bug.cgi?id=663823
2012-01-04 18:06:51 -05:00
3a3e26c1bd fileUtils: Fix recursivelyDeleteDir 2012-01-04 17:57:08 -05:00
bf2ad9d4e8 app: Fix crash on search
Not all desktop files tracked by the shell have
Exec lines.  This could be because they're actually
run by another process, for instance, and the desktop
file is merely there to provide metadata.  For example,
nautilus-pastebin provides a desktop file without an
Exec line.

The shell currently crashes if one of these partial
desktop files is installed and the user attempts to
search from the overview.

commit 37726a4cb6 fixed
a similar crasher.

This commit fixes the next one lower in the code.

https://bugzilla.gnome.org/show_bug.cgi?id=663815
2012-01-04 17:42:53 -05:00
b053d9c84f Updated Danish translation 2012-01-03 12:21:00 +01:00
4afa8bebdb Updated Norwegian Nynorsk translation 2011-12-26 14:33:01 +01:00
caf3d5add0 Updated Lithuanian translation 2011-12-06 17:10:37 +02:00
7cf038474a Updated Finnish translation 2011-11-15 22:20:36 +02:00
c7bcc8150c Updated British English translation 2011-11-12 07:48:52 +00:00
6d58397508 Updated Japanese translation 2011-11-09 21:23:48 +09:00
49d0fc178d Updated Czech translation 2011-10-30 14:31:52 +01:00
b83b8f64ff Updated French translation 2011-10-29 19:03:56 +02:00
6cc8a42720 Updated Esperanto translation 2011-10-26 19:05:10 +02:00
50a2d285eb Updated Swedish translation 2011-10-26 11:55:01 +02:00
fdf05310e9 Updated Persian translation 2011-10-24 21:13:22 +03:30
7baa393b1b [l10n]Updated Catalan (Valencian) translation 2011-10-23 23:43:01 +02:00
113694c44b [l10n]Updated Catalan translation 2011-10-23 23:42:57 +02:00
0c2f51b27f Updated Swedish translation 2011-10-23 13:07:22 +02:00
04cb84de2a Updated Lithuanian translation 2011-10-22 23:00:54 +03:00
9475c16e80 Updated Slovenian translation 2011-10-22 13:20:39 +02:00
6f41a9e10c Updated Bulgarian translation 2011-10-21 23:31:28 +03:00
be3b939a24 Updated Slovenian translation 2011-10-21 21:32:39 +02:00
04fb3a5a7c Updated Brazilian Portuguese translation 2011-10-20 12:46:59 -02:00
697b6dbfff Updated Brazilian Portuguese translation 2011-10-20 12:39:00 -02:00
bb4639e423 Updated Telugu Translation 2011-10-20 16:41:52 +05:30
69db63b4cd Updated Vietnamese translation 2011-10-19 19:39:27 +11:00
f9d17b214e po/vi: import from Damned Lies 2011-10-19 19:38:35 +11:00
174 changed files with 11049 additions and 18002 deletions

13
.gitignore vendored
View File

@ -21,19 +21,6 @@ data/gnome-shell.desktop.in
data/gschemas.compiled
data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid
docs/reference/*/*.args
docs/reference/*/*.bak
docs/reference/*/*.hierarchy
docs/reference/*/*.interfaces
docs/reference/*/*.prerequisites
docs/reference/*/*.sgml
docs/reference/*/*.signals
docs/reference/*/*.stamp
docs/reference/*/*.txt
docs/reference/*/*.types
docs/reference/*/html/
docs/reference/*/xml/
gtk-doc.make
js/misc/config.js
intltool-extract.in
intltool-merge.in

View File

@ -1,7 +1,7 @@
# Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src browser-plugin tests po man docs
SUBDIRS = data js src browser-plugin tests po man
EXTRA_DIST = \
.project \
@ -19,5 +19,3 @@ DIST_EXCLUDE = \
distcheck-hook:
@echo "Checking disted files against files in git"
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc

136
NEWS
View File

@ -1,106 +1,46 @@
3.3.3
3.2.2
=====
* https://live.gnome.org/EveryDetailMatters
- Stop flashing the window labels on actions in overview [Zan; #644861]
- Improve the look of window captions in the overview [Marc; #664487]
- Move dash tooltips beside the icon [Seif, Stefano; #666166]
* Support application menus exported from applications via new GLib API
and D-Bus protocol. [Giovanni, Colin, Matthias, Cosimo]
* For removable device prompts, show "Open with Rhythmbox], rather
than "Open with Rhythmbox Music Player' [Florian; #664561]
* Switch to activating the message tray only with a hot corner rather
than a full row of pixels, allowing mouse events to apps [Rui; #663366]
* Fully handle the case where the workspaces-only-on-primary
GSetting is set to false [Florian; #652580]
* Add support for background-size CSS property to St [Quentin; #633462]
* Port to new GJS Lang.Class framework [Giovanni; #664436]
* Finish port to GDBus [Giovanni; #664436]
* Stop using the deprecated Clutter default stage [Florian, Jasper; #664052]
* Fix bugs that kept browser plugin from working in WebKit-based browser
[Jasper; #666444]
* Fix typo that made uninstalling extensions not work [Jasper]
* Fix crash in browser plugin if shell is not run [Jürg]
* Reintroduce piscine paschal ovum [Giovanni; #666606]
* Network menu bug fixes
Giovanni; #664124, #665194, #665680, #666429, #666614]
* Misc bug fixes [Florian, Jasper, Jonny, Marina, Ron; #647587, #659272,
#665261, #666020, #666243]
* Fix crash when searching in the shell caused by .desktop files
without Exec= lines (commonly, nautilus-pastebin) [Ray; #663815]
* Message Tray:
- Fix bug that would cause confusion between notifications from different
services running in the gnome-settings-daemon process
[Marina, Jasper; #664138]
- Don't steal the focus when popping up beneath the pointer [Rui; #661358]
- Only pop up the message tray from a hot corner, rather than trapping
clicks on the entire bottom row. [Rui; #663366]
* Browser plugin and extension.gnome.org integration
- Fix multiple bugs that kept the plugin from working in WebKit-based browsers
[Jasper, #663823, #666444]
- Fix plugin crash when the shell is installed but not running [Jürg]
- Fix problem that kept plugin uninstallation from working [Jasper]
* gnome-shell-extension-tool
- Fix error that was printed after creating an extension [Jasper; #661623]
- Use xdg-open rather than the deprecated gnome-open [Jasper]
* Don't recreate dash icons unnecessarily - this hopefully fixes various
crashes. [Owen, Giovanni; #648450]
* Fix several bugs that caused errors and slowdowns when updating the
network menu. [Giovanni; #651378, #659277, #663278]
* Fix several crashers related to updating workspace thumbnails
[Owen; #667652]
* Fix memory management error causing gnome-shell-hotplug-sniffer to crash
[Owen; #667378]
* Fix crash and misdrawing with shadowed elements [Owen; #668048, #668050]
* Fix several small memory leaks. [Jasper, Florian]
Contributors:
Jürg Billeter, Giovanni Campagna, Stefano Candori, Cosimo Cecchi,
Matthias Clasen, Zan Dobersek, Quentin Glidic, Jonny Lamb, Ryan Lortie,
Seif Lotfy, Rui Matos, Florian Müllner, Bastien Nocera, Jasper St. Pierre,
Marc Plano-Lesay, Colin Walters, Ron Yorsten, Marina Zhurakhinskaya
Jürg Billeter, Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode,
Owen Taylor, Marina Zhurakhinskaya
Translations:
Petr Kovar [cz], Kris Thomsen [dk], Daniel Mustieles [es],
Ville-Pekka Vainio [fi], Yaron Shahrabani [he], Žygimantas Beručka [lt],
Jovan Naumovski [mk], Kjartan Maraas [nb], "Andreas N" [nn],
Lucian Adrian Grijincu [ro], Matej Urbančič [sl], Praveen Illa [te],
Muhammet Kara [tr], Daniel Korostil [uk], Aron Xu [zh_CN]
3.3.2
=====
* Port D-Bus usage in the shell to GDBus [Giovanni, Marc-Antoine, Florian,
Jasper, Matthias; #648651, #658078, #663902, #663941]
* Message tray
- Add right-click option to chats to mute the conversation [Ana; #659962]
- Don't steal the focus when popping up under the pointer [Rui; #661358]
* Looking Glass
- Add alt-Tab completion [Jason; #661054]
- Show errors from extensions in the extensions tab [Jasper; #660546]
- Allow switching tabs with <Control>PageUp/PageDown
- Theme consistently with the rest of the shell [Jason; 650900]
* Extension system
- Don't try to load disabled extensions at all [Jasper; #661815, #662704]
- Enable and disable plugins in a consistent order [Jasper; #661815, #662704]
- Add options to enable/disable extensions to gnome-shell-extension-tool
[Jasper; #661815]
* Adapt to Mutter change to GSettings [Florian, Matthias; #663429]
* Allow creating a new workspace by dragging a window or launcher in the
middle of two existing ones [Jasper; #646409]
* Allow using Alt-Tab while during drag-and-drop and other operations
that grab the pointer [Adel; #660457]
* Do a better job of finding the right user to authenticate
as when showing a PolKit dialog [Matthias; #651547]
* Control the D-Bus Eval() method by the developer-tools GSetting which
is used for looking glass and screen recorder. [Jasper; #662891]
* Fix browser plugin to work under WebKit-based browser [Jasper; #663823]
* Fix certain stacking issues with alt-Tab [Jasper; #660650]
* Fixes for GLib deprecations [Jasper; #662011]p
* Fixes for GTK+ deprecations [Florian, Rico; #662245]p
* Fixes for Clutter deprecations [Jasper; #662627]
* Visual improvements and UI tweaks [Florian, Jakub, Jasper;
#662800, #658096, #662226]
* Hard-code "Home" as the name for the home dir, rather than looking
it up via GSettings; avoids schema dependency [Cosimo; #559895]
* Don't show "Switch User" on single user machines [Florian; #657011]
* Generate documentation for St toolkit [Florian]
* Improve marking of strings for translation [Matthias, Piotr; #658664]
* Networking menu bug fixes [Giovanni; #650007, #651378, #659277, #663278]
* Code cleanups and leak fixes to StTextureCache
[Jasper, Florian; #660968, #662998]
* Code cleanups [Adel, Florian, Jasper; #662238, #663584]
* Build fixes [Adel, Colin, Florian, Ming Han]
* Misc bug fixes [Adel, Florian, "Fry", Jasper, Giovanni, Ray, Rui, Stefan;
#660520, #661029, #661231, #661623, #661921, #662235, #662236, #662502,
#662394, #662799, #662969, #663175, #663277, #663815, #663891, #662967]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Piotr Drąg, Adel Gadllah,
Rui Matos, Florian Müllner, Marc-Antoine Perennou, Ana Risteska,
Jason Siefken, Jakub Steiner, Ray Strode, Jasper St. Pierre, Ming Han Teh,
Rico Tzschichholz, Colin Walters, Stefan Zwanenburg
Translation:
Alexander Shopov [bg], Marek Černocký [cs], Mario Blättermann [de],
Kostas Papadimas [el], Bruce Cowan [en_GB], Kristjan Schmidt [eo],
Jorge González, Daniel Mustieles, Benjamín Valero Espinosa [es],
Mattias Põldaru [et], Arash Mousavi [fa], Ville-Pekka Vainio [fi],
Fran Diéguez [gl], Yaron Shahrabani [he], Hideki Yamane [ja],
Algimantas Margevičius [lt], Kjartan Maraas [nb], Daniel Nylander [se],
Matej Urbančič [sl], Praveen Illa [te], Muhammet Kara [tr],
Nguyễn Thái Ngọc Duy [vi], Cheng-Chia Tseng [zh_HK, zh_TW]
Alexander Shopov [bg], Gil Forcada [ca], Carles Ferrando [ca@valencia],
Marek Černocký [cz], Kris Thomsen [dk], Bruce Cowan [en_GB],
Kristjan Schmidt [eo], Daniel Mustieles [es], Arash Mousavi [fa],
Ville-Pekka Vainio [fi], Bruno Brouard [fr], Hideki Yamane [ja],
Žygimantas Beručka, Aurimas Černius [lt], Kjartan Maraas [nb],
"Andreas N" [nn], Djavan Fagundes, Antonio Fernandes C. Neto [pt_BR],
Daniel Nylander [se], Matej Urbančič [sl], Praveen Illa [te],
Nguyễn Thái Ngọc Duy [vi]
3.2.1
=====

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.3.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.2.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -36,6 +36,10 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
PKG_PROG_PKG_CONFIG([0.22])
# GConf stuff
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
AM_GCONF_SOURCE_2
GLIB_GSETTINGS
# Get a value to substitute into gnome-shell.in
@ -63,10 +67,10 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.7.5
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.29.18
MUTTER_MIN_VERSION=3.3.3
MUTTER_MIN_VERSION=3.2.1
FOLKS_MIN_VERSION=0.5.2
GTK_MIN_VERSION=3.0.0
GIO_MIN_VERSION=2.31.0
GIO_MIN_VERSION=2.29.10
LIBECAL_MIN_VERSION=2.32.0
LIBEDATASERVER_MIN_VERSION=1.2.0
LIBEDATASERVERUI_MIN_VERSION=2.91.6
@ -76,13 +80,13 @@ POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
libxml-2.0
PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
gio-unix-2.0 dbus-glib-1 libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION
folks >= $FOLKS_MIN_VERSION
libmutter >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 $recorder_modules
libgnome-menu-3.0 $recorder_modules gconf-2.0
gdk-x11-3.0 libsoup-2.4
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
@ -117,6 +121,7 @@ CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 gnome-desktop-3.0 >= 2.90.0 x11)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)
@ -126,7 +131,6 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
AC_SUBST([BLUETOOTH_DIR],["$BLUETOOTH_DIR"])
AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
AC_SUBST([HAVE_BLUETOOTH],[1])
@ -175,13 +179,11 @@ AC_SUBST(GIRDIR)
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
AC_SUBST(TYPELIBDIR)
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=maximum)
enable_compile_warnings=error)
changequote(,)dnl
if test "$enable_compile_warnings" != no ; then
@ -239,12 +241,6 @@ AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
AC_CONFIG_FILES([
Makefile
data/Makefile
docs/Makefile
docs/reference/Makefile
docs/reference/shell/Makefile
docs/reference/shell/shell-docs.sgml
docs/reference/st/Makefile
docs/reference/st/st-docs.sgml
js/Makefile
js/misc/config.js
src/Makefile

View File

@ -60,14 +60,23 @@ gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
all-local: gschemas.compiled
# GConf schemas: provide defaults for keys from Metacity we are overriding
gconfschemadir = @GCONF_SCHEMA_FILE_DIR@
gconfschema_DATA = gnome-shell.schemas
shadersdir = $(pkgdatadir)/shaders
shaders_DATA = \
shaders/dim-window.glsl
install-data-local:
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(gconfschema_DATA)
EXTRA_DIST = \
gnome-shell.desktop.in.in \
$(menu_DATA) \
$(gconfschema_DATA) \
$(shaders_DATA) \
org.gnome.shell.gschema.xml.in

100
data/gnome-shell.schemas Normal file
View File

@ -0,0 +1,100 @@
<gconfschemafile>
<schemalist>
<!-- Metacity overrides -->
<schema>
<key>/schemas/desktop/gnome/shell/windows/attach_modal_dialogs</key>
<applyto>/desktop/gnome/shell/windows/attach_modal_dialogs</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Attach modal dialog to the parent window</short>
<long>
This key overrides /apps/mutter/general/attach_modal_dialogs when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/windows/button_layout</key>
<applyto>/desktop/gnome/shell/windows/button_layout</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>:close</default>
<locale name="C">
<short>Arrangement of buttons on the titlebar</short>
<long>
Arrangement of buttons on the titlebar. The
value should be a string, such as
"menu:minimize,maximize,spacer,close"; the colon separates the
left corner of the window from the right corner, and
the button names are comma-separated. Duplicate buttons
are not allowed. Unknown button names are silently ignored
so that buttons can be added in future gnome-shell versions
without breaking older versions.
A special spacer tag can be used to insert some space between
two adjacent buttons.
This key overrides /apps/metacity/general/button_layout when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/windows/edge_tiling</key>
<applyto>/desktop/gnome/shell/windows/edge_tiling</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>enable edge tiling when dropping windows on screen edges</short>
<long>
If enabled, dropping windows on vertical screen edges maximizes them
vertically and resizes them horizontally to cover half of the
available area. Dropping windows on the top screen edge maximizes them
completely.
This key overrides /apps/metacity/general/edge_tiling when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/windows/theme</key>
<applyto>/desktop/gnome/shell/windows/theme</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>Adwaita</default>
<locale name="C">
<short>Current theme</short>
<long>
The theme determines the appearance of window borders,
titlebar, and so forth.
This key overrides /apps/metacity/general/theme when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/windows/workspaces_only_on_primary</key>
<applyto>/desktop/gnome/shell/windows/workspaces_only_on_primary</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Workspaces only on primary monitor</short>
<long>
This key overrides /apps/mutter/general/workspaces_only_on_primary when
running GNOME Shell.
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@ -16,9 +16,8 @@
<_summary>Uuids of extensions to enable</_summary>
<_description>
GNOME Shell extensions have a uuid property; this key lists extensions
which should be loaded. Any extension that wants to be loaded needs
to be in this list. You can also manipulate this list with the
EnableExtension and DisableExtension DBus methods on org.gnome.Shell.
which should be loaded. disabled-extensions overrides this setting for
extensions that appear in both lists.
</_description>
</key>
<key name="enable-app-monitoring" type="b">
@ -142,40 +141,4 @@
</_description>
</key>
</schema>
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/">
<key name="attach-modal-dialogs" type="b">
<default>true</default>
<summary>Attach modal dialog to the parent window</summary>
<description>
This key overrides the key in org.gnome.mutter when running
GNOME Shell.
</description>
</key>
<key name="button-layout" type="s">
<default>":close"</default>
<summary>Arrangement of buttons on the titlebar</summary>
<description>
This key overrides the key in org.gnome.desktop.wm.preferences when
running GNOME Shell.
</description>
</key>
<key name="edge-tiling" type="b">
<default>true</default>
<summary>Enable edge tiling when dropping windows on screen edges</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
<key name="workspaces-only-on-primary" type="b">
<default>true</default>
<summary>Workspaces only on primary monitor</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
</schema>
</schemalist>

View File

@ -36,18 +36,18 @@ stage {
StScrollBar
{
padding: 0px;
padding: 0px;
}
StScrollView.vfade
{
-st-vfade-offset: 68px;
-st-vfade-offset: 68px;
}
StScrollView StScrollBar
{
min-width: 16px;
min-height: 16px;
min-width: 16px;
min-height: 16px;
}
@ -60,7 +60,6 @@ StScrollBar StBin#trough {
StScrollBar StButton#vhandle
{
background-image: url("scroll-vhandle.svg");
background-size: contain;
background-color: #252525;
border: 1px solid #080808;
border-radius: 8px;
@ -69,7 +68,6 @@ StScrollBar StButton#vhandle
StScrollBar StButton#hhandle
{
background-image: url("scroll-hhandle.svg");
background-size: contain;
background-color: #252525;
border: 1px solid #080808;
border-radius: 8px;
@ -226,20 +224,16 @@ StTooltip StLabel {
.toggle-switch-us {
background-image: url("toggle-off-us.svg");
background-size: contain;
}
.toggle-switch-us:checked {
background-image: url("toggle-on-us.svg");
background-size: contain;
}
.toggle-switch-intl {
background-image: url("toggle-off-intl.svg");
background-size: contain;
}
.toggle-switch-intl:checked {
background-image: url("toggle-on-intl.svg");
background-size: contain;
}
.nm-menu-item-icons {
@ -362,7 +356,6 @@ StTooltip StLabel {
.panel-button:focus {
border-image: url("panel-button-border.svg") 10 10 0 2;
background-image: url("panel-button-highlight-wide.svg");
background-size: contain;
color: white;
text-shadow: black 0px 2px 2px;
}
@ -371,7 +364,6 @@ StTooltip StLabel {
.panel-status-button:checked,
.panel-status-button:focus {
background-image: url("panel-button-highlight-narrow.svg");
background-size: contain;
}
.panel-button:active > .system-status-icon,
@ -475,17 +467,16 @@ StTooltip StLabel {
}
.window-caption {
background: rgba(0,0,0,0.5);
border-radius: 8px;
background: rgba(0,0,0,0.8);
border: 1px solid rgba(128,128,128,0.40);
border-radius: 10px;
font-size: 9pt;
font-weight: bold;
padding: 6px 12px;
-shell-caption-spacing: 12px;
padding: 2px 8px;
-shell-caption-spacing: 4px;
}
.window-close {
background-image: url("close-window.svg");
background-size: 34px;
height: 34px;
width: 34px;
-shell-close-overlap: 20px;
@ -518,10 +509,8 @@ StTooltip StLabel {
width: 60px;
}
.placeholder {
.dash-placeholder {
background-image: url("dash-placeholder.svg");
background-size: contain;
height: 24px;
}
#viewSelector {
@ -655,17 +644,6 @@ StTooltip StLabel {
font-size: 11pt;
}
.dash-label {
border-radius: 7px;
padding: 4px 12px;
background-color: rgba(0,0,0,0.5);
color: #ffffff;
font-size: 0.9em;
font-weight: bold;;
text-align: center;
-x-offset: 8px;
}
/* Apps */
.icon-grid {
@ -707,13 +685,11 @@ StTooltip StLabel {
.app-filter:selected {
color: #ffffff;
background-image: url("filter-selected-ltr.svg");
background-size: contain;
background-position: 190px 10px;
}
.app-filter:selected:rtl {
background-image: url("filter-selected-rtl.svg");
background-size: contain;
background-position: 10px 10px;
}
@ -766,24 +742,24 @@ StTooltip StLabel {
}
.contact-icon {
border-radius: 4px;
border-radius: 4px;
}
.contact-details {
padding: 6px 8px 11px 8px;
padding: 6px 8px 11px 8px;
}
.contact-details-alias {
font-size: 16px;
padding-bottom: 11px;
font-size: 16px;
padding-bottom: 11px;
}
.contact-details-status {
font-size: 11pt;
font-size: 11pt;
}
.contact-details-status-icon {
padding-right: 2px;
padding-right: 2px;
}
.contact:hover {
@ -794,7 +770,6 @@ StTooltip StLabel {
.app-well-app.running > .overview-icon {
text-shadow: black 0px 2px 2px;
background-image: url("running-indicator.svg");
background-size: contain;
}
.contact:selected,
@ -825,45 +800,37 @@ StTooltip StLabel {
#LookingGlassDialog
{
background-color: rgba(0,0,0,0.80);
spacing: 4px;
padding: 4px;
border: 2px solid grey;
border-radius: 4px;
background-color: rgba(0,0,0,0.85);
spacing: 4px;
padding: 4px;
border: 2px solid grey;
border-radius: 4px;
color: #ffffff;
color: #88ff66;
}
#LookingGlassDialog > #Toolbar
{
border: 1px solid grey;
border-radius: 4px;
border: 1px solid grey;
border-radius: 4px;
}
#LookingGlassDialog .labels {
spacing: 4px;
spacing: 4px;
}
#LookingGlassDialog .notebook-tab {
-natural-hpadding: 12px;
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
transition-duration: 100;
padding-left: .3em;
padding-right: .3em;
padding: 2px;
}
#LookingGlassDialog .notebook-tab:hover {
color: white;
text-shadow: black 0px 2px 2px;
color: #00ff00;
}
#LookingGlassDialog .notebook-tab:selected {
border-image: url("panel-button-border.svg") 10 10 0 2;
background-image: url("panel-button-highlight-wide.svg");
color: white;
text-shadow: black 0px 2px 2px;
border: 1px solid #88ff66;
border-radius: 4px;
padding: 5px;
}
#LookingGlassDialog .lg-inspector-title {
@ -873,58 +840,52 @@ StTooltip StLabel {
.lg-dialog StLabel
{
color: #ffffff;
color: #88ff66;
}
.lg-dialog StEntry
{
color: #ffffff;
selection-background-color: #bbbbbb;
selected-color: #333333;
}
.lg-completions-text
{
font-size: .9em;
font-style: italic;
color: #88ff66;
selection-background-color: #88ff66;
selected-color: black;
}
.lg-obj-inspector-title
{
spacing: 4px;
spacing: 4px;
}
.lg-obj-inspector-button
{
border: 1px solid gray;
padding: 4px;
border-radius: 4px;
border: 1px solid #88ff66;
padding: 4px;
border-radius: 4px;
}
.lg-obj-inspector-button:hover
{
border: 1px solid #ffffff;
border: 1px solid #00ff00;
}
.lg-dialog .shell-link
{
color: #999999;
color: #88ff66;
}
.lg-dialog .shell-link:hover
{
color: #dddddd;
color: #00ff00;
}
#LookingGlassDialog StBoxLayout#EvalBox
{
padding: 4px;
spacing: 4px;
padding: 4px;
spacing: 4px;
}
#LookingGlassDialog StBoxLayout#ResultsArea
{
spacing: 4px;
spacing: 4px;
}
#lookingGlassExtensions {
@ -951,11 +912,11 @@ StTooltip StLabel {
}
#LookingGlassPropertyInspector {
background: rgba(0, 0, 0, 0.8);
background: rgba(0, 0, 0, 0.9);
border: 2px solid grey;
border-radius: 4px;
padding: 6px;
color: #ffffff;
color: #88ff66;
}
/* Calendar popup */
@ -1248,7 +1209,6 @@ StTooltip StLabel {
#notification-scrollview {
max-height: 10em;
-st-vfade-offset: 24px;
}
#notification-scrollview > .top-shadow, #notification-scrollview > .bottom-shadow {
@ -1291,8 +1251,7 @@ StTooltip StLabel {
}
.notification-icon-button > StIcon {
icon-size: 16px;
padding: 8px;
icon-size: 36px;
}
.hotplug-transient-box {
@ -1362,8 +1321,9 @@ StTooltip StLabel {
padding: 8px 0;
}
.chat-received {
.chat-sent {
padding-left: 4px;
border-radius: 4px;
}
.chat-received:rtl {
@ -1373,7 +1333,8 @@ StTooltip StLabel {
.chat-sent {
padding-left: 18pt;
color: #959595;
border-radius: 4px;
color: #7E7E7E;
}
.chat-sent:rtl {
@ -1383,6 +1344,7 @@ StTooltip StLabel {
.chat-meta-message {
padding-left: 4px;
border-radius: 4px;
font-size: 9pt;
color: #bbbbbb;
}
@ -1456,7 +1418,6 @@ StTooltip StLabel {
.summary-source-button:selected .summary-source {
background-image: url("panel-button-highlight-narrow.svg");
background-size: contain;
border-image: url("source-button-border.svg") 10 10 0 1;
}
@ -1467,7 +1428,6 @@ StTooltip StLabel {
.summary-source-button:expanded:selected {
background-image: url("panel-button-highlight-wide.svg");
background-size: contain;
border-image: url("source-button-border.svg") 10 10 0 1;
}
@ -1581,7 +1541,6 @@ StTooltip StLabel {
width: 52px;
height: 52px;
background-image: url("corner-ripple-ltr.png");
background-size: contain;
}
.ripple-box:rtl {
@ -1623,7 +1582,6 @@ StTooltip StLabel {
border: 0px;
background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-up.svg");
background-size: contain;
border-radius: 8px;
}
@ -1632,7 +1590,6 @@ StTooltip StLabel {
border: 0px;
background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-down.svg");
background-size: contain;
border-radius: 8px;
}
@ -1942,7 +1899,6 @@ StTooltip StLabel {
background-gradient-end: white;
background-gradient-direction: vertical;
color: black;
selected-color: white;
border-radius: 5px;
border: 2px solid #555753;
}

View File

@ -1 +0,0 @@
SUBDIRS = reference

View File

@ -1 +0,0 @@
SUBDIRS = shell st

View File

@ -1,113 +0,0 @@
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=shell
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
DOC_SOURCE_DIR=$(top_srcdir)/src
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/*.h
CFILE_GLOB=$(top_srcdir)/src/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES= \
calendar-server \
gvc \
hotplug-sniffer \
st \
tray \
gactionmuxer.h \
gactionobservable.h \
gactionobserver.h \
shell-recorder-src.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
DISTCLEANFILES = $(DOC_MODULES).types
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC
TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/git.mk

View File

@ -1,73 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>Shell Reference Manual</title>
<releaseinfo>
for Shell @VERSION@.
<!--The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/shell/index.html">http://[SERVER]/shell/</ulink>.-->
</releaseinfo>
</bookinfo>
<chapter>
<title>Actors</title>
<xi:include href="xml/shell-generic-container.xml"/>
<xi:include href="xml/shell-slicer.xml"/>
<xi:include href="xml/shell-stack.xml"/>
</chapter>
<chapter>
<title>Application tracking</title>
<xi:include href="xml/shell-app.xml"/>
<xi:include href="xml/shell-app-usage.xml"/>
<xi:include href="xml/shell-window-tracker.xml"/>
</chapter>
<chapter>
<title>Search</title>
<xi:include href="xml/shell-app-system.xml"/>
<xi:include href="xml/shell-contact-system.xml"/>
<xi:include href="xml/shell-doc-system.xml"/>
</chapter>
<chapter>
<title>Tray Icons</title>
<xi:include href="xml/shell-embedded-window.xml"/>
<xi:include href="xml/shell-gtk-embed.xml"/>
<xi:include href="xml/shell-tray-icon.xml"/>
<xi:include href="xml/shell-tray-manager.xml"/>
</chapter>
<chapter>
<title>Recorder</title>
<xi:include href="xml/shell-recorder.xml"/>
<xi:include href="xml/shell-recorder-src.xml"/>
</chapter>
<chapter>
<title>Integration helpers and utilities</title>
<xi:include href="xml/shell-global.xml"/>
<xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-xfixes-cursor.xml"/>
<xi:include href="xml/shell-util.xml"/>
<xi:include href="xml/shell-mount-operation.xml"/>
<xi:include href="xml/shell-mobile-providers.xml"/>
<xi:include href="xml/shell-network-agent.xml"/>
<xi:include href="xml/shell-polkit-authentication-agent.xml"/>
<xi:include href="xml/shell-tp-client.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -1,104 +0,0 @@
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=st
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
DOC_SOURCE_DIR=$(top_srcdir)/src/st
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types --rebuild-sections
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/st/*.h
CFILE_GLOB=$(top_srcdir)/src/st/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES=st-private.h st-theme-node-private.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=
GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
DISTCLEANFILES = $(DOC_MODULE).types $(DOC_MODULE)-sections.txt
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC
TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/git.mk

View File

@ -1,68 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>St Reference Manual</title>
<releaseinfo>
for St @VERSION@.
<!--The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/st/index.html">http://[SERVER]/st/</ulink>.-->
</releaseinfo>
</bookinfo>
<part>
<title>API reference</title>
<chapter id="base">
<title>Abstract classes and Interfaces</title>
<xi:include href="xml/st-widget.xml"/>
<xi:include href="xml/st-widget-accessible.xml"/>
<xi:include href="xml/st-container.xml"/>
<xi:include href="xml/st-scrollable.xml"/>
</chapter>
<chapter id="widgets">
<title>Widgets</title>
<xi:include href="xml/st-button.xml"/>
<xi:include href="xml/st-drawing-area.xml"/>
<xi:include href="xml/st-entry.xml"/>
<xi:include href="xml/st-icon.xml"/>
<xi:include href="xml/st-label.xml"/>
<xi:include href="xml/st-tooltip.xml"/>
</chapter>
<chapter id="containers">
<title>Containers</title>
<xi:include href="xml/st-bin.xml"/>
<xi:include href="xml/st-box-layout.xml"/>
<xi:include href="xml/st-group.xml"/>
<xi:include href="xml/st-overflow-box.xml"/>
<xi:include href="xml/st-scroll-view.xml"/>
<xi:include href="xml/st-table.xml"/>
</chapter>
<chapter id="styling">
<title>Styling</title>
<xi:include href="xml/st-theme.xml"/>
<xi:include href="xml/st-theme-context.xml"/>
<xi:include href="xml/st-theme-node.xml"/>
<xi:include href="xml/st-theme-node-transition.xml"/>
<xi:include href="xml/st-texture-cache.xml"/>
</chapter>
</part>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -13,7 +13,6 @@ nobase_dist_js_DATA = \
misc/format.js \
misc/gnomeSession.js \
misc/history.js \
misc/jsParse.js \
misc/modemManager.js \
misc/params.js \
misc/screenSaver.js \
@ -72,7 +71,6 @@ nobase_dist_js_DATA = \
ui/tweener.js \
ui/userMenu.js \
ui/viewSelector.js \
ui/wanda.js \
ui/windowAttentionHandler.js \
ui/windowManager.js \
ui/workspace.js \

View File

@ -21,9 +21,11 @@
const Lang = imports.lang;
const Signals = imports.signals;
const Task = new Lang.Class({
Name: 'Task',
function Task() {
this._init.apply(this, arguments);
}
Task.prototype = {
_init: function(scope, handler) {
if (scope)
this.scope = scope;
@ -39,17 +41,22 @@ const Task = new Lang.Class({
return null;
},
});
};
Signals.addSignalMethods(Task.prototype);
const Hold = new Lang.Class({
Name: 'Hold',
Extends: Task,
function Hold() {
this._init.apply(this, arguments);
}
Hold.prototype = {
__proto__: Task.prototype,
_init: function() {
this.parent(this, function () {
return this;
});
Task.prototype._init.call(this,
this,
function () {
return this;
});
this._acquisitions = 1;
},
@ -81,15 +88,18 @@ const Hold = new Lang.Class({
isAcquired: function() {
return this._acquisitions > 0;
}
});
}
Signals.addSignalMethods(Hold.prototype);
const Batch = new Lang.Class({
Name: 'Batch',
Extends: Task,
function Batch() {
this._init.apply(this, arguments);
}
Batch.prototype = {
__proto__: Task.prototype,
_init: function(scope, tasks) {
this.parent();
Task.prototype._init.call(this);
this.tasks = [];
@ -156,12 +166,20 @@ const Batch = new Lang.Class({
cancel: function() {
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
}
});
};
Signals.addSignalMethods(Batch.prototype);
const ConcurrentBatch = new Lang.Class({
Name: 'ConcurrentBatch',
Extends: Batch,
function ConcurrentBatch() {
this._init.apply(this, arguments);
}
ConcurrentBatch.prototype = {
__proto__: Batch.prototype,
_init: function(scope, tasks) {
Batch.prototype._init.call(this, scope, tasks);
},
process: function() {
let hold = this.runTask();
@ -175,12 +193,19 @@ const ConcurrentBatch = new Lang.Class({
// concurrently.
this.nextTask();
}
});
};
Signals.addSignalMethods(ConcurrentBatch.prototype);
const ConsecutiveBatch = new Lang.Class({
Name: 'ConsecutiveBatch',
Extends: Batch,
function ConsecutiveBatch() {
this._init.apply(this, arguments);
}
ConsecutiveBatch.prototype = {
__proto__: Batch.prototype,
_init: function(scope, tasks) {
Batch.prototype._init.call(this, scope, tasks);
},
process: function() {
let hold = this.runTask();
@ -199,5 +224,5 @@ const ConsecutiveBatch = new Lang.Class({
this.nextTask();
}
}
});
};
Signals.addSignalMethods(ConsecutiveBatch.prototype);

View File

@ -1,22 +1,32 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
<method name='CanRestart'>
<arg type='b' direction='out'/>
</method>
<method name='CanStop'>
<arg type='b' direction='out'/>
</method>
<method name='Restart' />
<method name='Stop' />
</interface>;
const ConsoleKitProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
const ConsoleKitManagerIface = {
name: 'org.freedesktop.ConsoleKit.Manager',
methods: [{ name: 'CanRestart',
inSignature: '',
outSignature: 'b' },
{ name: 'CanStop',
inSignature: '',
outSignature: 'b' },
{ name: 'Restart',
inSignature: '',
outSignature: '' },
{ name: 'Stop',
inSignature: '',
outSignature: '' }]
};
function ConsoleKitManager() {
return new ConsoleKitProxy(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
this._init();
};
ConsoleKitManager.prototype = {
_init: function() {
DBus.system.proxifyObject(this,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
}
};
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);

View File

@ -1,20 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
<method name='GetDefaultDevice'>
<arg type='o' direction='out' />
</method>
</interface>;
const FprintManagerProxy = Gio.DBusProxy.makeProxyWrapper(FprintManagerIface);
const FprintManagerIface = {
name: 'net.reactivated.Fprint.Manager',
methods: [{ name: 'GetDefaultDevice',
inSignature: '',
outSignature: 'o' }]
};
function FprintManager() {
return new FprintManagerProxy(Gio.DBus.system,
'net.reactivated.Fprint',
'/net/reactivated/Fprint/Manager');
this._init();
};
FprintManager.prototype = {
_init: function() {
DBus.system.proxifyObject(this,
'net.reactivated.Fprint',
'/net/reactivated/Fprint/Manager');
}
};
DBus.proxifyPrototype(FprintManager.prototype, FprintManagerIface);

View File

@ -33,6 +33,7 @@ const St = imports.gi.St;
const GdmGreeter = imports.gi.GdmGreeter;
const Batch = imports.gdm.batch;
const DBus = imports.dbus;
const Fprint = imports.gdm.fingerprint;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
@ -140,9 +141,11 @@ function _smoothlyResizeActor(actor, width, height) {
return hold;
}
const UserListItem = new Lang.Class({
Name: 'UserListItem',
function UserListItem(user, reason) {
this._init(user, reason);
}
UserListItem.prototype = {
_init: function(user) {
this.user = user;
this._userChangedId = this.user.connect('changed',
@ -271,12 +274,15 @@ const UserListItem = new Lang.Class({
});
return hold;
}
});
};
Signals.addSignalMethods(UserListItem.prototype);
const UserList = new Lang.Class({
Name: 'UserList',
function UserList() {
this._init.apply(this, arguments);
}
UserList.prototype = {
_init: function() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor.set_policy(Gtk.PolicyType.NEVER,
@ -532,12 +538,14 @@ const UserList = new Lang.Class({
item.actor.destroy();
delete this._items[userName];
}
});
};
Signals.addSignalMethods(UserList.prototype);
const SessionListItem = new Lang.Class({
Name: 'SessionListItem',
function SessionListItem(id, name) {
this._init(id, name);
}
SessionListItem.prototype = {
_init: function(id, name) {
this.id = id;
@ -592,12 +600,14 @@ const SessionListItem = new Lang.Class({
_onClicked: function() {
this.emit('activate');
}
});
};
Signals.addSignalMethods(SessionListItem.prototype);
const SessionList = new Lang.Class({
Name: 'SessionList',
function SessionList() {
this._init();
}
SessionList.prototype = {
_init: function() {
this.actor = new St.Bin();
@ -728,15 +738,24 @@ const SessionList = new Lang.Class({
}));
}
}
});
};
Signals.addSignalMethods(SessionList.prototype);
const LoginDialog = new Lang.Class({
Name: 'LoginDialog',
Extends: ModalDialog.ModalDialog,
function LoginDialog() {
if (_loginDialog == null) {
this._init();
_loginDialog = this;
}
return _loginDialog;
}
LoginDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function() {
this.parent({ shellReactive: true, styleClass: 'login-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { shellReactive: true,
styleClass: 'login-dialog' });
this.connect('destroy',
Lang.bind(this, this._onDestroy));
this.connect('opened',
@ -825,7 +844,7 @@ const LoginDialog = new Lang.Class({
x_fill: true,
y_fill: false,
x_align: St.Align.START });
// Translators: this message is shown below the password entry field
// translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
style_class: 'login-dialog-prompt-fingerprint-message' });
@ -845,9 +864,6 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START });
this._promptBox.hide();
// translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for
// manually entering the username.
let notListedLabel = new St.Label({ text: _("Not listed?"),
style_class: 'login-dialog-not-listed-label' });
this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
@ -889,7 +905,7 @@ const LoginDialog = new Lang.Class({
if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
return;
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, Lang.bind(this,
this._fprintManager.GetDefaultDeviceRemote(DBus.CALL_FLAG_START, Lang.bind(this,
function(device, error) {
if (!error && device)
this._haveFingerprintReader = true;
@ -1380,8 +1396,8 @@ const LoginDialog = new Lang.Class({
},
close: function() {
this.parent();
ModalDialog.ModalDialog.prototype.close.call(this);
Main.ctrlAltTabManager.removeGroup(this._group);
}
});
};

View File

@ -25,12 +25,15 @@ const ConsoleKit = imports.gdm.consoleKit;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const PowerMenuButton = new Lang.Class({
Name: 'PowerMenuButton',
Extends: PanelMenu.SystemStatusButton,
function PowerMenuButton() {
this._init();
}
PowerMenuButton.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
this.parent('system-shutdown', null);
PanelMenu.SystemStatusButton.prototype._init.call(this, 'system-shutdown', null);
this._consoleKitManager = new ConsoleKit.ConsoleKitManager();
this._upClient = new UPowerGlib.Client();
@ -140,4 +143,4 @@ const PowerMenuButton = new Lang.Class({
if (this._haveShutdown)
this._consoleKitManager.StopRemote();
}
});
};

View File

@ -8,9 +8,11 @@ const Search = imports.ui.search;
const THUMBNAIL_ICON_MARGIN = 2;
const DocInfo = new Lang.Class({
Name: 'DocInfo',
function DocInfo(recentInfo) {
this._init(recentInfo);
}
DocInfo.prototype = {
_init : function(recentInfo) {
this.recentInfo = recentInfo;
// We actually used get_modified() instead of get_visited()
@ -47,7 +49,7 @@ const DocInfo = new Lang.Class({
}
return mtype;
}
});
};
var docManagerInstance = null;
@ -60,9 +62,11 @@ function getDocManager() {
/**
* DocManager wraps the DocSystem, primarily to expose DocInfo objects.
*/
const DocManager = new Lang.Class({
Name: 'DocManager',
function DocManager() {
this._init();
}
DocManager.prototype = {
_init: function() {
this._docSystem = Shell.DocSystem.get_default();
this._infosByTimestamp = [];
@ -131,6 +135,6 @@ const DocManager = new Lang.Class({
return this._infosByUri[url];
})), terms);
}
});
};
Signals.addSignalMethods(DocManager.prototype);

View File

@ -1,18 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const Lang = imports.lang;
const Signals = imports.signals;
const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
<method name="SetStatus">
<arg type="u" direction="in"/>
</method>
<property name="status" type="u" access="readwrite"/>
<signal name="StatusChanged">
<arg type="u" direction="out"/>
</signal>
</interface>;
const PresenceIface = {
name: 'org.gnome.SessionManager.Presence',
methods: [{ name: 'SetStatus',
inSignature: 'u',
outSignature: '' }],
properties: [{ name: 'status',
signature: 'u',
access: 'readwrite' }],
signals: [{ name: 'StatusChanged',
inSignature: 'u' }]
};
const PresenceStatus = {
AVAILABLE: 0,
@ -21,41 +23,104 @@ const PresenceStatus = {
IDLE: 3
};
var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
function Presence(initCallback, cancellable) {
return new PresenceProxy(Gio.DBus.session, 'org.gnome.SessionManager',
'/org/gnome/SessionManager/Presence', initCallback, cancellable);
function Presence() {
this._init();
}
Presence.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
},
getStatus: function(callback) {
this.GetRemote('status', Lang.bind(this,
function(status, ex) {
if (!ex)
callback(this, status);
}));
},
setStatus: function(status) {
this.SetStatusRemote(status);
}
};
DBus.proxifyPrototype(Presence.prototype, PresenceIface);
// Note inhibitors are immutable objects, so they don't
// change at runtime (changes always come in the form
// of new inhibitors)
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
<property name="app_id" type="s" access="read" />
<property name="client_id" type="s" access="read" />
<property name="reason" type="s" access="read" />
<property name="flags" type="u" access="read" />
<property name="toplevel_xid" type="u" access="read" />
<property name="cookie" type="u" access="read" />
</interface>;
const InhibitorIface = {
name: 'org.gnome.SessionManager.Inhibitor',
properties: [{ name: 'app_id',
signature: 's',
access: 'readonly' },
{ name: 'client_id',
signature: 's',
access: 'readonly' },
{ name: 'reason',
signature: 's',
access: 'readonly' },
{ name: 'flags',
signature: 'u',
access: 'readonly' },
{ name: 'toplevel_xid',
signature: 'u',
access: 'readonly' },
{ name: 'cookie',
signature: 'u',
access: 'readonly' }],
};
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
function Inhibitor(objectPath, initCallback, cancellable) {
return new InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
function Inhibitor(objectPath) {
this._init(objectPath);
}
Inhibitor.prototype = {
_init: function(objectPath) {
DBus.session.proxifyObject(this,
'org.gnome.SessionManager',
objectPath);
this.isLoaded = false;
this._loadingPropertiesCount = InhibitorIface.properties.length;
for (let i = 0; i < InhibitorIface.properties.length; i++) {
let propertyName = InhibitorIface.properties[i].name;
this.GetRemote(propertyName, Lang.bind(this,
function(value, exception) {
if (exception)
return;
this[propertyName] = value;
this._loadingPropertiesCount--;
if (this._loadingPropertiesCount == 0) {
this.isLoaded = true;
this.emit('is-loaded');
}
}));
}
},
};
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
Signals.addSignalMethods(Inhibitor.prototype);
// Not the full interface, only the methods we use
const SessionManagerIface = <interface name="org.gnome.SessionManager">
<method name="Logout">
<arg type="u" direction="in" />
</method>
<method name="Shutdown" />
<method name="CanShutdown">
<arg type="b" direction="out" />
</method>
</interface>;
const SessionManagerIface = {
name: 'org.gnome.SessionManager',
methods: [
{ name: 'Logout', inSignature: 'u', outSignature: '' },
{ name: 'Shutdown', inSignature: '', outSignature: '' },
{ name: 'CanShutdown', inSignature: '', outSignature: 'b' }
]
};
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
function SessionManager(initCallback, cancellable) {
return new SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
function SessionManager() {
this._init();
}
SessionManager.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
}
};
DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);

View File

@ -7,9 +7,11 @@ const Params = imports.misc.params;
const DEFAULT_LIMIT = 512;
const HistoryManager = new Lang.Class({
Name: 'HistoryManager',
function HistoryManager(params) {
this._init(params);
}
HistoryManager.prototype = {
_init: function(params) {
params = Params.parse(params, { gsettingsKey: null,
limit: DEFAULT_LIMIT,
@ -109,5 +111,5 @@ const HistoryManager = new Lang.Class({
if (this._key)
global.settings.set_strv(this._key, this._history);
}
});
};
Signals.addSignalMethods(HistoryManager.prototype);

View File

@ -1,246 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// Returns a list of potential completions for text. Completions either
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
// commandHeader is prefixed on any expression before it is eval'ed. It will most likely
// consist of global constants that might not carry over from the calling environment.
//
// This function is likely the one you want to call from external modules
function getCompletions(text, commandHeader, globalCompletionList) {
let methods = [];
let expr, base;
let attrHead = '';
if (globalCompletionList == null) {
globalCompletionList = [];
}
let offset = getExpressionOffset(text, text.length - 1);
if (offset >= 0) {
text = text.slice(offset);
// Look for expressions like "Main.panel.foo" and match Main.panel and foo
let matches = text.match(/(.*)\.(.*)/);
if (matches) {
[expr, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter(function(attr) {
return attr.slice(0, attrHead.length) == attrHead;
});
}
// Look for the empty expression or partially entered words
// not proceeded by a dot and match them against global constants
matches = text.match(/^(\w*)$/);
if (text == '' || matches) {
[expr, attrHead] = matches;
methods = globalCompletionList.filter(function(attr) {
return attr.slice(0, attrHead.length) == attrHead;
});
}
}
return [methods, attrHead];
}
//
// A few functions for parsing strings of javascript code.
//
// Identify characters that delimit an expression. That is,
// if we encounter anything that isn't a letter, '.', ')', or ']',
// we should stop parsing.
function isStopChar(c) {
return !c.match(/[\w\.\)\]]/);
}
// Given the ending position of a quoted string, find where it starts
function findMatchingQuote(expr, offset) {
let quoteChar = expr.charAt(offset);
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
return i;
}
}
return -1;
}
// Given the ending position of a regex, find where it starts
function findMatchingSlash(expr, offset) {
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
return i;
}
}
return -1;
}
// If expr.charAt(offset) is ')' or ']',
// return the position of the corresponding '(' or '[' bracket.
// This function does not check for syntactic correctness. e.g.,
// findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset);
let openBrace = ({')': '(', ']': '['})[closeBrace];
function findTheBrace(expr, offset) {
if (offset < 0) {
return -1;
}
if (expr.charAt(offset) == openBrace) {
return offset;
}
if (expr.charAt(offset).match(/['"]/)) {
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
}
if (expr.charAt(offset) == '/') {
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
}
if (expr.charAt(offset) == closeBrace) {
return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
}
return findTheBrace(expr, offset - 1);
}
return findTheBrace(expr, offset - 1);
}
// Walk expr backwards from offset looking for the beginning of an
// expression suitable for passing to eval.
// There is no guarantee of correct javascript syntax between the return
// value and offset. This function is meant to take a string like
// "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
function getExpressionOffset(expr, offset) {
while (offset >= 0) {
let currChar = expr.charAt(offset);
if (isStopChar(currChar)){
return offset + 1;
}
if (currChar.match(/[\)\]]/)) {
offset = findMatchingBrace(expr, offset);
}
--offset;
}
return offset + 1;
}
// Things with non-word characters or that start with a number
// are not accessible via .foo notation and so aren't returned
function isValidPropertyName(w) {
return !(w.match(/\W/) || w.match(/^\d/));
}
// To get all properties (enumerable and not), we need to walk
// the prototype chain ourselves
function getAllProps(obj) {
if (obj === null || obj === undefined) {
return [];
}
return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
}
// Given a string _expr_, returns all methods
// that can be accessed via '.' notation.
// e.g., expr="({ foo: null, bar: null, 4: null })" will
// return ["foo", "bar", ...] but the list will not include "4",
// since methods accessed with '.' notation must star with a letter or _.
function getPropertyNamesFromExpression(expr, commandHeader) {
if (commandHeader == null) {
commandHeader = '';
}
let obj = {};
if (!isUnsafeExpression(expr)) {
try {
obj = eval(commandHeader + expr);
} catch (e) {
return [];
}
} else {
return [];
}
let propsUnique = {};
if (typeof obj === 'object'){
let allProps = getAllProps(obj);
// Get only things we are allowed to complete following a '.'
allProps = allProps.filter( isValidPropertyName );
// Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties
allProps.map(function(p){ propsUnique[p] = null; });
}
return Object.keys(propsUnique).sort();
}
// Given a list of words, returns the longest prefix they all have in common
function getCommonPrefix(words) {
let word = words[0];
for (let i = 0; i < word.length; i++) {
for (let w = 1; w < words.length; w++) {
if (words[w].charAt(i) != word.charAt(i))
return word.slice(0, i);
}
}
return word;
}
// Returns true if there is reason to think that eval(str)
// will modify the global scope
function isUnsafeExpression(str) {
// Remove any blocks that are quoted or are in a regex
function removeLiterals(str) {
if (str.length == 0) {
return '';
}
let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') {
return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') {
return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
}
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
}
// Check for any sort of assignment
// The strategy used is dumb: remove any quotes
// or regexs and comparison operators and see if there is an '=' character.
// If there is, it might be an unsafe assignment.
let prunedStr = removeLiterals(str);
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/=/)) {
return true;
} else if (prunedStr.match(/;/)) {
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well
return true;
}
return false;
}
// Returns a list of global keywords derived from str
function getDeclaredConstants(str) {
let ret = [];
str.split(';').forEach(function(s) {
let base, keyword;
let match = s.match(/const\s+(\w+)\s*=/);
if (match) {
[base, keyword] = match;
ret.push(keyword);
}
});
return ret;
}

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
@ -8,43 +8,33 @@ const Signals = imports.signals;
// The following are not the complete interfaces, just the methods we need
// (or may need in the future)
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
<method name="GetRegistrationInfo">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="s" direction="out" />
</method>
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<property name="AccessTechnology" type="u" access="read" />
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
<signal name="RegistrationInfo">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="s" direction="out" />
</signal>
</interface>;
const ModemGsmNetworkInterface = {
name: 'org.freedesktop.ModemManager.Modem.Gsm.Network',
methods: [
{ name: 'GetRegistrationInfo', inSignature: '', outSignature: 'uss' },
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' }
],
properties: [
{ name: 'AccessTechnology', signature: 'u', access: 'read' }
],
signals: [
{ name: 'SignalQuality', inSignature: 'u' },
{ name: 'RegistrationInfo', inSignature: 'uss' }
]
};
const ModemGsmNetworkProxy = DBus.makeProxyClass(ModemGsmNetworkInterface);
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<method name="GetServingSystem">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="u" direction="out" />
</method>
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
</interface>;
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
const ModemCdmaInterface = {
name: 'org.freedesktop.ModemManager.Modem.Cdma',
methods: [
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' },
{ name: 'GetServingSystem', inSignature: '', outSignature: 'usu' }
],
signals: [
{ name: 'SignalQuality', inSignature: 'u' }
]
};
const ModemCdmaProxy = DBus.makeProxyClass(ModemCdmaInterface);
let _providersTable;
function _getProvidersTable() {
@ -54,21 +44,23 @@ function _getProvidersTable() {
return _providersTable = providers;
}
const ModemGsm = new Lang.Class({
Name: 'ModemGsm',
function ModemGsm() {
this._init.apply(this, arguments);
}
ModemGsm.prototype = {
_init: function(path) {
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
// Code is duplicated because the function have different signatures
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
this.signal_quality = quality;
this.emit('notify::signal-quality');
}));
this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
this.operator_name = this._findOperatorName(name, code);
this.emit('notify::operator-name');
}));
@ -154,19 +146,21 @@ const ModemGsm = new Lang.Class({
return name3 || name2 || null;
}
});
}
Signals.addSignalMethods(ModemGsm.prototype);
const ModemCdma = new Lang.Class({
Name: 'ModemCdma',
function ModemCdma() {
this._init.apply(this, arguments);
}
ModemCdma.prototype = {
_init: function(path) {
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
this.signal_quality = params[0];
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
this.signal_quality = quality;
this.emit('notify::signal-quality');
// receiving this signal means the device got activated
@ -227,5 +221,5 @@ const ModemCdma = new Lang.Class({
return null;
}
});
};
Signals.addSignalMethods(ModemCdma.prototype);

View File

@ -1,48 +1,53 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const Lang = imports.lang;
const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
<method name="GetActive">
<arg type="b" direction="out" />
</method>
<method name="Lock" />
<method name="SetActive">
<arg type="b" direction="in" />
</method>
<signal name="ActiveChanged">
<arg type="b" direction="out" />
</signal>
</interface>;
const ScreenSaverInfo = Gio.DBusInterfaceInfo.new_for_xml(ScreenSaverIface);
const ScreenSaverIface = {
name: 'org.gnome.ScreenSaver',
methods: [{ name: 'GetActive',
inSignature: '',
outSignature: 'b' },
{ name: 'Lock',
inSignature: '' },
{ name: 'SetActive',
inSignature: 'b' }],
signals: [{ name: 'ActiveChanged',
inSignature: 'b' }]
};
function ScreenSaverProxy() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
g_interface_name: ScreenSaverInfo.name,
g_interface_info: ScreenSaverInfo,
g_name: 'org.gnome.ScreenSaver',
g_object_path: '/org/gnome/ScreenSaver',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self.init(null);
self.screenSaverActive = false;
self.connectSignal('ActiveChanged', function(proxy, senderName, [isActive]) {
self.screenSaverActive = isActive;
});
self.connect('notify::g-name-owner', function() {
if (self.g_name_owner) {
self.GetActiveRemote(function(result, excp) {
if (result) {
let [isActive] = result;
self.screenSaverActive = isActive;
}
});
} else
self.screenSaverActive = false;
});
return self;
this._init();
}
ScreenSaverProxy.prototype = {
_init: function() {
DBus.session.proxifyObject(this,
'org.gnome.ScreenSaver',
'/org/gnome/ScreenSaver');
DBus.session.watch_name('org.gnome.ScreenSaver',
false, // do not launch a name-owner if none exists
Lang.bind(this, this._onSSAppeared),
Lang.bind(this, this._onSSVanished));
this.screenSaverActive = false;
this.connect('ActiveChanged',
Lang.bind(this, this._onActiveChanged));
},
_onSSAppeared: function(owner) {
this.GetActiveRemote(Lang.bind(this, function(isActive) {
this.screenSaverActive = isActive;
}))
},
_onSSVanished: function(oldOwner) {
this.screenSaverActive = false;
},
_onActiveChanged: function(object, isActive) {
this.screenSaverActive = isActive;
}
};
DBus.proxifyPrototype(ScreenSaverProxy.prototype, ScreenSaverIface);

View File

@ -232,53 +232,3 @@ function fixupPCIDescription(desc) {
return out.join(' ');
}
// lowerBound:
// @array: an array or array-like object, already sorted
// according to @cmp
// @val: the value to add
// @cmp: a comparator (or undefined to compare as numbers)
//
// Returns the position of the first element that is not
// lower than @val, according to @cmp.
// That is, returns the first position at which it
// is possible to insert @val without violating the
// order.
// This is quite like an ordinary binary search, except
// that it doesn't stop at first element comparing equal.
function lowerBound(array, val, cmp) {
let min, max, mid, v;
cmp = cmp || function(a, b) { return a - b; };
if (array.length == 0)
return 0;
min = 0; max = array.length;
while (min < (max - 1)) {
mid = Math.floor((min + max) / 2);
v = cmp(array[mid], val);
if (v < 0)
min = mid + 1;
else
max = mid;
}
return (min == max || cmp(array[min], val) < 0) ? max : min;
}
// insertSorted:
// @array: an array sorted according to @cmp
// @val: a value to insert
// @cmp: the sorting function
//
// Inserts @val into @array, preserving the
// sorting invariants.
// Returns the position at which it was inserted
function insertSorted(array, val, cmp) {
let pos = lowerBound(array, val, cmp);
array.splice(pos, 0, val);
return pos;
}

View File

@ -43,9 +43,11 @@ function primaryModifier(mask) {
return primary;
}
const AltTabPopup = new Lang.Class({
Name: 'AltTabPopup',
function AltTabPopup() {
this._init();
}
AltTabPopup.prototype = {
_init : function() {
this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
reactive: true,
@ -168,12 +170,8 @@ const AltTabPopup = new Lang.Class({
if (localApps.length == 0 && otherApps.length == 0)
return false;
if (!Main.pushModal(this.actor)) {
// Probably someone else has a pointer grab, try again with keyboard only
if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
return false;
}
}
if (!Main.pushModal(this.actor))
return false;
this._haveModal = true;
this._modifierMask = primaryModifier(mask);
@ -197,7 +195,7 @@ const AltTabPopup = new Lang.Class({
this.actor.get_allocation_box();
// Make the initial selection
if (binding == 'switch-group') {
if (binding == 'switch_group') {
if (backward) {
this._select(0, this._appIcons[0].cachedWindows.length - 1);
} else {
@ -206,9 +204,9 @@ const AltTabPopup = new Lang.Class({
else
this._select(0, 0);
}
} else if (binding == 'switch-group-backward') {
} else if (binding == 'switch_group_backward') {
this._select(0, this._appIcons[0].cachedWindows.length - 1);
} else if (binding == 'switch-windows-backward') {
} else if (binding == 'switch_windows_backward') {
this._select(this._appIcons.length - 1);
} else if (this._appIcons.length == 1) {
this._select(0);
@ -538,11 +536,13 @@ const AltTabPopup = new Lang.Class({
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
});
}
});
};
const SwitcherList = new Lang.Class({
Name: 'SwitcherList',
function SwitcherList(squareItems) {
this._init(squareItems);
}
SwitcherList.prototype = {
_init : function(squareItems) {
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -847,13 +847,15 @@ const SwitcherList = new Lang.Class({
// Clip the area for scrolling
this._clipBin.set_clip(0, -topPadding, (this.actor.allocation.x2 - this.actor.allocation.x1) - leftPadding - rightPadding, this.actor.height + bottomPadding);
}
});
};
Signals.addSignalMethods(SwitcherList.prototype);
const AppIcon = new Lang.Class({
Name: 'AppIcon',
function AppIcon(app) {
this._init(app);
}
AppIcon.prototype = {
_init: function(app) {
this.app = app;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
@ -871,14 +873,17 @@ const AppIcon = new Lang.Class({
this._iconBin.set_size(size, size);
this._iconBin.child = this.icon;
}
});
};
const AppSwitcher = new Lang.Class({
Name: 'AppSwitcher',
Extends: SwitcherList,
function AppSwitcher() {
this._init.apply(this, arguments);
}
AppSwitcher.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(localApps, otherApps, altTabPopup) {
this.parent(true);
SwitcherList.prototype._init.call(this, true);
// Construct the AppIcons, add to the popup
let activeWorkspace = global.screen.get_active_workspace();
@ -957,7 +962,7 @@ const AppSwitcher = new Lang.Class({
_allocate: function (actor, box, flags) {
// Allocate the main list items
this.parent(actor, box, flags);
SwitcherList.prototype._allocate.call(this, actor, box, flags);
let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
let arrowWidth = arrowHeight * 2;
@ -1012,7 +1017,7 @@ const AppSwitcher = new Lang.Class({
this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
}
this.parent(n, justOutline);
SwitcherList.prototype.highlight.call(this, n, justOutline);
this._curApp = n;
if (this._curApp != -1) {
@ -1036,14 +1041,17 @@ const AppSwitcher = new Lang.Class({
if (appIcon.cachedWindows.length == 1)
arrow.hide();
}
});
};
const ThumbnailList = new Lang.Class({
Name: 'ThumbnailList',
Extends: SwitcherList,
function ThumbnailList(windows) {
this._init(windows);
}
ThumbnailList.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(windows) {
this.parent(false);
SwitcherList.prototype._init.call(this);
let activeWorkspace = global.screen.get_active_workspace();
@ -1121,7 +1129,7 @@ const ThumbnailList = new Lang.Class({
// Make sure we only do this once
this._thumbnailBins = new Array();
}
});
};
function _drawArrow(area, side) {
let themeNode = area.get_theme_node();

View File

@ -26,9 +26,11 @@ const MAX_APPLICATION_WORK_MILLIS = 75;
const MENU_POPUP_TIMEOUT = 600;
const SCROLL_TIME = 0.1;
const AlphabeticalView = new Lang.Class({
Name: 'AlphabeticalView',
function AlphabeticalView() {
this._init();
}
AlphabeticalView.prototype = {
_init: function() {
this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
this._appSystem = Shell.AppSystem.get_default();
@ -128,11 +130,13 @@ const AlphabeticalView = new Lang.Class({
this._addApp(app);
}
}
});
};
const ViewByCategories = new Lang.Class({
Name: 'ViewByCategories',
function ViewByCategories() {
this._init();
}
ViewByCategories.prototype = {
_init: function() {
this._appSystem = Shell.AppSystem.get_default();
this.actor = new St.BoxLayout({ style_class: 'all-app' });
@ -277,14 +281,16 @@ const ViewByCategories = new Lang.Class({
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}
}
});
};
/* This class represents a display containing a collection of application items.
* The applications are sorted based on their name.
*/
const AllAppDisplay = new Lang.Class({
Name: 'AllAppDisplay',
function AllAppDisplay() {
this._init();
}
AllAppDisplay.prototype = {
_init: function() {
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
@ -300,15 +306,17 @@ const AllAppDisplay = new Lang.Class({
_redisplay: function() {
this._appView.refresh();
}
});
};
const AppSearchProvider = new Lang.Class({
Name: 'AppSearchProvider',
Extends: Search.SearchProvider,
function AppSearchProvider() {
this._init();
}
AppSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
this.parent(_("APPLICATIONS"));
Search.SearchProvider.prototype._init.call(this, _("APPLICATIONS"));
this._appSys = Shell.AppSystem.get_default();
},
@ -356,15 +364,17 @@ const AppSearchProvider = new Lang.Class({
let icon = new AppWellIcon(app);
return icon.actor;
}
});
};
const SettingsSearchProvider = new Lang.Class({
Name: 'SettingsSearchProvider',
Extends: Search.SearchProvider,
function SettingsSearchProvider() {
this._init();
}
SettingsSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
this.parent(_("SETTINGS"));
Search.SearchProvider.prototype._init.call(this, _("SETTINGS"));
this._appSys = Shell.AppSystem.get_default();
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
},
@ -402,28 +412,35 @@ const SettingsSearchProvider = new Lang.Class({
let icon = new AppWellIcon(app);
return icon.actor;
}
});
};
const AppIcon = new Lang.Class({
Name: 'AppIcon',
Extends: IconGrid.BaseIcon,
function AppIcon(app, params) {
this._init(app, params);
}
AppIcon.prototype = {
__proto__: IconGrid.BaseIcon.prototype,
_init : function(app, params) {
this.app = app;
let label = this.app.get_name();
this.parent(label, params);
IconGrid.BaseIcon.prototype._init.call(this,
label,
params);
},
createIcon: function(iconSize) {
return this.app.create_icon_texture(iconSize);
}
});
};
const AppWellIcon = new Lang.Class({
Name: 'AppWellIcon',
function AppWellIcon(app, iconParams, onActivateOverride) {
this._init(app, iconParams, onActivateOverride);
}
AppWellIcon.prototype = {
_init : function(app, iconParams, onActivateOverride) {
this.app = app;
this.actor = new St.Button({ style_class: 'app-well-app',
@ -470,7 +487,6 @@ const AppWellIcon = new Lang.Class({
Lang.bind(this,
this._onStateChanged));
this._onStateChanged();
this.isMenuUp = false;
},
_onDestroy: function() {
@ -552,8 +568,8 @@ const AppWellIcon = new Lang.Class({
this._menuManager.addMenu(this._menu);
}
this.isMenuUp = true;
this.actor.set_hover(true);
this.actor.show_tooltip();
this._menu.popup();
return false;
@ -569,7 +585,6 @@ const AppWellIcon = new Lang.Class({
_onMenuPoppedDown: function() {
this.actor.sync_hover();
this.isMenuUp = false;
},
_onActivate: function (event) {
@ -605,19 +620,22 @@ const AppWellIcon = new Lang.Class({
getDragActorSource: function() {
return this.icon.icon;
}
});
};
Signals.addSignalMethods(AppWellIcon.prototype);
const AppIconMenu = new Lang.Class({
Name: 'AppIconMenu',
Extends: PopupMenu.PopupMenu,
function AppIconMenu(source) {
this._init(source);
}
AppIconMenu.prototype = {
__proto__: PopupMenu.PopupMenu.prototype,
_init: function(source) {
let side = St.Side.LEFT;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
side = St.Side.RIGHT;
this.parent(source.actor, 0.5, side);
PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side);
// We want to keep the item hovered while the menu is up
this.blockSourceEvents = true;
@ -705,5 +723,5 @@ const AppIconMenu = new Lang.Class({
}
this.close();
}
});
};
Signals.addSignalMethods(AppIconMenu.prototype);

View File

@ -6,9 +6,11 @@ const Signals = imports.signals;
const Main = imports.ui.main;
const AppFavorites = new Lang.Class({
Name: 'AppFavorites',
function AppFavorites() {
this._init();
}
AppFavorites.prototype = {
FAVORITE_APPS_KEY: 'favorite-apps',
_init: function() {
@ -120,7 +122,7 @@ const AppFavorites = new Lang.Class({
this._addFavorite(appId, pos);
}));
}
});
};
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;

View File

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const DBus = imports.dbus;
const Mainloop = imports.mainloop;
const Gio = imports.gi.Gio;
const Params = imports.misc.params;
@ -15,58 +16,69 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
const ConsoleKitSessionIface = <interface name="org.freedesktop.ConsoleKit.Session">
<method name="IsActive">
<arg type="b" direction="out" />
</method>
<signal name="ActiveChanged">
<arg type="b" direction="out" />
</signal>
</interface>;
const ConsoleKitSessionIface = {
name: 'org.freedesktop.ConsoleKit.Session',
methods: [{ name: 'IsActive',
inSignature: '',
outSignature: 'b' }],
signals: [{ name: 'ActiveChanged',
inSignature: 'b' }]
};
const ConsoleKitSessionProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitSessionProxy = DBus.makeProxyClass(ConsoleKitSessionIface);
const ConsoleKitManagerIface = <interface name="org.freedesktop.ConsoleKit.Manager">
<method name="GetCurrentSession">
<arg type="o" direction="out" />
</method>
</interface>;
const ConsoleKitManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ConsoleKitManagerIface);
const ConsoleKitManagerIface = {
name: 'org.freedesktop.ConsoleKit.Manager',
methods: [{ name: 'GetCurrentSession',
inSignature: '',
outSignature: 'o' }]
};
function ConsoleKitManager() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
g_interface_name: ConsoleKitManagerInfo.name,
g_interface_info: ConsoleKitManagerInfo,
g_name: 'org.freedesktop.ConsoleKit',
g_object_path: '/org/freedesktop/ConsoleKit/Manager',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
this._init();
};
self.connect('notify::g-name-owner', function() {
if (self.g_name_owner) {
self.GetCurrentSessionRemote(function([session]) {
self._ckSession = new ConsoleKitSessionProxy(Gio.DBus.system, 'org.freedesktop.ConsoleKit', session);
ConsoleKitManager.prototype = {
_init: function() {
this.sessionActive = true;
self._ckSession.connectSignal('ActiveChanged', function(object, senderName, [isActive]) {
self.sessionActive = isActive;
});
self._ckSession.IsActiveRemote(function([isActive]) {
self.sessionActive = isActive;
});
});
} else {
self.sessionActive = true;
}
});
DBus.system.proxifyObject(this,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
self.init(null);
return self;
DBus.system.watch_name('org.freedesktop.ConsoleKit',
false, // do not launch a name-owner if none exists
Lang.bind(this, this._onManagerAppeared),
Lang.bind(this, this._onManagerVanished));
},
_onManagerAppeared: function(owner) {
this.GetCurrentSessionRemote(Lang.bind(this, this._onCurrentSession));
},
_onManagerVanished: function(oldOwner) {
this.sessionActive = true;
},
_onCurrentSession: function(session) {
this._ckSession = new ConsoleKitSessionProxy(DBus.system, 'org.freedesktop.ConsoleKit', session);
this._ckSession.connect
('ActiveChanged', Lang.bind(this, function(object, isActive) {
this.sessionActive = isActive;
}));
this._ckSession.IsActiveRemote(Lang.bind(this, function(isActive) {
this.sessionActive = isActive;
}));
}
};
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);
function AutomountManager() {
this._init();
}
const AutomountManager = new Lang.Class({
Name: 'AutomountManager',
AutomountManager.prototype = {
_init: function() {
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = [];
@ -74,8 +86,9 @@ const AutomountManager = new Lang.Class({
this.ckListener = new ConsoleKitManager();
this._ssProxy = new ScreenSaver.ScreenSaverProxy();
this._ssProxy.connectSignal('ActiveChanged',
Lang.bind(this, this._screenSaverActiveChanged));
this._ssProxy.connect('ActiveChanged',
Lang.bind(this,
this._screenSaverActiveChanged));
this._volumeMonitor = Gio.VolumeMonitor.get();
@ -98,7 +111,7 @@ const AutomountManager = new Lang.Class({
Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
},
_screenSaverActiveChanged: function(object, senderName, [isActive]) {
_screenSaverActiveChanged: function(object, isActive) {
if (!isActive) {
this._volumeQueue.forEach(Lang.bind(this, function(volume) {
this._checkAndMountVolume(volume);
@ -266,4 +279,4 @@ const AutomountManager = new Lang.Class({
return false;
});
}
});
}

View File

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
@ -61,23 +62,31 @@ function startAppForMount(app, mount) {
/******************************************/
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
<method name="SniffURI">
<arg type="s" direction="in" />
<arg type="as" direction="out" />
</method>
</interface>;
const HotplugSnifferIface = {
name: 'org.gnome.Shell.HotplugSniffer',
methods: [{ name: 'SniffURI',
inSignature: 's',
outSignature: 'as' }]
};
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() {
return new HotplugSnifferProxy(Gio.DBus.session,
const HotplugSniffer = function() {
this._init();
};
HotplugSniffer.prototype = {
_init: function() {
DBus.session.proxifyObject(this,
'org.gnome.Shell.HotplugSniffer',
'/org/gnome/Shell/HotplugSniffer');
},
};
DBus.proxifyPrototype(HotplugSniffer.prototype, HotplugSnifferIface);
function ContentTypeDiscoverer(callback) {
this._init(callback);
}
const ContentTypeDiscoverer = new Lang.Class({
Name: 'ContentTypeDiscoverer',
ContentTypeDiscoverer.prototype = {
_init: function(callback) {
this._callback = callback;
},
@ -105,8 +114,9 @@ const ContentTypeDiscoverer = new Lang.Class({
let root = mount.get_root();
let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote(root.get_uri(),
Lang.bind(this, function([contentTypes]) {
hotplugSniffer.SniffURIRemote
(root.get_uri(), DBus.CALL_FLAG_START,
Lang.bind(this, function(contentTypes) {
this._emitCallback(mount, contentTypes);
}));
}
@ -134,11 +144,13 @@ const ContentTypeDiscoverer = new Lang.Class({
this._callback(mount, apps, contentTypes);
}
});
}
const AutorunManager = new Lang.Class({
Name: 'AutorunManager',
function AutorunManager() {
this._init();
}
AutorunManager.prototype = {
_init: function() {
this._volumeMonitor = Gio.VolumeMonitor.get();
@ -255,14 +267,17 @@ const AutorunManager = new Lang.Class({
+ ': ' + e.toString());
}
},
});
}
const AutorunResidentSource = new Lang.Class({
Name: 'AutorunResidentSource',
Extends: MessageTray.Source,
function AutorunResidentSource() {
this._init();
}
AutorunResidentSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function() {
this.parent(_("Removable Devices"));
MessageTray.Source.prototype._init.call(this, _("Removable Devices"));
this._mounts = [];
@ -317,14 +332,19 @@ const AutorunResidentSource = new Lang.Class({
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
});
}
const AutorunResidentNotification = new Lang.Class({
Name: 'AutorunResidentNotification',
Extends: MessageTray.Notification,
function AutorunResidentNotification(source) {
this._init(source);
}
AutorunResidentNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source) {
this.parent(source, source.title, null, { customContent: true });
MessageTray.Notification.prototype._init.call(this, source,
source.title, null,
{ customContent: true });
// set the notification as resident
this.setResident(true);
@ -398,11 +418,13 @@ const AutorunResidentNotification = new Lang.Class({
return item;
},
});
}
const AutorunTransientDispatcher = new Lang.Class({
Name: 'AutorunTransientDispatcher',
function AutorunTransientDispatcher() {
this._init();
}
AutorunTransientDispatcher.prototype = {
_init: function() {
this._sources = [];
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
@ -493,14 +515,17 @@ const AutorunTransientDispatcher = new Lang.Class({
// destroy the notification source
source.destroy();
}
});
}
const AutorunTransientSource = new Lang.Class({
Name: 'AutorunTransientSource',
Extends: MessageTray.Source,
function AutorunTransientSource(mount, apps) {
this._init(mount, apps);
}
AutorunTransientSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(mount, apps) {
this.parent(mount.get_name());
MessageTray.Source.prototype._init.call(this, mount.get_name());
this.mount = mount;
this.apps = apps;
@ -517,14 +542,19 @@ const AutorunTransientSource = new Lang.Class({
return new St.Icon({ gicon: this.mount.get_icon(),
icon_size: this.ICON_SIZE });
}
});
}
const AutorunTransientNotification = new Lang.Class({
Name: 'AutorunTransientNotification',
Extends: MessageTray.Notification,
function AutorunTransientNotification(source) {
this._init(source);
}
AutorunTransientNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source) {
this.parent(source, source.title, null, { customContent: true });
MessageTray.Notification.prototype._init.call(this, source,
source.title, null,
{ customContent: true });
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
vertical: true });
@ -557,7 +587,7 @@ const AutorunTransientNotification = new Lang.Class({
let label = new St.Bin({ y_align: St.Align.MIDDLE,
child: new St.Label
({ text: _("Open with %s").format(app.get_name()) })
({ text: _("Open with %s").format(app.get_display_name()) })
});
box.add(label);
@ -599,5 +629,5 @@ const AutorunTransientNotification = new Lang.Class({
return button;
}
});
}

View File

@ -21,9 +21,11 @@ const POPUP_ANIMATION_TIME = 0.15;
* placed. The arrow position may be controlled via setArrowOrigin().
*
*/
const BoxPointer = new Lang.Class({
Name: 'BoxPointer',
function BoxPointer(side, binProperties) {
this._init(side, binProperties);
}
BoxPointer.prototype = {
_init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide;
this._arrowOrigin = 0;
@ -450,4 +452,4 @@ const BoxPointer = new Lang.Class({
get opacity() {
return this.actor.opacity;
}
});
};

View File

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
@ -155,24 +156,28 @@ function _getEventDayAbbreviation(dayNumber) {
// Abstraction for an appointment/event in a calendar
const CalendarEvent = new Lang.Class({
Name: 'CalendarEvent',
function CalendarEvent(date, end, summary, allDay) {
this._init(date, end, summary, allDay);
}
CalendarEvent.prototype = {
_init: function(date, end, summary, allDay) {
this.date = date;
this.end = end;
this.summary = summary;
this.allDay = allDay;
}
});
};
// Interface for appointments/events - e.g. the contents of a calendar
//
// First, an implementation with no events
const EmptyEventSource = new Lang.Class({
Name: 'EmptyEventSource',
function EmptyEventSource() {
this._init();
}
EmptyEventSource.prototype = {
_init: function() {
},
@ -187,32 +192,33 @@ const EmptyEventSource = new Lang.Class({
hasEvents: function(day) {
return false;
}
});
};
Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<signal name="Changed" />
</interface>;
const CalendarServerIface = {
name: 'org.gnome.Shell.CalendarServer',
methods: [{ name: 'GetEvents',
inSignature: 'xxb',
outSignature: 'a(sssbxxa{sv})' }],
signals: [{ name: 'Changed',
inSignature: '' }]
};
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
const CalendarServer = function () {
this._init();
};
function CalendarServer() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
g_interface_name: CalendarServerInfo.name,
g_interface_info: CalendarServerInfo,
g_name: 'org.gnome.Shell.CalendarServer',
g_object_path: '/org/gnome/Shell/CalendarServer',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
CalendarServer.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.Shell.CalendarServer', '/org/gnome/Shell/CalendarServer');
}
};
self.init(null);
return self;
DBus.proxifyPrototype(CalendarServer.prototype, CalendarServerIface);
// an implementation that reads data from a session bus service
function DBusEventSource(owner) {
this._init(owner);
}
function _datesEqual(a, b) {
@ -233,22 +239,18 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
return true;
}
// an implementation that reads data from a session bus service
const DBusEventSource = new Lang.Class({
Name: 'DBusEventSource',
_init: function() {
DBusEventSource.prototype = {
_init: function(owner) {
this._resetCache();
this._dbusProxy = new CalendarServer();
this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
this._dbusProxy = new CalendarServer(owner);
this._dbusProxy.connect('Changed', Lang.bind(this, this._onChanged));
this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
if (this._dbusProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
}));
DBus.session.watch_name('org.gnome.Shell.CalendarServer',
false, // do not launch a name-owner if none exists
Lang.bind(this, this._onNameAppeared),
Lang.bind(this, this._onNameVanished));
},
_resetCache: function() {
@ -271,7 +273,7 @@ const DBusEventSource = new Lang.Class({
this._loadEvents(false);
},
_onEventsReceived: function([appointments]) {
_onEventsReceived: function(appointments) {
let newEvents = [];
if (appointments != null) {
for (let n = 0; n < appointments.length; n++) {
@ -294,9 +296,9 @@ const DBusEventSource = new Lang.Class({
_loadEvents: function(forceReload) {
if (this._curRequestBegin && this._curRequestEnd){
let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
let callFlags = 0;
if (forceReload)
callFlags = Gio.DBusCallFlags.NONE;
callFlags |= DBus.CALL_FLAG_START;
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
@ -337,15 +339,17 @@ const DBusEventSource = new Lang.Class({
return true;
}
});
};
Signals.addSignalMethods(DBusEventSource.prototype);
// Calendar:
// @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
const Calendar = new Lang.Class({
Name: 'Calendar',
function Calendar(eventSource) {
this._init(eventSource);
}
Calendar.prototype = {
_init: function(eventSource) {
if (eventSource) {
this._eventSource = eventSource;
@ -611,13 +615,15 @@ const Calendar = new Lang.Class({
if (this._eventSource)
this._eventSource.requestRange(beginDate, iter, forceReload);
}
});
};
Signals.addSignalMethods(Calendar.prototype);
const EventsList = new Lang.Class({
Name: 'EventsList',
function EventsList(eventSource) {
this._init(eventSource);
}
EventsList.prototype = {
_init: function(eventSource) {
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
this._date = new Date();
@ -748,4 +754,4 @@ const EventsList = new Lang.Class({
this._showOtherDay(this._date);
}
}
});
};

View File

@ -20,9 +20,11 @@ function launchContact(id) {
/* This class represents a shown contact search result in the overview */
const Contact = new Lang.Class({
Name: 'Contact',
function Contact(id) {
this._init(id);
}
Contact.prototype = {
_init: function(id) {
this._contactSys = Shell.ContactSystem.get_default();
this.individual = this._contactSys.get_individual(id);
@ -129,16 +131,19 @@ const Contact = new Lang.Class({
return tc.load_icon_name(null, 'avatar-default', St.IconType.FULLCOLOR, size);
}
},
});
};
/* Searches for and returns contacts */
const ContactSearchProvider = new Lang.Class({
Name: 'ContactSearchProvider',
Extends: Search.SearchProvider,
function ContactSearchProvider() {
this._init();
}
ContactSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
this.parent(_("CONTACTS"));
Search.SearchProvider.prototype._init.call(this, _("CONTACTS"));
this._contactSys = Shell.ContactSystem.get_default();
},
@ -177,4 +182,4 @@ const ContactSearchProvider = new Lang.Class({
activateResult: function(id, params) {
launchContact(id);
}
});
};

View File

@ -22,9 +22,11 @@ const SortGroup = {
BOTTOM: 2
};
const CtrlAltTabManager = new Lang.Class({
Name: 'CtrlAltTabManager',
function CtrlAltTabManager() {
this._init();
}
CtrlAltTabManager.prototype = {
_init: function() {
this._items = [];
this._focusManager = St.FocusManager.get_for_stage(global.stage);
@ -132,15 +134,17 @@ const CtrlAltTabManager = new Lang.Class({
}));
}
}
});
};
function mod(a, b) {
return (a + b) % b;
}
const CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup',
function CtrlAltTabPopup() {
this._init();
}
CtrlAltTabPopup.prototype = {
_init : function() {
this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
reactive: true });
@ -183,7 +187,7 @@ const CtrlAltTabPopup = new Lang.Class({
let [childMinHeight, childNaturalHeight] = this._switcher.actor.get_preferred_height(primary.width - hPadding);
let [childMinWidth, childNaturalWidth] = this._switcher.actor.get_preferred_width(childNaturalHeight);
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
childBox.x2 = Math.min(primary.x + primary.width - hPadding, childBox.x1 + childNaturalWidth);
childBox.x2 = Math.min(primary.width - hPadding, childBox.x1 + childNaturalWidth);
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._switcher.actor.allocate(childBox, flags);
@ -299,14 +303,17 @@ const CtrlAltTabPopup = new Lang.Class({
this._selection = num;
this._switcher.highlight(num);
}
});
};
const CtrlAltTabSwitcher = new Lang.Class({
Name: 'CtrlAltTabSwitcher',
Extends: AltTab.SwitcherList,
function CtrlAltTabSwitcher(items) {
this._init(items);
}
CtrlAltTabSwitcher.prototype = {
__proto__ : AltTab.SwitcherList.prototype,
_init : function(items) {
this.parent(true);
AltTab.SwitcherList.prototype._init.call(this, true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
@ -329,4 +336,4 @@ const CtrlAltTabSwitcher = new Lang.Class({
this.addItem(box, text);
}
});
};

View File

@ -6,7 +6,6 @@ const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites;
@ -17,15 +16,14 @@ const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
const DASH_ANIMATION_TIME = 0.2;
const DASH_ITEM_LABEL_SHOW_TIME = 0.15;
const DASH_ITEM_LABEL_HIDE_TIME = 0.1;
const DASH_ITEM_HOVER_TIMEOUT = 300;
// A container like StBin, but taking the child's scale into account
// when requesting a size
const DashItemContainer = new Lang.Class({
Name: 'DashItemContainer',
function DashItemContainer() {
this._init();
}
DashItemContainer.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
this.actor.connect('get-preferred-width',
@ -36,8 +34,6 @@ const DashItemContainer = new Lang.Class({
Lang.bind(this, this._allocate));
this.actor._delegate = this;
this._label = null;
this.child = null;
this._childScale = 1;
this._childOpacity = 255;
@ -90,60 +86,6 @@ const DashItemContainer = new Lang.Class({
alloc.natural_size = natWidth * this.child.scale_y;
},
showLabel: function() {
if (this._label == null)
return;
this._label.opacity = 0;
this._label.show();
let [stageX, stageY] = this.actor.get_transformed_position();
let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
let labelHeight = this._label.get_height();
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
let y = stageY + yOffset;
let node = this._label.get_theme_node();
let xOffset = node.get_length('-x-offset');
let x;
if (St.Widget.get_default_direction () == St.TextDirection.RTL)
x = stageX - this._label.get_width() - xOffset;
else
x = stageX + this.actor.get_width() + xOffset;
this._label.set_position(x, y);
Tweener.addTween(this._label,
{ opacity: 255,
time: DASH_ITEM_LABEL_SHOW_TIME,
transition: 'easeOutQuad',
});
},
setLabelText: function(text) {
if (this._label == null)
this._label = new St.Label({ style_class: 'dash-label'});
this._label.set_text(text);
Main.layoutManager.addChrome(this._label);
this._label.hide();
},
hideLabel: function () {
this._label.opacity = 255;
Tweener.addTween(this._label,
{ opacity: 0,
time: DASH_ITEM_LABEL_HIDE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._label.hide();
})
});
},
setChild: function(actor) {
if (this.child == actor)
return;
@ -215,14 +157,17 @@ const DashItemContainer = new Lang.Class({
get childOpacity() {
return this._childOpacity;
}
});
};
const RemoveFavoriteIcon = new Lang.Class({
Name: 'RemoveFavoriteIcon',
Extends: DashItemContainer,
function RemoveFavoriteIcon() {
this._init();
}
RemoveFavoriteIcon.prototype = {
__proto__: DashItemContainer.prototype,
_init: function() {
this.parent();
DashItemContainer.prototype._init.call(this);
this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
this._iconActor = null;
@ -274,21 +219,28 @@ const RemoveFavoriteIcon = new Lang.Class({
return true;
}
});
};
const DragPlaceholderItem = new Lang.Class({
Name: 'DragPlaceholderItem',
Extends: DashItemContainer,
function DragPlaceholderItem() {
this._init();
}
DragPlaceholderItem.prototype = {
__proto__: DashItemContainer.prototype,
_init: function() {
this.parent();
this.setChild(new St.Bin({ style_class: 'placeholder' }));
DashItemContainer.prototype._init.call(this);
this.setChild(new St.Bin({ style_class: 'dash-placeholder' }));
}
});
};
const Dash = new Lang.Class({
Name: 'Dash',
function Dash() {
this._init();
}
Dash.prototype = {
_init : function() {
this._maxHeight = -1;
this.iconSize = 64;
@ -298,7 +250,6 @@ const Dash = new Lang.Class({
this._dragPlaceholderPos = -1;
this._animatingPlaceholdersCount = 0;
this._favRemoveTarget = null;
this._labelTimeoutId = 0;
this._box = new St.BoxLayout({ name: 'dash',
vertical: true,
@ -432,35 +383,14 @@ const Dash = new Lang.Class({
Lang.bind(this, function() {
display.actor.opacity = 255;
}));
display.actor.set_tooltip_text(app.get_name());
let item = new DashItemContainer();
item.setChild(display.actor);
item.setLabelText(app.get_name());
display.icon.setIconSize(this.iconSize);
display.actor.connect('notify::hover',
Lang.bind(this, function() {
this._onHover(item, display)
}));
return item;
},
_onHover: function (item, display) {
if (display.actor.get_hover() && !display.isMenuUp) {
if (this._labelTimeoutId == 0) {
this._labelTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
Lang.bind(this, function() {
item.showLabel();
return false;
}));
}
} else {
if (this._labelTimeoutId > 0)
Mainloop.source_remove(this._labelTimeoutId);
this._labelTimeoutId = 0;
item.hideLabel();
}
return item;
},
_adjustIconSize: function() {
@ -832,6 +762,6 @@ const Dash = new Lang.Class({
return true;
}
});
};
Signals.addSignalMethods(Dash.prototype);

View File

@ -40,9 +40,12 @@ function _onVertSepRepaint (area)
cr.stroke();
};
const DateMenuButton = new Lang.Class({
Name: 'DateMenuButton',
Extends: PanelMenu.Button,
function DateMenuButton() {
this._init.apply(this, arguments);
}
DateMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function(params) {
params = Params.parse(params, { showEvents: true });
@ -54,7 +57,7 @@ const DateMenuButton = new Lang.Class({
let menuAlignment = 0.25;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
menuAlignment = 1.0 - menuAlignment;
this.parent(menuAlignment);
PanelMenu.Button.prototype._init.call(this, menuAlignment);
this._clock = new St.Label();
this.actor.add_actor(this._clock);
@ -236,4 +239,4 @@ const DateMenuButton = new Lang.Class({
}
}
}
});
};

View File

@ -69,9 +69,11 @@ function removeDragMonitor(monitor) {
}
}
const _Draggable = new Lang.Class({
Name: 'Draggable',
function _Draggable(actor, params) {
this._init(actor, params);
}
_Draggable.prototype = {
_init : function(actor, params) {
params = Params.parse(params, { manualMode: false,
restoreOnSuccess: false,
@ -594,7 +596,7 @@ const _Draggable = new Lang.Class({
this._dragActor = undefined;
currentDraggable = null;
}
});
};
Signals.addSignalMethods(_Draggable.prototype);

View File

@ -1,16 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DocInfo = imports.misc.docInfo;
const Lang = imports.lang;
const Params = imports.misc.params;
const Search = imports.ui.search;
const DocSearchProvider = new Lang.Class({
Name: 'DocSearchProvider',
Extends: Search.SearchProvider,
function DocSearchProvider() {
this._init();
}
DocSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function(name) {
this.parent(_("RECENT ITEMS"));
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
this._docManager = DocInfo.getDocManager();
},
@ -41,4 +44,4 @@ const DocSearchProvider = new Lang.Class({
getSubsearchResultSet: function(previousResults, terms) {
return this._docManager.subsearch(previousResults, terms);
}
});
};

View File

@ -18,19 +18,19 @@
* 02111-1307, USA.
*/
const DBus = imports.dbus;
const Lang = imports.lang;
const Signals = imports.signals;
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession;
const GnomeSession = imports.misc.gnomeSession
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
@ -43,23 +43,22 @@ const _DIALOG_ICON_SIZE = 32;
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
<method name="Open">
<arg type="u" direction="in" />
<arg type="u" direction="in" />
<arg type="u" direction="in" />
<arg type="ao" direction="in" />
</method>
<signal name="ConfirmedLogout" />
<signal name="ConfirmedReboot" />
<signal name="ConfirmedShutdown" />
<signal name="Canceled" />
<signal name="Closed" />
</interface>;
const EndSessionDialogIface = {
name: 'org.gnome.SessionManager.EndSessionDialog',
methods: [{ name: 'Open',
inSignature: 'uuuao',
outSignature: ''
}
],
signals: [{ name: 'Canceled',
inSignature: '',
}],
properties: []
};
const logoutDialogContent = {
subjectWithUser: C_("title", "Log Out %s"),
subject: C_("title", "Log Out"),
subjectWithUser: _("Log Out %s"),
subject: _("Log Out"),
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
uninhibitedDescriptionWithUser: function(user, seconds) {
return ngettext("%s will be logged out automatically in %d second.",
@ -73,12 +72,12 @@ const logoutDialogContent = {
},
endDescription: _("Logging out of the system."),
confirmButtons: [{ signal: 'ConfirmedLogout',
label: C_("button", "Log Out") }],
label: _("Log Out") }],
iconStyleClass: 'end-session-dialog-logout-icon'
};
const shutdownDialogContent = {
subject: C_("title", "Power Off"),
subject: _("Power Off"),
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will power off automatically in %d second.",
@ -87,15 +86,15 @@ const shutdownDialogContent = {
},
endDescription: _("Powering off the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") },
label: _("Restart") },
{ signal: 'ConfirmedShutdown',
label: C_("button", "Power Off") }],
label: _("Power Off") }],
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
const restartDialogContent = {
subject: C_("title", "Restart"),
subject: _("Restart"),
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will restart automatically in %d second.",
@ -104,7 +103,7 @@ const restartDialogContent = {
},
endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }],
label: _("Restart") }],
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
@ -142,9 +141,11 @@ function findAppFromInhibitor(inhibitor) {
return app;
}
const ListItem = new Lang.Class({
Name: 'ListItem',
function ListItem(app, reason) {
this._init(app, reason);
}
ListItem.prototype = {
_init: function(app, reason) {
this._app = app;
this._reason = reason;
@ -190,7 +191,7 @@ const ListItem = new Lang.Class({
this.emit('activate');
this._app.activate();
}
});
};
Signals.addSignalMethods(ListItem.prototype);
// The logout timer only shows updates every 10 seconds
@ -228,19 +229,29 @@ function _setLabelText(label, text) {
}
}
function EndSessionDialog() {
if (_endSessionDialog == null) {
this._init();
DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
this);
_endSessionDialog = this;
}
return _endSessionDialog;
}
function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
_endSessionDialog = new EndSessionDialog();
let dialog = new EndSessionDialog();
}
const EndSessionDialog = new Lang.Class({
Name: 'EndSessionDialog',
Extends: ModalDialog.ModalDialog,
EndSessionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function() {
this.parent({ styleClass: 'end-session-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'end-session-dialog' });
this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
@ -315,9 +326,6 @@ const EndSessionDialog = new Lang.Class({
if (this._applicationList.get_children().length == 0)
scrollView.hide();
}));
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
},
_onDestroy: function() {
@ -431,20 +439,26 @@ const EndSessionDialog = new Lang.Class({
},
close: function() {
this.parent();
this._dbusImpl.emit_signal('Closed', null);
ModalDialog.ModalDialog.prototype.close.call(this);
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
'Closed', '', []);
},
cancel: function() {
this._stopTimer();
this._dbusImpl.emit_signal('Canceled', null);
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
'Canceled', '', []);
this.close(global.get_current_time());
},
_confirm: function(signal) {
this._fadeOutDialog();
this._stopTimer();
this._dbusImpl.emit_signal(signal, null);
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
signal, '', []);
},
_onOpened: function() {
@ -496,41 +510,39 @@ const EndSessionDialog = new Lang.Class({
this._updateContent();
},
OpenAsync: function(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._inhibitors = [];
this._applicationList.destroy_children();
this._type = type;
if (!(this._type in DialogContent)) {
invocation.report_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
"Unknown dialog type requested");
return;
}
if (!(this._type in DialogContent))
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
"Unknown dialog type requested");
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
this._onInhibitorLoaded(proxy);
}));
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
inhibitor.connect('is-loaded',
Lang.bind(this, function() {
this._onInhibitorLoaded(inhibitor);
}));
this._inhibitors.push(inhibitor);
}
this._updateButtons();
if (!this.open(timestamp)) {
invocation.report_dbus_error('org.gnome.Shell.ModalDialog.GrabError',
"Cannot grab pointer and keyboard");
return;
}
if (!this.open(timestamp))
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
"Cannot grab pointer and keyboard");
this._updateContent();
let signalId = this.connect('opened',
Lang.bind(this, function() {
invocation.return_value(null);
callback();
this.disconnect(signalId);
}));
}
});
};
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);

View File

@ -22,7 +22,6 @@ const ExtensionState = {
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
@ -63,9 +62,6 @@ const extensionMeta = {};
const extensions = {};
// Maps uuid -> extension state object (returned from init())
const extensionStateObjs = {};
// Contains the order that extensions were enabled in.
const extensionOrder = [];
// Arrays of uuids
var enabledExtensions;
// GFile for user extensions
@ -202,7 +198,7 @@ function gotExtensionZipFile(session, message, uuid) {
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
loadExtension(dir, ExtensionType.PER_USER, true);
loadExtension(dir, true, ExtensionType.PER_USER);
});
}
@ -216,27 +212,6 @@ function disableExtension(uuid) {
let extensionState = extensionStateObjs[uuid];
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
let orderIdx = extensionOrder.indexOf(uuid);
let order = extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
extensionStateObjs[uuid].disable();
} catch(e) {
logExtensionError(uuid, e.toString());
}
}
try {
extensionState.disable();
} catch(e) {
@ -244,17 +219,6 @@ function disableExtension(uuid) {
return;
}
for (let i = 0; i < order.length; i++) {
let uuid = order[i];
try {
extensionStateObjs[uuid].enable();
} catch(e) {
logExtensionError(uuid, e.toString());
}
}
extensionOrder.splice(orderIdx, 1);
meta.state = ExtensionState.DISABLED;
_signals.emit('extension-state-changed', meta);
}
@ -264,18 +228,11 @@ function enableExtension(uuid) {
if (!meta)
return;
if (meta.state == ExtensionState.INITIALIZED) {
loadExtension(meta.dir, meta.type, true);
return;
}
if (meta.state != ExtensionState.DISABLED)
return;
let extensionState = extensionStateObjs[uuid];
extensionOrder.push(uuid);
try {
extensionState.enable();
} catch(e) {
@ -297,7 +254,7 @@ function logExtensionError(uuid, message, state) {
state: state });
}
function loadExtension(dir, type, enabled) {
function loadExtension(dir, enabled, type) {
let info;
let uuid = dir.get_basename();
@ -346,9 +303,14 @@ function loadExtension(dir, type, enabled) {
return;
}
if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
(meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
logExtensionError(uuid, 'extension is not compatible with current GNOME Shell and/or GJS version');
return;
}
extensionMeta[uuid] = meta;
meta.type = type;
meta.dir = dir;
meta.path = dir.get_path();
meta.error = '';
@ -362,11 +324,6 @@ function loadExtension(dir, type, enabled) {
return;
}
if (!enabled) {
meta.state = ExtensionState.INITIALIZED;
return;
}
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
logExtensionError(uuid, 'Missing extension.js');
@ -426,7 +383,8 @@ function loadExtension(dir, type, enabled) {
meta.state = ExtensionState.DISABLED;
enableExtension(uuid);
if (enabled)
enableExtension(uuid);
_signals.emit('extension-loaded', meta.uuid);
_signals.emit('extension-state-changed', meta);
@ -486,7 +444,7 @@ function _loadExtensionsIn(dir, type) {
let name = info.get_name();
let child = dir.get_child(name);
let enabled = enabledExtensions.indexOf(name) != -1;
loadExtension(child, type, enabled);
loadExtension(child, enabled, type);
}
fileEnum.close(null);
}
@ -502,12 +460,15 @@ function loadExtensions() {
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
}
const InstallExtensionDialog = new Lang.Class({
Name: 'InstallExtensionDialog',
Extends: ModalDialog.ModalDialog,
function InstallExtensionDialog(uuid, version_tag, name) {
this._init(uuid, version_tag, name);
}
InstallExtensionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(uuid, version_tag, name) {
this.parent({ styleClass: 'extension-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'extension-dialog' });
this._uuid = uuid;
this._version_tag = version_tag;
@ -567,4 +528,4 @@ const InstallExtensionDialog = new Lang.Class({
this.close(global.get_current_time());
}
});
};

View File

@ -10,9 +10,11 @@ const Params = imports.misc.params;
const ICON_SIZE = 48;
const BaseIcon = new Lang.Class({
Name: 'BaseIcon',
function BaseIcon(label, createIcon) {
this._init(label, createIcon);
}
BaseIcon.prototype = {
_init : function(label, params) {
params = Params.parse(params, { createIcon: null,
setSizeManually: false,
@ -35,8 +37,7 @@ const BaseIcon = new Lang.Class({
this.actor.set_child(box);
this.iconSize = ICON_SIZE;
this._iconBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._iconBin = new St.Bin();
box.add_actor(this._iconBin);
@ -126,12 +127,12 @@ const BaseIcon = new Lang.Class({
this.iconSize = size;
this.icon = this.createIcon(this.iconSize);
this._iconBin.child = this.icon;
// The icon returned by createIcon() might actually be smaller than
// the requested icon size (for instance StTextureCache does this
// for fallback icons), so set the size explicitly.
this._iconBin.set_size(this.iconSize, this.iconSize);
this.icon.set_size(this.iconSize, this.iconSize);
this._iconBin.child = this.icon;
},
_onStyleChanged: function() {
@ -153,11 +154,13 @@ const BaseIcon = new Lang.Class({
this._createIconTexture(size);
}
});
};
const IconGrid = new Lang.Class({
Name: 'IconGrid',
function IconGrid(params) {
this._init(params);
}
IconGrid.prototype = {
_init: function(params) {
params = Params.parse(params, { rowLimit: null,
columnLimit: null,
@ -326,4 +329,4 @@ const IconGrid = new Lang.Class({
visibleItemsCount: function() {
return this._grid.get_children().length - this._grid.get_n_skip_paint();
}
});
};

View File

@ -39,31 +39,34 @@ const PRETTY_KEYS = {
'Alt_L': 'Alt'
};
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
<method name='Show'>
<arg type='u' direction='in' />
</method>
<method name='Hide'>
<arg type='u' direction='in' />
</method>
<method name='SetCursorLocation'>
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
</method>
<method name='SetEntryLocation'>
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
</method>
<property name='Name' access='read' type='s' />
</interface>;
const CaribouKeyboardIface = {
name: 'org.gnome.Caribou.Keyboard',
methods: [ { name: 'Show',
inSignature: 'u',
outSignature: ''
},
{ name: 'Hide',
inSignature: 'u',
outSignature: ''
},
{ name: 'SetCursorLocation',
inSignature: 'iiii',
outSignature: ''
},
{ name: 'SetEntryLocation',
inSignature: 'iiii',
outSignature: ''
} ],
properties: [ { name: 'Name',
signature: 's',
access: 'read' } ]
};
const Key = new Lang.Class({
Name: 'Key',
function Key() {
this._init.apply(this, arguments);
}
Key.prototype = {
_init : function(key) {
this._key = key;
@ -189,15 +192,15 @@ const Key = new Lang.Class({
this._boxPointer.hide(true);
}
}
});
};
const Keyboard = new Lang.Class({
// HACK: we can't set Name, because it collides with Name dbus property
// Name: 'Keyboard',
function Keyboard() {
this._init.apply(this, arguments);
}
Keyboard.prototype = {
_init: function () {
this._impl = Gio.DBusExportedObject.wrapJSObject(CaribouKeyboardIface, this);
this._impl.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
DBus.session.exportObject('/org/gnome/Caribou/Keyboard', this);
this.actor = null;
@ -286,7 +289,7 @@ const Keyboard = new Lang.Class({
if (focus && (focus._extended_keys || (focus._key && focus._key.extended_key)))
return;
let time = global.get_current_time();
let time = global.current_event_time();
if (focus instanceof Clutter.Text)
this.Show(time);
else
@ -529,15 +532,19 @@ const Keyboard = new Lang.Class({
get Name() {
return 'gnome-shell';
}
});
};
DBus.conformExport(Keyboard.prototype, CaribouKeyboardIface);
const KeyboardSource = new Lang.Class({
Name: 'KeyboardSource',
Extends: MessageTray.Source,
function KeyboardSource() {
this._init.apply(this, arguments);
}
KeyboardSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(keyboard) {
this.parent(_("Keyboard"));
this._keyboard = keyboard;
MessageTray.Source.prototype._init.call(this, _("Keyboard"));
this._setSummaryIcon(this.createNotificationIcon());
},
@ -548,7 +555,7 @@ const KeyboardSource = new Lang.Class({
icon_size: this.ICON_SIZE });
},
handleSummaryClick: function() {
handleSummaryClick: function() {
let event = Clutter.get_current_event();
if (event.type() != Clutter.EventType.BUTTON_RELEASE)
return false;
@ -560,4 +567,4 @@ const KeyboardSource = new Lang.Class({
open: function() {
this._keyboard.show();
}
});
};

View File

@ -17,9 +17,11 @@ const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const STARTUP_ANIMATION_TIME = 0.2;
const KEYBOARD_ANIMATION_TIME = 0.5;
const LayoutManager = new Lang.Class({
Name: 'LayoutManager',
function LayoutManager() {
this._init.apply(this, arguments);
}
LayoutManager.prototype = {
_init: function () {
this._rtl = (St.Widget.get_default_direction() == St.TextDirection.RTL);
this.monitors = [];
@ -372,7 +374,7 @@ const LayoutManager = new Lang.Class({
findMonitorForActor: function(actor) {
return this._chrome.findMonitorForActor(actor);
}
});
};
Signals.addSignalMethods(LayoutManager.prototype);
@ -380,9 +382,11 @@ Signals.addSignalMethods(LayoutManager.prototype);
//
// This class manages a "hot corner" that can toggle switching to
// overview.
const HotCorner = new Lang.Class({
Name: 'HotCorner',
function HotCorner() {
this._init();
}
HotCorner.prototype = {
_init : function() {
// 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
@ -433,9 +437,9 @@ const HotCorner = new Lang.Class({
Lang.bind(this, this._onCornerLeft));
// Cache the three ripples instead of dynamically creating and destroying them.
this._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
this._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
Main.uiGroup.add_actor(this._ripple1);
Main.uiGroup.add_actor(this._ripple2);
@ -544,7 +548,7 @@ const HotCorner = new Lang.Class({
return true;
return false;
}
});
};
// This manages the shell "chrome"; the UI that's visible in the
@ -557,9 +561,11 @@ const defaultParams = {
affectsInputRegion: true
};
const Chrome = new Lang.Class({
Name: 'Chrome',
function Chrome() {
this._init.apply(this, arguments);
}
Chrome.prototype = {
_init: function(layoutManager) {
this._layoutManager = layoutManager;
@ -581,13 +587,12 @@ const Chrome = new Lang.Class({
this._screenSaverActive = false;
this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
this._screenSaverProxy.connectSignal('ActiveChanged', Lang.bind(this, function(proxy, senderName, [isActive]) {
this._onScreenSaverActiveChanged(isActive);
}));
this._screenSaverProxy.GetActiveRemote(Lang.bind(this, function(result, err) {
if (!err)
this._onScreenSaverActiveChanged(result[0]);
}));
this._screenSaverProxy.connect('ActiveChanged', Lang.bind(this, this._onScreenSaverActiveChanged));
this._screenSaverProxy.GetActiveRemote(Lang.bind(this,
function(result, err) {
if (!err)
this._onScreenSaverActiveChanged(this._screenSaverProxy, result);
}));
this._relayout();
},
@ -728,7 +733,7 @@ const Chrome = new Lang.Class({
this._queueUpdateRegions();
},
_onScreenSaverActiveChanged: function(screenSaverActive) {
_onScreenSaverActiveChanged: function(proxy, screenSaverActive) {
this._screenSaverActive = screenSaverActive;
this._updateVisibility();
this._queueUpdateRegions();
@ -975,4 +980,4 @@ const Chrome = new Lang.Class({
return false;
}
});
};

View File

@ -30,9 +30,11 @@ const Tweener = imports.ui.tweener;
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height in @params.
*/
const Lightbox = new Lang.Class({
Name: 'Lightbox',
function Lightbox(container, params) {
this._init(container, params);
}
Lightbox.prototype = {
_init : function(container, params) {
params = Params.parse(params, { inhibitEvents: false,
width: null,
@ -194,4 +196,4 @@ const Lightbox = new Lang.Class({
this.highlight(null);
}
});
};

View File

@ -4,9 +4,11 @@ const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
const Link = new Lang.Class({
Name: 'Link',
function Link(props) {
this._init(props);
}
Link.prototype = {
_init : function(props) {
let realProps = { reactive: true,
track_hover: true,
@ -17,5 +19,6 @@ const Link = new Lang.Class({
this.actor = new St.Button(realProps);
}
});
};
Signals.addSignalMethods(Link.prototype);

View File

@ -2,6 +2,7 @@
const Clutter = imports.gi.Clutter;
const Cogl = imports.gi.Cogl;
const GConf = imports.gi.GConf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
@ -19,7 +20,6 @@ const Link = imports.ui.link;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const JsParse = imports.misc.jsParse;
/* Imports...feel free to add here as needed */
var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
@ -41,88 +41,12 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
const HISTORY_KEY = 'looking-glass-history';
// Time between tabs for them to count as a double-tab event
const AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
const AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 0.2;
const AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of window (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(window).filter(function(a){ return a.charAt(0) != '_' });
const headerProperties = JsParse.getDeclaredConstants(commandHeader);
return keywords.concat(windowProperties).concat(headerProperties);
function Notebook() {
this._init();
}
const AutoComplete = new Lang.Class({
Name: 'AutoComplete',
_init: function(entry) {
this._entry = entry;
this._entry.connect('key-press-event', Lang.bind(this, this._entryKeyPressEvent));
this._lastTabTime = global.get_current_time();
},
_processCompletionRequest: function(event) {
if (event.completions.length == 0) {
return;
}
// Unique match = go ahead and complete; multiple matches + single tab = complete the common starting string;
// multiple matches + double tab = emit a suggest event with all possible options
if (event.completions.length == 1) {
this.additionalCompletionText(event.completions[0], event.attrHead);
this.emit('completion', { completion: event.completions[0], type: 'whole-word' });
} else if (event.completions.length > 1 && event.tabType === 'single') {
let commonPrefix = JsParse.getCommonPrefix(event.completions);
if (commonPrefix.length > 0) {
this.additionalCompletionText(commonPrefix, event.attrHead);
this.emit('completion', { completion: commonPrefix, type: 'prefix' });
this.emit('suggest', { completions: event.completions});
}
} else if (event.completions.length > 1 && event.tabType === 'double') {
this.emit('suggest', { completions: event.completions});
}
},
_entryKeyPressEvent: function(actor, event) {
let cursorPos = this._entry.clutter_text.get_cursor_position();
let text = this._entry.get_text();
if (cursorPos != -1) {
text = text.slice(0, cursorPos);
}
if (event.get_key_symbol() == Clutter.Tab) {
let [completions, attrHead] = JsParse.getCompletions(text, commandHeader, AUTO_COMPLETE_GLOBAL_KEYWORDS);
let currTime = global.get_current_time();
if ((currTime - this._lastTabTime) < AUTO_COMPLETE_DOUBLE_TAB_DELAY) {
this._processCompletionRequest({ tabType: 'double',
completions: completions,
attrHead: attrHead });
} else {
this._processCompletionRequest({ tabType: 'single',
completions: completions,
attrHead: attrHead });
}
this._lastTabTime = currTime;
}
},
// Insert characters of text not already included in head at cursor position. i.e., if text="abc" and head="a",
// the string "bc" will be appended to this._entry
additionalCompletionText: function(text, head) {
let additionalCompletionText = text.slice(head.length);
let cursorPos = this._entry.clutter_text.get_cursor_position();
this._entry.clutter_text.insert_text(additionalCompletionText, cursorPos);
}
});
Signals.addSignalMethods(AutoComplete.prototype);
const Notebook = new Lang.Class({
Name: 'Notebook',
Notebook.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
@ -227,26 +151,8 @@ const Notebook = new Lang.Class({
return;
let vAdjust = tabData.scrollView.vscroll.adjustment;
vAdjust.value = vAdjust.upper - vAdjust.page_size;
},
nextTab: function() {
let nextIndex = this._selectedIndex;
if (nextIndex < this._tabs.length - 1) {
++nextIndex;
}
this.selectIndex(nextIndex);
},
prevTab: function() {
let prevIndex = this._selectedIndex;
if (prevIndex > 0) {
--prevIndex;
}
this.selectIndex(prevIndex);
}
});
};
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) {
@ -258,9 +164,12 @@ function objectToString(o) {
}
}
const ObjLink = new Lang.Class({
Name: 'ObjLink',
Extends: Link.Link,
function ObjLink(o, title) {
this._init(o, title);
}
ObjLink.prototype = {
__proto__: Link.Link,
_init: function(o, title) {
let text;
@ -270,8 +179,7 @@ const ObjLink = new Lang.Class({
text = objectToString(o);
text = GLib.markup_escape_text(text, -1);
this._obj = o;
this.parent({ label: text });
Link.Link.prototype._init.call(this, { label: text });
this.actor.get_child().single_line_mode = true;
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
},
@ -279,11 +187,13 @@ const ObjLink = new Lang.Class({
_onClicked: function (link) {
Main.lookingGlass.inspectObject(this._obj, this.actor);
}
});
};
const Result = new Lang.Class({
Name: 'Result',
function Result(command, o, index) {
this._init(command, o, index);
}
Result.prototype = {
_init : function(command, o, index) {
this.index = index;
this.o = o;
@ -305,11 +215,13 @@ const Result = new Lang.Class({
padBin.add_actor(line);
this.actor.add(padBin);
}
});
};
const WindowList = new Lang.Class({
Name: 'WindowList',
function WindowList() {
this._init();
}
WindowList.prototype = {
_init : function () {
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default();
@ -350,12 +262,14 @@ const WindowList = new Lang.Class({
}
}
}
});
};
Signals.addSignalMethods(WindowList.prototype);
const ObjInspector = new Lang.Class({
Name: 'ObjInspector',
function ObjInspector() {
this._init();
}
ObjInspector.prototype = {
_init : function () {
this._obj = null;
this._previousObj = null;
@ -455,7 +369,7 @@ const ObjInspector = new Lang.Class({
_onBack: function() {
this.selectObject(this._previousObj, true);
}
});
};
function addBorderPaintHook(actor) {
let signalId = actor.connect_after('paint',
@ -481,9 +395,11 @@ function addBorderPaintHook(actor) {
return signalId;
}
const Inspector = new Lang.Class({
Name: 'Inspector',
function Inspector() {
this._init();
}
Inspector.prototype = {
_init: function() {
let container = new Shell.GenericContainer({ width: 0,
height: 0 });
@ -622,13 +538,15 @@ const Inspector = new Lang.Class({
this._borderPaintId = addBorderPaintHook(this._target);
}
}
});
};
Signals.addSignalMethods(Inspector.prototype);
const ErrorLog = new Lang.Class({
Name: 'ErrorLog',
function ErrorLog() {
this._init();
}
ErrorLog.prototype = {
_init: function() {
this.actor = new St.BoxLayout();
this.text = new St.Label();
@ -663,11 +581,13 @@ const ErrorLog = new Lang.Class({
}
this.text.text = text;
}
});
};
const Memory = new Lang.Class({
Name: 'Memory',
function Memory() {
this._init();
}
Memory.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
this._glibc_uordblks = new St.Label();
@ -712,11 +632,13 @@ const Memory = new Lang.Class({
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
}
});
};
const Extensions = new Lang.Class({
Name: 'Extensions',
function Extensions() {
this._init();
}
Extensions.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
@ -764,40 +686,11 @@ const Extensions = new Lang.Class({
Main.lookingGlass.close();
},
_onViewErrors: function (actor) {
let meta = actor._extensionMeta;
let shouldShow = !actor._isShowing;
if (shouldShow) {
let errors = ExtensionSystem.errors[meta.uuid];
let errorDisplay = new St.BoxLayout({ vertical: true });
if (errors && errors.length) {
for (let i = 0; i < errors.length; i ++)
errorDisplay.add(new St.Label({ text: errors[i] }));
} else {
/* Translators: argument is an extension UUID. */
let message = _("%s has not emitted any errors.").format(meta.uuid);
errorDisplay.add(new St.Label({ text: message }));
}
actor._errorDisplay = errorDisplay;
actor._parentBox.add(errorDisplay);
actor.label = _("Hide Errors");
} else {
actor._errorDisplay.destroy();
actor._errorDisplay = null;
actor.label = _("Show Errors");
}
actor._isShowing = shouldShow;
},
_stateToString: function(extensionState) {
switch (extensionState) {
case ExtensionSystem.ExtensionState.ENABLED:
return _("Enabled");
case ExtensionSystem.ExtensionState.DISABLED:
case ExtensionSystem.ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionSystem.ExtensionState.ERROR:
return _("Error");
@ -837,20 +730,15 @@ const Extensions = new Lang.Class({
metaBox.add(webpage.actor);
}
let viewerrors = new Link.Link({ label: _("Show Errors") });
viewerrors.actor._extensionMeta = meta;
viewerrors.actor._parentBox = box;
viewerrors.actor._isShowing = false;
viewerrors.actor.connect('clicked', Lang.bind(this, this._onViewErrors));
metaBox.add(viewerrors.actor);
return box;
}
});
};
const LookingGlass = new Lang.Class({
Name: 'LookingGlass',
function LookingGlass() {
this._init();
}
LookingGlass.prototype = {
_init : function() {
this._borderPaintTarget = null;
this._borderPaintId = 0;
@ -867,8 +755,7 @@ const LookingGlass = new Lang.Class({
this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
style_class: 'lg-dialog',
vertical: true,
visible: false,
reactive: true });
visible: false });
this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent));
this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
@ -923,15 +810,15 @@ const LookingGlass = new Lang.Class({
this._resultsArea = new St.BoxLayout({ name: 'ResultsArea', vertical: true });
this._evalBox.add(this._resultsArea, { expand: true });
this._entryArea = new St.BoxLayout({ name: 'EntryArea' });
this._evalBox.add_actor(this._entryArea);
let entryArea = new St.BoxLayout({ name: 'EntryArea' });
this._evalBox.add_actor(entryArea);
let label = new St.Label({ text: 'js>>> ' });
this._entryArea.add(label);
entryArea.add(label);
this._entry = new St.Entry({ can_focus: true });
ShellEntry.addContextMenu(this._entry);
this._entryArea.add(this._entry, { expand: true });
entryArea.add(this._entry, { expand: true });
this._windowList = new WindowList();
this._windowList.connect('selected', Lang.bind(this, function(list, window) {
@ -950,9 +837,6 @@ const LookingGlass = new Lang.Class({
notebook.appendPage('Extensions', this._extensions.actor);
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
// Hide any completions we are currently showing
this._hideCompletions();
let text = o.get_text();
// Ensure we don't get newlines in the command; the history file is
// newline-separated.
@ -968,17 +852,6 @@ const LookingGlass = new Lang.Class({
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entry.clutter_text });
this._autoComplete = new AutoComplete(this._entry);
this._autoComplete.connect('suggest', Lang.bind(this, function(a,e) {
this._showCompletions(e.completions);
}));
// If a completion is completed unambiguously, the currently-displayed completion
// suggestions become irrelevant.
this._autoComplete.connect('completion', Lang.bind(this, function(a,e) {
if (e.type == 'whole-word')
this._hideCompletions();
}));
this._resize();
},
@ -1023,59 +896,6 @@ const LookingGlass = new Lang.Class({
this._notebook.scrollToBottom(0);
},
_showCompletions: function(completions) {
if (!this._completionActor) {
let actor = new St.BoxLayout({ vertical: true });
this._completionText = new St.Label({ name: 'LookingGlassAutoCompletionText', style_class: 'lg-completions-text' });
this._completionText.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._completionText.clutter_text.line_wrap = true;
actor.add(this._completionText);
let line = new Clutter.Rectangle();
let padBin = new St.Bin({ x_fill: true, y_fill: true });
padBin.add_actor(line);
actor.add(padBin);
this._completionActor = actor;
this._evalBox.insert_before(this._completionActor, this._entryArea);
}
this._completionText.set_text(completions.join(', '));
// Setting the height to -1 allows us to get its actual preferred height rather than
// whatever was last given in set_height by Tweener.
this._completionActor.set_height(-1);
let [minHeight, naturalHeight] = this._completionText.get_preferred_height(this._resultsArea.get_width());
// Don't reanimate if we are already visible
if (this._completionActor.visible) {
this._completionActor.height = naturalHeight;
} else {
this._completionActor.show();
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
transition: 'easeOutQuad',
height: naturalHeight,
opacity: 255
});
}
},
_hideCompletions: function() {
if (this._completionActor) {
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
transition: 'easeOutQuad',
height: 0,
opacity: 0,
onComplete: Lang.bind(this, function () {
this._completionActor.hide();
})
});
}
},
_evaluate : function(command) {
this._history.addItem(command);
@ -1140,7 +960,6 @@ const LookingGlass = new Lang.Class({
// Handle key events which are relevant for all tabs of the LookingGlass
_globalKeyPressEvent : function(actor, event) {
let symbol = event.get_key_symbol();
let modifierState = Shell.get_event_state(event);
if (symbol == Clutter.Escape) {
if (this._objInspector.actor.visible) {
this._objInspector.close();
@ -1149,14 +968,6 @@ const LookingGlass = new Lang.Class({
}
return true;
}
// Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
if (modifierState & Clutter.ModifierType.CONTROL_MASK) {
if (symbol == Clutter.KEY_Page_Up) {
this._notebook.prevTab();
} else if (symbol == Clutter.KEY_Page_Down) {
this._notebook.nextTab();
}
}
return false;
},
@ -1207,5 +1018,5 @@ const LookingGlass = new Lang.Class({
})
});
}
});
};
Signals.addSignalMethods(LookingGlass.prototype);

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
@ -13,6 +12,22 @@ const Main = imports.ui.main;
const MagnifierDBus = imports.ui.magnifierDBus;
const Params = imports.misc.params;
// Keep enums in sync with GSettings schemas
const MouseTrackingMode = {
NONE: 0,
CENTERED: 1,
PROPORTIONAL: 2,
PUSH: 3
};
const ScreenPosition = {
NONE: 0,
FULL_SCREEN: 1,
TOP_HALF: 2,
BOTTOM_HALF: 3,
LEFT_HALF: 4,
RIGHT_HALF: 5
};
const MOUSE_POLL_FREQUENCY = 50;
const CROSSHAIRS_CLIP_SIZE = [100, 100];
@ -36,15 +51,17 @@ const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
let magDBusService = null;
const Magnifier = new Lang.Class({
Name: 'Magnifier',
function Magnifier() {
this._init();
}
Magnifier.prototype = {
_init: function() {
// Magnifier is a manager of ZoomRegions.
this._zoomRegions = [];
// Create small clutter tree for the magnified mouse.
let xfixesCursor = Shell.XFixesCursor.get_for_stage(global.stage);
let xfixesCursor = Shell.XFixesCursor.get_default();
this._mouseSprite = new Clutter.Texture();
xfixesCursor.update_texture_image(this._mouseSprite);
this._cursorRoot = new Clutter.Group();
@ -503,7 +520,7 @@ const Magnifier = new Lang.Class({
if (this._zoomRegions.length) {
let position = this._settings.get_enum(SCREEN_POSITION_KEY);
this._zoomRegions[0].setScreenPosition(position);
if (position != GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN)
if (position != ScreenPosition.FULL_SCREEN)
this._updateLensMode();
}
},
@ -541,19 +558,21 @@ const Magnifier = new Lang.Class({
);
}
}
});
};
Signals.addSignalMethods(Magnifier.prototype);
const ZoomRegion = new Lang.Class({
Name: 'ZoomRegion',
function ZoomRegion(magnifier, mouseSourceActor) {
this._init(magnifier, mouseSourceActor);
}
ZoomRegion.prototype = {
_init: function(magnifier, mouseSourceActor) {
this._magnifier = magnifier;
this._mouseTrackingMode = GDesktopEnums.MagnifierMouseTrackingMode.NONE;
this._mouseTrackingMode = MouseTrackingMode.NONE;
this._clampScrollingAtEdges = false;
this._lensMode = false;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
this._screenPosition = ScreenPosition.FULL_SCREEN;
this._magView = null;
this._uiGroupClone = null;
@ -628,8 +647,7 @@ const ZoomRegion = new Lang.Class({
* @mode: One of the enum MouseTrackingMode values.
*/
setMouseTrackingMode: function(mode) {
if (mode >= GDesktopEnums.MagnifierMouseTrackingMode.NONE &&
mode <= GDesktopEnums.MagnifierMouseTrackingMode.PUSH)
if (mode >= MouseTrackingMode.NONE && mode <= MouseTrackingMode.PUSH)
this._mouseTrackingMode = mode;
},
@ -650,7 +668,7 @@ const ZoomRegion = new Lang.Class({
*/
setViewPort: function(viewPort) {
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.NONE;
this._screenPosition = ScreenPosition.NONE;
},
/**
@ -732,7 +750,7 @@ const ZoomRegion = new Lang.Class({
viewPort.width = global.screen_width;
viewPort.height = global.screen_height/2;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.TOP_HALF;
this._screenPosition = ScreenPosition.TOP_HALF;
},
/**
@ -746,7 +764,7 @@ const ZoomRegion = new Lang.Class({
viewPort.width = global.screen_width;
viewPort.height = global.screen_height/2;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF;
this._screenPosition = ScreenPosition.BOTTOM_HALF;
},
/**
@ -760,7 +778,7 @@ const ZoomRegion = new Lang.Class({
viewPort.width = global.screen_width/2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.LEFT_HALF;
this._screenPosition = ScreenPosition.LEFT_HALF;
},
/**
@ -774,7 +792,7 @@ const ZoomRegion = new Lang.Class({
viewPort.width = global.screen_width/2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF;
this._screenPosition = ScreenPosition.RIGHT_HALF;
},
/**
@ -790,7 +808,7 @@ const ZoomRegion = new Lang.Class({
viewPort.height = global.screen_height;
this.setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
this._screenPosition = ScreenPosition.FULL_SCREEN;
},
/**
@ -803,19 +821,19 @@ const ZoomRegion = new Lang.Class({
*/
setScreenPosition: function(inPosition) {
switch (inPosition) {
case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
case ScreenPosition.FULL_SCREEN:
this.setFullScreenMode();
break;
case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
case ScreenPosition.TOP_HALF:
this.setTopHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
case ScreenPosition.BOTTOM_HALF:
this.setBottomHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
case ScreenPosition.LEFT_HALF:
this.setLeftHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
case ScreenPosition.RIGHT_HALF:
this.setRightHalf();
break;
}
@ -838,7 +856,7 @@ const ZoomRegion = new Lang.Class({
*/
scrollToMousePos: function() {
this._followingCursor = true;
if (this._mouseTrackingMode != GDesktopEnums.MagnifierMouseTrackingMode.NONE)
if (this._mouseTrackingMode != MouseTrackingMode.NONE)
this._changeROI({ redoCursorTracking: true });
else
this._updateMousePosition();
@ -973,7 +991,7 @@ const ZoomRegion = new Lang.Class({
this._yMagFactor = params.yMagFactor;
if (params.redoCursorTracking &&
this._mouseTrackingMode != GDesktopEnums.MagnifierMouseTrackingMode.NONE) {
this._mouseTrackingMode != MouseTrackingMode.NONE) {
// This depends on this.xMagFactor/yMagFactor already being updated
[params.xCenter, params.yCenter] = this._centerFromMousePosition();
}
@ -1023,7 +1041,7 @@ const ZoomRegion = new Lang.Class({
_isFullScreen: function() {
// Does the magnified view occupy the whole screen? Note that this
// doesn't necessarily imply
// this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
// this._screenPosition = ScreenPosition.FULL_SCREEN;
if (this._viewPortX != 0 || this._viewPortY != 0)
return false;
@ -1040,13 +1058,13 @@ const ZoomRegion = new Lang.Class({
let xMouse = this._magnifier.xMouse;
let yMouse = this._magnifier.yMouse;
if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL) {
if (this._mouseTrackingMode == MouseTrackingMode.PROPORTIONAL) {
return this._centerFromMouseProportional(xMouse, yMouse);
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
else if (this._mouseTrackingMode == MouseTrackingMode.PUSH) {
return this._centerFromMousePush(xMouse, yMouse);
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
else if (this._mouseTrackingMode == MouseTrackingMode.CENTERED) {
return this._centerFromMouseCentered(xMouse, yMouse);
}
@ -1146,11 +1164,13 @@ const ZoomRegion = new Lang.Class({
yMagMouse - groupHeight / 2);
}
}
});
};
const Crosshairs = new Lang.Class({
Name: 'Crosshairs',
function Crosshairs() {
this._init();
}
Crosshairs.prototype = {
_init: function() {
// Set the group containing the crosshairs to three times the desktop
@ -1406,4 +1426,4 @@ const Crosshairs = new Lang.Class({
this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
}
});
};

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const DBus = imports.dbus;
const Main = imports.ui.main;
const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
@ -11,99 +10,61 @@ const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
const MagnifierIface = <interface name={MAG_SERVICE_NAME}>
<method name="setActive">
<arg type="b" direction="in" />
</method>
<method name="isActive">
<arg type="b" direction="out" />
</method>
<method name="showCursor" />
<method name="hideCursor" />
<method name="createZoomRegion">
<arg type="d" direction="in" />
<arg type="d" direction="in" />
<arg type="ai" direction="in" />
<arg type="ai" direction="in" />
<arg type="o" direction="out" />
</method>
<method name="addZoomRegion">
<arg type="o" direction="in" />
<arg type="b" direction="out" />
</method>
<method name="getZoomRegions">
<arg type="ao" direction="out" />
</method>
<method name="clearAllZoomRegions" />
<method name="fullScreenCapable">
<arg type="b" direction="out" />
</method>
<method name="setCrosswireSize">
<arg type="i" direction="in" />
</method>
<method name="getCrosswireSize">
<arg type="i" direction="out" />
</method>
<method name="setCrosswireLength">
<arg type="i" direction="in" />
</method>
<method name="getCrosswireLength">
<arg type="i" direction="out" />
</method>
<method name="setCrosswireClip">
<arg type="b" direction="in" />
</method>
<method name="getCrosswireClip">
<arg type="b" direction="out" />
</method>
<method name="setCrosswireColor">
<arg type="u" direction="in" />
</method>
<method name="getCrosswireColor">
<arg type="u" direction="out" />
</method>
</interface>;
const MagnifierIface = {
name: MAG_SERVICE_NAME,
methods: [
{ name: 'setActive', inSignature: 'b', outSignature: '' },
{ name: 'isActive', inSignature: '', outSignature: 'b' },
{ name: 'showCursor', inSignature: '', outSignature: '' },
{ name: 'hideCursor', inSignature: '', outSignature: '' },
{ name: 'createZoomRegion', inSignature: 'ddaiai', outSignature: 'o' },
{ name: 'addZoomRegion', inSignature: 'o', outSignature: 'b' },
{ name: 'getZoomRegions', inSignature: '', outSignature: 'ao' },
{ name: 'clearAllZoomRegions', inSignature: '', outSignature: '' },
{ name: 'fullScreenCapable', inSignature: '', outSignature: 'b' },
{ name: 'setCrosswireSize', inSignature: 'i', outSignature: '' },
{ name: 'getCrosswireSize', inSignature: '', outSignature: 'i' },
{ name: 'setCrosswireLength', inSignature: 'i', outSignature: '' },
{ name: 'getCrosswireLength', inSignature: '', outSignature: 'i' },
{ name: 'setCrosswireClip', inSignature: 'b', outSignature: '' },
{ name: 'getCrosswireClip', inSignature: '', outSignature: 'b' },
{ name: 'setCrosswireColor', inSignature: 'u', outSignature: '' },
{ name: 'getCrosswireColor', inSignature: '', outSignature: 'u' }
],
signals: [],
properties: []
};
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
<method name="setMagFactor">
<arg type="d" direction="in" />
<arg type="d" direction="in" />
</method>
<method name="getMagFactor">
<arg type="d" direction="out" />
<arg type="d" direction="out" />
</method>
<method name="setRoi">
<arg type="ai" direction="in" />
</method>
<method name="getRoi">
<arg type="ai" direction="out" />
</method>
<method name="shiftContentsTo">
<arg type="i" direction="in" />
<arg type="i" direction="in" />
<arg type="b" direction="out" />
</method>
<method name="moveResize">
<arg type="ai" direction="in" />
</method>
</interface>;
const ZoomRegionIface = {
name: ZOOM_SERVICE_NAME,
methods: [
{ name: 'setMagFactor', inSignature: 'dd', outSignature: ''},
{ name: 'getMagFactor', inSignature: '', outSignature: 'dd' },
{ name: 'setRoi', inSignature: 'ai', outSignature: '' },
{ name: 'getRoi', inSignature: '', outSignature: 'ai' },
{ name: 'shiftContentsTo', inSignature: 'ii', outSignature: 'b' },
{ name: 'moveResize', inSignature: 'ai', outSignature: '' }
],
signals: [],
properties: []
};
// For making unique ZoomRegion DBus proxy object paths of the form:
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
let _zoomRegionInstanceCount = 0;
const ShellMagnifier = new Lang.Class({
Name: 'ShellMagnifier',
function ShellMagnifier() {
this._init();
}
ShellMagnifier.prototype = {
_init: function() {
this._zoomers = {};
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MagnifierIface, this);
this._dbusImpl.export(Gio.DBus.session, MAG_SERVICE_PATH);
DBus.session.exportObject(MAG_SERVICE_PATH, this);
},
/**
@ -234,10 +195,10 @@ const ShellMagnifier = new Lang.Class({
Main.magnifier.clearAllZoomRegions();
for (let objectPath in this._zoomers) {
let proxyAndZoomer = this._zoomers[objectPath];
proxyAndZoomer.proxy.destroy();
proxyAndZoomer.proxy = null;
proxyAndZoomer.zoomRegion = null;
delete this._zoomers[objectPath];
DBus.session.unexportObject(proxyAndZoomer);
}
this._zoomers = {};
},
@ -324,7 +285,7 @@ const ShellMagnifier = new Lang.Class({
// Drop the leading '#'.
return parseInt(colorString.slice(1), 16);
}
});
};
/**
* ShellMagnifierZoomRegion:
@ -332,14 +293,15 @@ const ShellMagnifier = new Lang.Class({
* @zoomerObjectPath: String that is the path to a DBus ZoomRegion.
* @zoomRegion: The actual zoom region associated with the object path.
*/
const ShellMagnifierZoomRegion = new Lang.Class({
Name: 'ShellMagnifierZoomRegion',
function ShellMagnifierZoomRegion(zoomerObjectPath, zoomRegion) {
this._init(zoomerObjectPath, zoomRegion);
}
ShellMagnifierZoomRegion.prototype = {
_init: function(zoomerObjectPath, zoomRegion) {
this._zoomRegion = zoomRegion;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ZoomRegionIface, this);
this._dbusImpl.export(Gio.DBus.session, zoomerObjectPath);
DBus.session.proxifyObject(this, ZOOM_SERVICE_NAME, zoomerObjectPath);
DBus.session.exportObject(zoomerObjectPath, this);
},
/**
@ -414,9 +376,8 @@ const ShellMagnifierZoomRegion = new Lang.Class({
moveResize: function(viewPort) {
let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
this._zoomRegion.setViewPort(viewRect);
},
destroy: function() {
this._dbusImpl.unexport();
}
});
};
DBus.conformExport(ShellMagnifier.prototype, MagnifierIface);
DBus.conformExport(ShellMagnifierZoomRegion.prototype, ZoomRegionIface);

View File

@ -1,9 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GConf = imports.gi.GConf;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -132,11 +134,15 @@ function _initUserSession() {
ExtensionSystem.init();
ExtensionSystem.loadExtensions();
Meta.keybindings_set_custom_handler('panel-run-dialog', function() {
let shellwm = global.window_manager;
shellwm.takeover_keybinding('panel_run_dialog');
shellwm.connect('keybinding::panel_run_dialog', function () {
getRunDialog().open();
});
Meta.keybindings_set_custom_handler('panel-main-menu', function () {
shellwm.takeover_keybinding('panel_main_menu');
shellwm.connect('keybinding::panel_main_menu', function () {
overview.toggle();
});
@ -157,6 +163,11 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME');
shellDBusService = new ShellDBus.GnomeShell();
// Force a connection now; dbus.js will do this internally
// if we use its name acquisition stuff but we aren't right
// now; to do so we'd need to convert from its async calls
// back into sync ones.
DBus.session.flush();
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem
@ -572,6 +583,16 @@ function _globalKeyPressHandler(actor, event) {
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = global.display.get_keybinding_action(keyCode, modifierState);
// The screenshot action should always be available (even if a
// modal dialog is present)
if (action == Meta.KeyBindingAction.COMMAND_SCREENSHOT) {
let gconf = GConf.Client.get_default();
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
if (command != null && command != '')
Util.spawnCommandLine(command);
return true;
}
// Other bindings are only available to the user session when the overview is up and
// no modal dialog is present.
if (global.session_type == Shell.SessionType.USER && (!overview.visible || modalCount > 1))
@ -647,17 +668,14 @@ function _findModal(actor) {
* initiated event. If not provided then the value of
* global.get_current_time() is assumed.
*
* @options: optional Meta.ModalOptions flags to indicate that the
* pointer is alrady grabbed
*
* Returns: true iff we successfully acquired a grab or already had one
*/
function pushModal(actor, timestamp, options) {
function pushModal(actor, timestamp) {
if (timestamp == undefined)
timestamp = global.get_current_time();
if (modalCount == 0) {
if (!global.begin_modal(timestamp, options ? options : 0)) {
if (!global.begin_modal(timestamp)) {
log('pushModal: invocation of begin_modal failed');
return false;
}

View File

@ -83,9 +83,11 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1);
}
const URLHighlighter = new Lang.Class({
Name: 'URLHighlighter',
function URLHighlighter(text, lineWrap, allowMarkup) {
this._init(text, lineWrap, allowMarkup);
}
URLHighlighter.prototype = {
_init: function(text, lineWrap, allowMarkup) {
if (!text)
text = '';
@ -209,11 +211,13 @@ const URLHighlighter = new Lang.Class({
}
return -1;
}
});
};
const FocusGrabber = new Lang.Class({
Name: 'FocusGrabber',
function FocusGrabber() {
this._init();
}
FocusGrabber.prototype = {
_init: function() {
this.actor = null;
@ -347,7 +351,7 @@ const FocusGrabber = new Lang.Class({
this._togglingFocusGrabMode = false;
}
}
});
}
Signals.addSignalMethods(FocusGrabber.prototype);
// Notification:
@ -404,9 +408,11 @@ Signals.addSignalMethods(FocusGrabber.prototype);
// the content and the action area of the notification will be cleared.
// The content area is also always cleared if 'customContent' is false
// because it might contain the @banner that didn't fit in the banner mode.
const Notification = new Lang.Class({
Name: 'Notification',
function Notification(source, title, banner, params) {
this._init(source, title, banner, params);
}
Notification.prototype = {
IMAGE_SIZE: 125,
_init: function(source, title, banner, params) {
@ -591,7 +597,8 @@ const Notification = new Lang.Class({
this._table.add_style_class_name('multi-line-notification');
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
vscrollbar_policy: this._scrollPolicy,
hscrollbar_policy: Gtk.PolicyType.NEVER });
hscrollbar_policy: Gtk.PolicyType.NEVER,
style_class: 'vfade' });
this._table.add(this._scrollArea, { row: 1,
col: 2 });
this._updateLastColumnSettings();
@ -947,12 +954,14 @@ const Notification = new Lang.Class({
this.actor.destroy();
this.actor._delegate = null;
}
});
};
Signals.addSignalMethods(Notification.prototype);
const Source = new Lang.Class({
Name: 'MessageTraySource',
function Source(title) {
this._init(title);
}
Source.prototype = {
ICON_SIZE: 24,
_init: function(title) {
@ -983,7 +992,6 @@ const Source = new Lang.Class({
this.isTransient = false;
this.isChat = false;
this.isMuted = false;
this.notifications = [];
},
@ -1048,13 +1056,6 @@ const Source = new Lang.Class({
this.emit('title-changed');
},
setMuted: function(muted) {
if (!this.isChat || this.isMuted == muted)
return;
this.isMuted = muted;
this.emit('muted-changed');
},
// Called to create a new icon actor (of size this.ICON_SIZE).
// Must be overridden by the subclass if you do not pass icons
// explicitly to the Notification() constructor.
@ -1093,8 +1094,7 @@ const Source = new Lang.Class({
notify: function(notification) {
this.pushNotification(notification);
if (!this.isMuted)
this.emit('notify', notification);
this.emit('notify', notification);
},
destroy: function(reason) {
@ -1134,12 +1134,14 @@ const Source = new Lang.Class({
_lastNotificationRemoved: function() {
this.destroy();
}
});
};
Signals.addSignalMethods(Source.prototype);
const SummaryItem = new Lang.Class({
Name: 'SummaryItem',
function SummaryItem(source) {
this._init(source);
}
SummaryItem.prototype = {
_init: function(source) {
this.source = source;
this.source.connect('notification-added', Lang.bind(this, this._notificationAddedToSource));
@ -1208,18 +1210,6 @@ const SummaryItem = new Lang.Class({
}));
this.rightClickMenu.add(item.actor);
if (source.isChat) {
item = new PopupMenu.PopupMenuItem('');
item.actor.connect('notify::mapped', Lang.bind(this, function() {
item.label.set_text(source.isMuted ? _("Unmute") : _("Mute"));
}));
item.connect('activate', Lang.bind(this, function() {
source.setMuted(!source.isMuted);
this.emit('done-displaying-content');
}));
this.rightClickMenu.add(item.actor);
}
let focusManager = St.FocusManager.get_for_stage(global.stage);
focusManager.add_group(this.rightClickMenu);
},
@ -1330,22 +1320,21 @@ const SummaryItem = new Lang.Class({
if (this.notificationStack.get_children().length > 0)
this.notificationStack.get_children()[0]._delegate.setIconVisible(true);
}
});
};
Signals.addSignalMethods(SummaryItem.prototype);
const MessageTray = new Lang.Class({
Name: 'MessageTray',
function MessageTray() {
this._init();
}
MessageTray.prototype = {
_init: function() {
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
this._onStatusChanged(proxy.status);
}));
this._presence = new GnomeSession.Presence();
this._userStatus = GnomeSession.PresenceStatus.AVAILABLE;
this._busy = false;
this._backFromAway = false;
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
this._onStatusChanged(status);
}));
this._presence.connect('StatusChanged', Lang.bind(this, this._onStatusChanged));
this._presence.getStatus(Lang.bind(this, this._onStatusChanged));
this.actor = new St.Group({ name: 'message-tray',
reactive: true,
@ -1549,14 +1538,6 @@ const MessageTray = new Lang.Class({
source.connect('notify', Lang.bind(this, this._onNotify));
source.connect('muted-changed', Lang.bind(this,
function () {
if (source.isMuted)
this._notificationQueue = this._notificationQueue.filter(function(notification) {
return source != notification.source;
});
}));
summaryItem.actor.connect('notify::hover', Lang.bind(this,
function () {
this._onSummaryItemHoverChanged(summaryItem);
@ -1913,7 +1894,7 @@ const MessageTray = new Lang.Class({
this._updateState();
},
_onStatusChanged: function(status) {
_onStatusChanged: function(presence, status) {
this._backFromAway = (this._userStatus == GnomeSession.PresenceStatus.IDLE && this._userStatus != status);
this._userStatus = status;
@ -2434,14 +2415,17 @@ const MessageTray = new Lang.Class({
if (this._clickedSummaryItem)
this._updateState();
}
});
};
const SystemNotificationSource = new Lang.Class({
Name: 'SystemNotificationSource',
Extends: Source,
function SystemNotificationSource() {
this._init();
}
SystemNotificationSource.prototype = {
__proto__: Source.prototype,
_init: function() {
this.parent(_("System Information"));
Source.prototype._init.call(this, _("System Information"));
this._setSummaryIcon(this.createNotificationIcon());
},
@ -2455,4 +2439,4 @@ const SystemNotificationSource = new Lang.Class({
open: function() {
this.destroy();
}
});
};

View File

@ -29,9 +29,11 @@ const State = {
FADED_OUT: 4
};
const ModalDialog = new Lang.Class({
Name: 'ModalDialog',
function ModalDialog() {
this._init();
}
ModalDialog.prototype = {
_init: function(params) {
params = Params.parse(params, { shellReactive: false,
styleClass: null });
@ -108,7 +110,7 @@ const ModalDialog = new Lang.Class({
this._buttonLayout.destroy_children();
this._actionKeys = {};
for (let i = 0; i < buttons.length; i++) {
for (let i = 0; i < buttons.length; i ++) {
let buttonInfo = buttons[i];
let label = buttonInfo['label'];
let action = buttonInfo['action'];
@ -301,5 +303,5 @@ const ModalDialog = new Lang.Class({
})
});
}
});
};
Signals.addSignalMethods(ModalDialog.prototype);

View File

@ -32,12 +32,15 @@ const ModalDialog = imports.ui.modalDialog;
const PopupMenu = imports.ui.popupMenu;
const ShellEntry = imports.ui.shellEntry;
const NetworkSecretDialog = new Lang.Class({
Name: 'NetworkSecretDialog',
Extends: ModalDialog.ModalDialog,
function NetworkSecretDialog() {
this._init.apply(this, arguments);
}
NetworkSecretDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(agent, requestId, connection, settingName, hints) {
this.parent({ styleClass: 'polkit-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'polkit-dialog' });
this._agent = agent;
this._requestId = requestId;
@ -355,11 +358,13 @@ const NetworkSecretDialog = new Lang.Class({
return content;
}
});
};
const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent',
function NetworkAgent() {
this._init.apply(this, arguments);
}
NetworkAgent.prototype = {
_init: function() {
this._native = new Shell.NetworkAgent({ auto_register: true,
identifier: 'org.gnome.Shell.NetworkAgent' });
@ -382,4 +387,4 @@ const NetworkAgent = new Lang.Class({
this._dialogs[requestId].close(global.get_current_time());
this._dialogs[requestId].destroy();
}
});
};

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
@ -16,52 +16,49 @@ const Util = imports.misc.util;
let nextNotificationId = 1;
// Should really be defined in Gio.js
const BusIface = <interface name="org.freedesktop.DBus">
<method name="GetConnectionUnixProcessID">
<arg type="s" direction="in" />
<arg type="u" direction="out" />
</method>
</interface>;
// Should really be defined in dbus.js
const BusIface = {
name: 'org.freedesktop.DBus',
methods: [{ name: 'GetConnectionUnixProcessID',
inSignature: 's',
outSignature: 'i' }]
};
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
function Bus() {
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
const Bus = function () {
this._init();
};
const NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
<method name="Notify">
<arg type="s" direction="in"/>
<arg type="u" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="as" direction="in"/>
<arg type="a{sv}" direction="in"/>
<arg type="i" direction="in"/>
<arg type="u" direction="out"/>
</method>
<method name="CloseNotification">
<arg type="u" direction="in"/>
</method>
<method name="GetCapabilities">
<arg type="as" direction="out"/>
</method>
<method name="GetServerInformation">
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
</method>
<signal name="NotificationClosed">
<arg type="u"/>
<arg type="u"/>
</signal>
<signal name="ActionInvoked">
<arg type="u"/>
<arg type="s"/>
</signal>
</interface>;
Bus.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
};
DBus.proxifyPrototype(Bus.prototype, BusIface);
const NotificationDaemonIface = {
name: 'org.freedesktop.Notifications',
methods: [{ name: 'Notify',
inSignature: 'susssasa{sv}i',
outSignature: 'u'
},
{ name: 'CloseNotification',
inSignature: 'u',
outSignature: ''
},
{ name: 'GetCapabilities',
inSignature: '',
outSignature: 'as'
},
{ name: 'GetServerInformation',
inSignature: '',
outSignature: 'ssss'
}],
signals: [{ name: 'NotificationClosed',
inSignature: 'uu' },
{ name: 'ActionInvoked',
inSignature: 'us' }]
};
const NotificationClosedReason = {
EXPIRED: 1,
@ -87,12 +84,13 @@ const rewriteRules = {
]
};
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
function NotificationDaemon() {
this._init();
}
NotificationDaemon.prototype = {
_init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
DBus.session.exportObject('/org/freedesktop/Notifications', this);
this._sources = [];
this._senderToPid = {};
@ -217,8 +215,8 @@ const NotificationDaemon = new Lang.Class({
return source;
},
NotifyAsync: function(params, invocation) {
let [appName, replacesId, icon, summary, body, actions, hints, timeout] = params;
Notify: function(appName, replacesId, icon, summary, body,
actions, hints, timeout) {
let id;
// Filter out chat, presence, calls and invitation notifications from
@ -237,7 +235,7 @@ const NotificationDaemon = new Lang.Class({
function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
}));
return invocation.return_value(GLib.Variant.new('(u)', [id]));
return id;
}
let rewrites = rewriteRules[appName];
@ -249,11 +247,6 @@ const NotificationDaemon = new Lang.Class({
}
}
for (let hint in hints) {
// unpack the variants
hints[hint] = hints[hint].deep_unpack();
}
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
// Be compatible with the various hints for image data and image path
@ -285,55 +278,51 @@ const NotificationDaemon = new Lang.Class({
}
this._notifications[id] = ndata;
let sender = invocation.get_sender();
let sender = DBus.getCurrentMessageContext().sender;
let pid = this._senderToPid[sender];
let source = this._getSource(appName, pid, ndata, sender, null);
if (source) {
this._notifyForSource(source, ndata);
return invocation.return_value(GLib.Variant.new('(u)', [id]));
return id;
}
if (replacesId) {
// There's already a pending call to GetConnectionUnixProcessID,
// which will see the new notification data when it finishes,
// so we don't have to do anything.
return invocation.return_value(GLib.Variant.new('(u)', [id]));;
return id;
}
this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this, function (result, excp) {
// The app may have updated or removed the notification
ndata = this._notifications[id];
if (!ndata)
return;
this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this,
function (pid, ex) {
// The app may have updated or removed the notification
ndata = this._notifications[id];
if (!ndata)
return;
if (excp) {
logError(excp, 'Call to GetConnectionUnixProcessID failed');
return;
}
source = this._getSource(appName, pid, ndata, sender, null);
let [pid] = result;
source = this._getSource(appName, pid, ndata, sender, null);
// We only store sender-pid entries for persistent sources.
// Removing the entries once the source is destroyed
// would result in the entries associated with transient
// sources removed once the notification is shown anyway.
// However, keeping these pairs would mean that we would
// possibly remove an entry associated with a persistent
// source when a transient source for the same sender is
// distroyed.
if (!source.isTransient) {
this._senderToPid[sender] = pid;
source.connect('destroy', Lang.bind(this,
function() {
delete this._senderToPid[sender];
}));
}
this._notifyForSource(source, ndata);
}));
// We only store sender-pid entries for persistent sources.
// Removing the entries once the source is destroyed
// would result in the entries associated with transient
// sources removed once the notification is shown anyway.
// However, keeping these pairs would mean that we would
// possibly remove an entry associated with a persistent
// source when a transient source for the same sender is
// distroyed.
if (!source.isTransient) {
this._senderToPid[sender] = pid;
source.connect('destroy', Lang.bind(this, function() {
delete this._senderToPid[sender];
}));
}
this._notifyForSource(source, ndata);
}));
return invocation.return_value(GLib.Variant.new('(u)', [id]));
return id;
},
_notifyForSource: function(source, ndata) {
@ -473,13 +462,17 @@ const NotificationDaemon = new Lang.Class({
},
_emitNotificationClosed: function(id, reason) {
this._dbusImpl.emit_signal('NotificationClosed',
GLib.Variant.new('(uu)', [id, reason]));
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'NotificationClosed', 'uu',
[id, reason]);
},
_emitActionInvoked: function(id, action) {
this._dbusImpl.emit_signal('ActionInvoked',
GLib.Variant.new('(us)', [id, action]));
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'ActionInvoked', 'us',
[id, action]);
},
_onTrayIconAdded: function(o, icon) {
@ -491,25 +484,33 @@ const NotificationDaemon = new Lang.Class({
if (source)
source.destroy();
}
});
};
const Source = new Lang.Class({
Name: 'NotificationDaemonSource',
Extends: MessageTray.Source,
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
function Source(title, pid, sender) {
this._init(title, pid, sender);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(title, pid, sender, trayIcon) {
this.parent(title);
MessageTray.Source.prototype._init.call(this, title);
this.initialTitle = title;
this.pid = pid;
if (sender)
this._nameWatcherId = Gio.DBus.session.watch_name(sender,
Gio.BusNameWatcherFlags.NONE,
null,
Lang.bind(this, this._onNameVanished));
else
this._nameWatcherId = 0;
// TODO: dbus-glib implementation of watch_name() doesnt return an id to be used for
// unwatch_name() or implement unwatch_name(), however when we move to using GDBus implementation,
// we should save the id here and call unwatch_name() with it in destroy().
// Moving to GDBus is the work in progress: https://bugzilla.gnome.org/show_bug.cgi?id=648651
// and https://bugzilla.gnome.org/show_bug.cgi?id=622921 .
DBus.session.watch_name(sender,
false,
null,
Lang.bind(this, this._onNameVanished));
this._setApp();
if (this.app)
@ -616,11 +617,6 @@ const Source = new Lang.Class({
},
destroy: function() {
if (this._nameWatcherId) {
Gio.DBus.session.unwatch_name(this._nameWatcherId);
this._nameWatcherId = 0;
}
this.parent();
MessageTray.Source.prototype.destroy.call(this);
}
});
};

View File

@ -23,7 +23,6 @@ const Params = imports.misc.params;
const PlaceDisplay = imports.ui.placeDisplay;
const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector;
const Wanda = imports.ui.wanda;
const WorkspacesView = imports.ui.workspacesView;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
@ -47,9 +46,11 @@ const SwipeScrollResult = {
CLICK: 2
};
const ShellInfo = new Lang.Class({
Name: 'ShellInfo',
function ShellInfo() {
this._init();
}
ShellInfo.prototype = {
_init: function() {
this._source = null;
this._undoCallback = null;
@ -94,11 +95,13 @@ const ShellInfo = new Lang.Class({
this._source.notify(notification);
}
});
};
const Overview = new Lang.Class({
Name: 'Overview',
function Overview() {
this._init.apply(this, arguments);
}
Overview.prototype = {
_init : function(params) {
params = Params.parse(params, { isDummy: false });
@ -109,6 +112,7 @@ const Overview = new Lang.Class({
if (this.isDummy) {
this.animationInProgress = false;
this.visible = false;
this.workspaces = null;
return;
}
@ -180,6 +184,8 @@ const Overview = new Lang.Class({
this._lastActiveWorkspaceIndex = -1;
this._lastHoveredWindow = null;
this._needsFakePointerEvent = false;
this.workspaces = null;
},
// The members we construct that are implemented in JS might
@ -202,8 +208,6 @@ const Overview = new Lang.Class({
this._viewSelector.addViewTab('applications', _("Applications"), appView.actor, 'system-run');
// Default search providers
// Wanda comes obviously first
this.addSearchProvider(new Wanda.WandaSearchProvider());
this.addSearchProvider(new AppDisplay.AppSearchProvider());
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
@ -587,10 +591,13 @@ const Overview = new Lang.Class({
this._workspacesDisplay.show();
this.workspaces = this._workspacesDisplay.workspacesView;
global.overlay_group.add_actor(this.workspaces.actor);
if (!this._desktopFade.child)
this._desktopFade.child = this._getDesktopClone();
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) {
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
this._desktopFade.opacity = 255;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
@ -725,7 +732,7 @@ const Overview = new Lang.Class({
this.animationInProgress = true;
this._hideInProgress = true;
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) {
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
this._desktopFade.opacity = 0;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
@ -734,7 +741,7 @@ const Overview = new Lang.Class({
transition: 'easeOutQuad' });
}
this._workspacesDisplay.zoomFromOverview();
this.workspaces.hide();
// Make other elements fade out.
Tweener.addTween(this._group,
@ -776,6 +783,9 @@ const Overview = new Lang.Class({
global.window_group.show();
this.workspaces.destroy();
this.workspaces = null;
this._workspacesDisplay.hide();
this._desktopFade.hide();
@ -801,5 +811,5 @@ const Overview = new Lang.Class({
this._needsFakePointerEvent = false;
}
}
});
};
Signals.addSignalMethods(Overview.prototype);

View File

@ -3,7 +3,6 @@
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
@ -99,9 +98,11 @@ function _unpremultiply(color) {
};
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
function AnimatedIcon(name, size) {
this._init(name, size);
}
AnimatedIcon.prototype = {
_init: function(name, size) {
this.actor = new St.Bin({ visible: false });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
@ -138,11 +139,13 @@ const AnimatedIcon = new Lang.Class({
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
}
});
};
const TextShadower = new Lang.Class({
Name: 'TextShadower',
function TextShadower() {
this._init();
}
TextShadower.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -222,7 +225,7 @@ const TextShadower = new Lang.Class({
child.allocate(childBox, flags);
}
}
});
};
/**
* AppMenuButton:
@ -232,19 +235,18 @@ const TextShadower = new Lang.Class({
* this menu also handles startup notification for it. So when we
* have an active startup notification, we switch modes to display that.
*/
const AppMenuButton = new Lang.Class({
Name: 'AppMenuButton',
Extends: PanelMenu.Button,
function AppMenuButton() {
this._init();
}
_init: function(menuManager) {
this.parent(0.0, true);
AppMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
PanelMenu.Button.prototype._init.call(this, 0.0);
this._startingApps = [];
this._menuManager = menuManager;
this._targetApp = null;
this._appMenuNotifyId = 0;
this._actionGroupNotifyId = 0;
let bin = new St.Bin({ name: 'appMenu' });
this.actor.add_actor(bin);
@ -269,6 +271,10 @@ const AppMenuButton = new Lang.Class({
this._iconBottomClip = 0;
this._quitMenu = new PopupMenu.PopupMenuItem('');
this.menu.addMenuItem(this._quitMenu);
this._quitMenu.connect('activate', Lang.bind(this, this._onQuit));
this._visible = !Main.overview.visible;
if (!this._visible)
this.actor.hide();
@ -447,6 +453,12 @@ const AppMenuButton = new Lang.Class({
}
},
_onQuit: function() {
if (this._targetApp == null)
return;
this._targetApp.request_quit();
},
_onAppStateChanged: function(appSys, app) {
let state = app.state;
if (state != Shell.AppState.STARTING) {
@ -508,10 +520,8 @@ const AppMenuButton = new Lang.Class({
}
if (targetApp == this._targetApp) {
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING) {
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING)
this.stopAnimation();
this._maybeSetMenu();
}
return;
}
@ -521,67 +531,37 @@ const AppMenuButton = new Lang.Class({
this._iconBox.hide();
this._label.setText('');
if (this._appMenuNotifyId)
this._targetApp.disconnect(this._appMenuNotifyId);
if (this._actionGroupNotifyId)
this._targetApp.disconnect(this._actionGroupNotifyId);
if (targetApp) {
this._appMenuNotifyId = targetApp.connect('notify::menu', Lang.bind(this, this._sync));
this._actionGroupNotifyId = targetApp.connect('notify::action-group', Lang.bind(this, this._sync));
}
this._targetApp = targetApp;
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
this._label.setText(targetApp.get_name());
// TODO - _quit() doesn't really work on apps in state STARTING yet
this._quitMenu.label.set_text(_("Quit %s").format(targetApp.get_name()));
this._iconBox.set_child(icon);
this._iconBox.show();
if (targetApp.get_state() == Shell.AppState.STARTING)
this.startAnimation();
else
this._maybeSetMenu();
this.emit('changed');
},
_maybeSetMenu: function() {
let menu;
if (this._targetApp.action_group) {
if (this.menu instanceof PopupMenu.RemoteMenu &&
this.menu.actionGroup == this._targetApp.action_group)
return;
menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
} else {
if (this.menu && !(this.menu instanceof PopupMenu.RemoteMenu))
return;
// fallback to older menu
menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
menu.addAction(_("Quit"), Lang.bind(this, function() {
this._targetApp.request_quit();
}));
}
this.setMenu(menu);
this._menuManager.addMenu(menu);
}
});
};
Signals.addSignalMethods(AppMenuButton.prototype);
// Activities button. Because everything else in the top bar is a
// PanelMenu.Button, it simplifies some things to make this be one too.
// We just hack it up to not actually have a menu attached to it.
const ActivitiesButton = new Lang.Class({
Name: 'ActivitiesButton',
Extends: PanelMenu.Button,
function ActivitiesButton() {
this._init.apply(this, arguments);
}
ActivitiesButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
this.parent(0.0);
PanelMenu.Button.prototype._init.call(this, 0.0);
let container = new Shell.GenericContainer();
container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
@ -718,11 +698,13 @@ const ActivitiesButton = new Lang.Class({
Mainloop.source_remove(this._xdndTimeOut);
this._xdndTimeOut = 0;
}
});
};
const PanelCorner = new Lang.Class({
Name: 'PanelCorner',
function PanelCorner(panel, side) {
this._init(panel, side);
}
PanelCorner.prototype = {
_init: function(box, side) {
this._side = side;
@ -898,12 +880,14 @@ const PanelCorner = new Lang.Class({
this.actor.set_size(cornerRadius, innerBorderWidth + cornerRadius);
this.actor.set_anchor_point(0, innerBorderWidth);
}
});
};
const Panel = new Lang.Class({
Name: 'Panel',
function Panel() {
this._init();
}
Panel.prototype = {
_init : function() {
this.actor = new Shell.GenericContainer({ name: 'panel',
reactive: true });
@ -954,8 +938,9 @@ const Panel = new Lang.Class({
// more cleanly with the rest of the panel
this._menus.addMenu(this._activitiesButton.menu);
this._appMenu = new AppMenuButton(this._menus);
this._appMenu = new AppMenuButton();
this._leftBox.add(this._appMenu.actor);
this._menus.addMenu(this._appMenu.menu);
}
/* center */
@ -1129,4 +1114,5 @@ const Panel = new Lang.Class({
if (box && box._delegate instanceof PanelMenu.ButtonBox)
box.destroy();
},
});
};

View File

@ -11,9 +11,11 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const ButtonBox = new Lang.Class({
Name: 'ButtonBox',
function ButtonBox(params) {
this._init.apply(this, arguments);
};
ButtonBox.prototype = {
_init: function(params) {
params = Params.parse(params, { style_class: 'panel-button' }, true);
this.actor = new Shell.GenericContainer(params);
@ -90,45 +92,31 @@ const ButtonBox = new Lang.Class({
child.allocate(childBox, flags);
},
});
}
const Button = new Lang.Class({
Name: 'PanelMenuButton',
Extends: ButtonBox,
function Button(menuAlignment) {
this._init(menuAlignment);
}
_init: function(menuAlignment, dontCreateMenu) {
this.parent({ reactive: true,
can_focus: true,
track_hover: true });
Button.prototype = {
__proto__: ButtonBox.prototype,
_init: function(menuAlignment) {
ButtonBox.prototype._init.call(this, { reactive: true,
can_focus: true,
track_hover: true });
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
if (dontCreateMenu)
this.menu = null;
else
this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));
},
setMenu: function(menu) {
if (this.menu)
this.menu.destroy();
this.menu = menu;
if (this.menu) {
this.menu.actor.add_style_class_name('panel-menu');
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
Main.uiGroup.add_actor(this.menu.actor);
this.menu.actor.hide();
}
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
this.menu.actor.add_style_class_name('panel-menu');
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
Main.uiGroup.add_actor(this.menu.actor);
this.menu.actor.hide();
},
_onButtonPress: function(actor, event) {
if (!this.menu)
return;
if (!this.menu.isOpen) {
// Setting the max-height won't do any good if the minimum height of the
// menu is higher then the screen; it's useful if part of the menu is
@ -142,9 +130,6 @@ const Button = new Lang.Class({
},
_onSourceKeyPress: function(actor, event) {
if (!this.menu)
return false;
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.menu.toggle();
@ -190,7 +175,7 @@ const Button = new Lang.Class({
this.emit('destroy');
}
});
};
Signals.addSignalMethods(Button.prototype);
/* SystemStatusButton:
@ -199,13 +184,15 @@ Signals.addSignalMethods(Button.prototype);
* volume, bluetooth...), which is just a PanelMenuButton with an
* icon and a tooltip
*/
const SystemStatusButton = new Lang.Class({
Name: 'SystemStatusButton',
Extends: Button,
function SystemStatusButton() {
this._init.apply(this, arguments);
}
SystemStatusButton.prototype = {
__proto__: Button.prototype,
_init: function(iconName,tooltipText) {
this.parent(0.0);
Button.prototype._init.call(this, 0.0);
this._iconActor = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
@ -232,4 +219,4 @@ const SystemStatusButton = new Lang.Class({
this.tooltip = null;
}
}
});
};

View File

@ -22,9 +22,11 @@ const Util = imports.misc.util;
* @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
* @launch: A JavaScript callback to launch the entry
*/
const PlaceInfo = new Lang.Class({
Name: 'PlaceInfo',
function PlaceInfo(id, name, iconFactory, launch) {
this._init(id, name, iconFactory, launch);
}
PlaceInfo.prototype = {
_init: function(id, name, iconFactory, launch) {
this.id = id;
this.name = name;
@ -53,7 +55,7 @@ const PlaceInfo = new Lang.Class({
isRemovable: function() {
return false;
}
});
};
// Helper function to translate launch parameters into a GAppLaunchContext
function _makeLaunchContext(params)
@ -70,9 +72,12 @@ function _makeLaunchContext(params)
return launchContext;
}
const PlaceDeviceInfo = new Lang.Class({
Name: 'PlaceDeviceInfo',
Extends: PlaceInfo,
function PlaceDeviceInfo(mount) {
this._init(mount);
}
PlaceDeviceInfo.prototype = {
__proto__: PlaceInfo.prototype,
_init: function(mount) {
this._mount = mount;
@ -118,11 +123,13 @@ const PlaceDeviceInfo = new Lang.Class({
_("Retry"));
}
}
});
};
const PlacesManager = new Lang.Class({
Name: 'PlacesManager',
function PlacesManager() {
this._init();
}
PlacesManager.prototype = {
_init: function() {
this._defaultPlaces = [];
this._mounts = [];
@ -188,9 +195,9 @@ const PlacesManager = new Lang.Class({
this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']);
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
this._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
this._bookmarkTimeoutId = 0;
this._monitor.connect('changed', Lang.bind(this, function () {
monitor.connect('changed', Lang.bind(this, function () {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
@ -353,15 +360,19 @@ const PlacesManager = new Lang.Class({
_removeById: function(sourceArray, id) {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
}
});
};
Signals.addSignalMethods(PlacesManager.prototype);
const PlaceSearchProvider = new Lang.Class({
Name: 'PlaceSearchProvider',
Extends: Search.SearchProvider,
function PlaceSearchProvider() {
this._init();
}
PlaceSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
this.parent(_("PLACES & DEVICES"));
Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
},
getResultMeta: function(resultId) {
@ -423,4 +434,4 @@ const PlaceSearchProvider = new Lang.Class({
let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
return this._searchPlaces(places, terms);
}
});
};

View File

@ -27,7 +27,6 @@ const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Polkit = imports.gi.Polkit;
@ -36,12 +35,15 @@ const PolkitAgent = imports.gi.PolkitAgent;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
Extends: ModalDialog.ModalDialog,
function AuthenticationDialog(actionId, message, cookie, userNames) {
this._init(actionId, message, cookie, userNames);
}
AuthenticationDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(actionId, message, cookie, userNames) {
this.parent({ styleClass: 'polkit-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'polkit-dialog' });
this.actionId = actionId;
this.message = message;
@ -86,14 +88,10 @@ const AuthenticationDialog = new Lang.Class({
if (userNames.length > 1) {
log('polkitAuthenticationAgent: Received ' + userNames.length +
' identities that can be used for authentication. Only ' +
'considering one.');
'considering the first one.');
}
let userName = GLib.get_user_name();
if (userNames.indexOf(userName) < 0)
userName = 'root';
if (userNames.indexOf(userName) < 0)
userName = userNames[0];
let userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name()
@ -332,12 +330,15 @@ const AuthenticationDialog = new Lang.Class({
this.close(global.get_current_time());
this._emitDone(false, true);
},
});
};
Signals.addSignalMethods(AuthenticationDialog.prototype);
const AuthenticationAgent = new Lang.Class({
Name: 'AuthenticationAgent',
function AuthenticationAgent() {
this._init();
}
AuthenticationAgent.prototype = {
_init: function() {
this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', Lang.bind(this, this._onInitiate));
@ -398,7 +399,7 @@ const AuthenticationAgent = new Lang.Class({
this._reallyCompleteRequest(wasDismissed);
}
}
});
}
function init() {
let agent = new AuthenticationAgent();

View File

@ -2,9 +2,7 @@
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
@ -28,9 +26,11 @@ function _ensureStyle(actor) {
actor.ensure_style();
}
const PopupBaseMenuItem = new Lang.Class({
Name: 'PopupBaseMenuItem',
function PopupBaseMenuItem(params) {
this._init(params);
}
PopupBaseMenuItem.prototype = {
_init: function (params) {
params = Params.parse (params, { reactive: true,
activate: true,
@ -108,16 +108,14 @@ const PopupBaseMenuItem = new Lang.Class({
this.emit('activate', event);
},
setActive: function (active, params) {
setActive: function (active) {
let activeChanged = active != this.active;
params = Params.parse (params, { grabKeyboard: true });
if (activeChanged) {
this.active = active;
if (active) {
this.actor.add_style_pseudo_class('active');
if (params.grabKeyboard)
this.actor.grab_key_focus();
this.actor.grab_key_focus();
} else
this.actor.remove_style_pseudo_class('active');
this.emit('active-changed', active);
@ -377,27 +375,33 @@ const PopupBaseMenuItem = new Lang.Class({
x -= availWidth + this._spacing;
}
}
});
};
Signals.addSignalMethods(PopupBaseMenuItem.prototype);
const PopupMenuItem = new Lang.Class({
Name: 'PopupMenuItem',
Extends: PopupBaseMenuItem,
function PopupMenuItem() {
this._init.apply(this, arguments);
}
PopupMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function (text, params) {
this.parent(params);
PopupBaseMenuItem.prototype._init.call(this, params);
this.label = new St.Label({ text: text });
this.addActor(this.label);
}
});
};
const PopupSeparatorMenuItem = new Lang.Class({
Name: 'PopupSeparatorMenuItem',
Extends: PopupBaseMenuItem,
function PopupSeparatorMenuItem() {
this._init();
}
PopupSeparatorMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function () {
this.parent({ reactive: false });
PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
this.addActor(this._drawingArea, { span: -1, expand: true });
@ -423,19 +427,22 @@ const PopupSeparatorMenuItem = new Lang.Class({
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
cr.fill();
}
});
};
const PopupAlternatingMenuItemState = {
DEFAULT: 0,
ALTERNATIVE: 1
}
const PopupAlternatingMenuItem = new Lang.Class({
Name: 'PopupAlternatingMenuItem',
Extends: PopupBaseMenuItem,
function PopupAlternatingMenuItem() {
this._init.apply(this, arguments);
}
PopupAlternatingMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(text, alternateText, params) {
this.parent(params);
PopupBaseMenuItem.prototype._init.call(this, params);
this.actor.add_style_class_name('popup-alternating-menu-item');
this._text = text;
@ -521,14 +528,17 @@ const PopupAlternatingMenuItem = new Lang.Class({
this._updateLabel();
}
});
};
const PopupSliderMenuItem = new Lang.Class({
Name: 'PopupSliderMenuItem',
Extends: PopupBaseMenuItem,
function PopupSliderMenuItem() {
this._init.apply(this, arguments);
}
PopupSliderMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(value) {
this.parent({ activate: false });
PopupBaseMenuItem.prototype._init.call(this, { activate: false });
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
@ -704,11 +714,13 @@ const PopupSliderMenuItem = new Lang.Class({
}
return false;
}
});
};
const Switch = new Lang.Class({
Name: 'Switch',
function Switch() {
this._init.apply(this, arguments);
}
Switch.prototype = {
_init: function(state) {
this.actor = new St.Bin({ style_class: 'toggle-switch' });
// Translators: this MUST be either "toggle-switch-us"
@ -731,14 +743,17 @@ const Switch = new Lang.Class({
toggle: function() {
this.setToggleState(!this.state);
}
});
};
const PopupSwitchMenuItem = new Lang.Class({
Name: 'PopupSwitchMenuItem',
Extends: PopupBaseMenuItem,
function PopupSwitchMenuItem() {
this._init.apply(this, arguments);
}
PopupSwitchMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(text, active, params) {
this.parent(params);
PopupBaseMenuItem.prototype._init.call(this, params);
this.label = new St.Label({ text: text });
this._switch = new Switch(active);
@ -773,7 +788,7 @@ const PopupSwitchMenuItem = new Lang.Class({
this.toggle();
}
this.parent(event);
PopupBaseMenuItem.prototype.activate.call(this, event);
},
toggle: function() {
@ -788,14 +803,17 @@ const PopupSwitchMenuItem = new Lang.Class({
setToggleState: function(state) {
this._switch.setToggleState(state);
}
});
};
const PopupImageMenuItem = new Lang.Class({
Name: 'PopupImageMenuItem',
Extends: PopupBaseMenuItem,
function PopupImageMenuItem() {
this._init.apply(this, arguments);
}
PopupImageMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function (text, iconName, params) {
this.parent(params);
PopupBaseMenuItem.prototype._init.call(this, params);
this.label = new St.Label({ text: text });
this.addActor(this.label);
@ -808,12 +826,13 @@ const PopupImageMenuItem = new Lang.Class({
setIcon: function(name) {
this._icon.icon_name = name;
}
});
};
const PopupMenuBase = new Lang.Class({
Name: 'PopupMenuBase',
Abstract: true,
function PopupMenuBase() {
throw new TypeError('Trying to instantiate abstract class PopupMenuBase');
}
PopupMenuBase.prototype = {
_init: function(sourceActor, styleClass) {
this.sourceActor = sourceActor;
@ -939,12 +958,7 @@ const PopupMenuBase = new Lang.Class({
this.emit('activate', menuItem);
this.close(true);
}));
// the weird name is to avoid a conflict with some random property
// the menuItem may have, called destroyId
// (FIXME: in the future it may make sense to have container objects
// like PopupMenuManager does)
menuItem._popupMenuDestroyId = menuItem.connect('destroy', Lang.bind(this, function(menuItem) {
menuItem.disconnect(menuItem._popupMenuDestroyId);
menuItem.connect('destroy', Lang.bind(this, function(emitter) {
menuItem.disconnect(menuItem._activateId);
menuItem.disconnect(menuItem._activeChangeId);
menuItem.disconnect(menuItem._sensitiveChangeId);
@ -1005,11 +1019,6 @@ const PopupMenuBase = new Lang.Class({
}
if (menuItem instanceof PopupMenuSection) {
this._connectSubMenuSignals(menuItem, menuItem);
menuItem._closingId = this.connect('open-state-changed',
function(self, open) {
if (!open)
menuItem.close(false);
});
menuItem.connect('destroy', Lang.bind(this, function() {
menuItem.disconnect(menuItem._subMenuActivateId);
menuItem.disconnect(menuItem._subMenuActiveChangeId);
@ -1123,15 +1132,18 @@ const PopupMenuBase = new Lang.Class({
this.emit('destroy');
}
});
};
Signals.addSignalMethods(PopupMenuBase.prototype);
const PopupMenu = new Lang.Class({
Name: 'PopupMenu',
Extends: PopupMenuBase,
function PopupMenu() {
this._init.apply(this, arguments);
}
PopupMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor, arrowAlignment, arrowSide) {
this.parent(sourceActor, 'popup-menu-content');
PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content');
this._arrowAlignment = arrowAlignment;
this._arrowSide = arrowSide;
@ -1216,14 +1228,17 @@ const PopupMenu = new Lang.Class({
this.isOpen = false;
this.emit('open-state-changed', false);
}
});
};
const PopupSubMenu = new Lang.Class({
Name: 'PopupSubMenu',
Extends: PopupMenuBase,
function PopupSubMenu() {
this._init.apply(this, arguments);
}
PopupSubMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor, sourceArrow) {
this.parent(sourceActor);
PopupMenuBase.prototype._init.call(this, sourceActor);
this._arrow = sourceArrow;
this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER;
@ -1378,7 +1393,7 @@ const PopupSubMenu = new Lang.Class({
return false;
}
});
};
/**
* PopupMenuSection:
@ -1388,30 +1403,35 @@ const PopupSubMenu = new Lang.Class({
* can add it to another menu), but is completely transparent
* to the user
*/
const PopupMenuSection = new Lang.Class({
Name: 'PopupMenuSection',
Extends: PopupMenuBase,
function PopupMenuSection() {
this._init.apply(this, arguments);
}
PopupMenuSection.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function() {
this.parent();
PopupMenuBase.prototype._init.call(this);
this.actor = this.box;
this.actor._delegate = this;
this.isOpen = true;
},
// deliberately ignore any attempt to open() or close(), but emit the
// corresponding signal so children can still pick it up
open: function(animate) { this.emit('open-state-changed', true); },
close: function() { this.emit('open-state-changed', false); },
});
// deliberately ignore any attempt to open() or close()
open: function(animate) { },
close: function() { },
}
const PopupSubMenuMenuItem = new Lang.Class({
Name: 'PopupSubMenuMenuItem',
Extends: PopupBaseMenuItem,
function PopupSubMenuMenuItem() {
this._init.apply(this, arguments);
}
PopupSubMenuMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(text) {
this.parent();
PopupBaseMenuItem.prototype._init.call(this);
this.actor.add_style_class_name('popup-submenu-menu-item');
@ -1433,8 +1453,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
destroy: function() {
this.menu.destroy();
this.parent();
PopupBaseMenuItem.prototype.destroy.call(this);
},
_onKeyPressEvent: function(actor, event) {
@ -1449,7 +1468,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
return true;
}
return this.parent(actor, event);
return PopupBaseMenuItem.prototype._onKeyPressEvent.call(this, actor, event);
},
activate: function(event) {
@ -1459,21 +1478,22 @@ const PopupSubMenuMenuItem = new Lang.Class({
_onButtonReleaseEvent: function(actor) {
this.menu.toggle();
}
});
};
const PopupComboMenu = new Lang.Class({
Name: 'PopupComboMenu',
Extends: PopupMenuBase,
function PopupComboMenu() {
this._init.apply(this, arguments);
}
PopupComboMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor) {
this.parent(sourceActor, 'popup-combo-menu');
PopupMenuBase.prototype._init.call(this,
sourceActor, 'popup-combo-menu');
this.actor = this.box;
this.actor._delegate = this;
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
sourceActor.connect('style-changed',
Lang.bind(this, this._onSourceActorStyleChanged));
this._activeItemPos = -1;
global.focus_manager.add_group(this.actor);
},
@ -1493,26 +1513,6 @@ const PopupComboMenu = new Lang.Class({
activeItem.actor.grab_key_focus();
},
_onSourceActorStyleChanged: function() {
// PopupComboBoxMenuItem clones the active item's actors
// to work with arbitrary items in the menu; this means
// that we need to propagate some style information and
// enforce style updates even when the menu is closed
let activeItem = this._getMenuItems()[this._activeItemPos];
if (this.sourceActor.has_style_pseudo_class('insensitive'))
activeItem.actor.add_style_pseudo_class('insensitive');
else
activeItem.actor.remove_style_pseudo_class('insensitive');
// To propagate the :active style, we need to make sure that the
// internal state of the PopupComboMenu is updated as well, but
// we must not move the keyboard grab
activeItem.setActive(this.sourceActor.has_style_pseudo_class('active'),
{ grabKeyboard: false });
_ensureStyle(this.actor);
},
open: function() {
if (this.isOpen)
return;
@ -1572,14 +1572,17 @@ const PopupComboMenu = new Lang.Class({
getItemVisible: function(position) {
return this._getMenuItems()[position].actor.visible;
}
});
};
const PopupComboBoxMenuItem = new Lang.Class({
Name: 'PopupComboBoxMenuItem',
Extends: PopupBaseMenuItem,
function PopupComboBoxMenuItem() {
this._init.apply(this, arguments);
}
PopupComboBoxMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function (params) {
this.parent(params);
PopupBaseMenuItem.prototype._init.call(this, params);
this._itemBox = new Shell.Stack();
this.addActor(this._itemBox);
@ -1697,254 +1700,16 @@ const PopupComboBoxMenuItem = new Lang.Class({
this.setActiveItem(position);
this.emit('active-item-changed', position);
}
});
/**
* RemoteMenu:
*
* A PopupMenu that tracks a GMenuModel and shows its actions
* (exposed by GApplication/GActionGroup)
*/
const RemoteMenu = new Lang.Class({
Name: 'RemoteMenu',
Extends: PopupMenu,
_init: function(sourceActor, model, actionGroup) {
this.parent(sourceActor, 0.0, St.Side.TOP);
this.model = model;
this.actionGroup = actionGroup;
this._actions = { };
this._modelChanged(this.model, 0, 0, this.model.get_n_items(), this);
this._actionStateChangeId = this.actionGroup.connect('action-state-changed', Lang.bind(this, this._actionStateChanged));
this._actionEnableChangeId = this.actionGroup.connect('action-enabled-changed', Lang.bind(this, this._actionEnabledChanged));
},
destroy: function() {
if (this._actionStateChangeId) {
this.actionGroup.disconnect(this._actionStateChangeId);
this._actionStateChangeId = 0;
}
if (this._actionEnableChangeId) {
this.actionGroup.disconnect(this._actionEnableChangeId);
this._actionEnableChangeId = 0;
}
this.parent();
},
_createMenuItem: function(model, index) {
let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
if (section_link) {
let item = new PopupMenuSection();
this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
return [item, true, ''];
}
// labels are not checked for existance, as they're required for all items
let label = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null).deep_unpack();
// remove all underscores that are not followed by another underscore
label = label.replace(/_([^_])/, '$1');
let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
if (submenu_link) {
let item = new PopupSubMenuMenuItem(label);
this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu);
return [item, false, ''];
}
let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
if (!this.actionGroup.has_action(action_id)) {
// the action may not be there yet, wait for action-added
return [null, false, 'action-added'];
}
if (!this._actions[action_id])
this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id),
state: this.actionGroup.get_action_state(action_id),
items: [ ],
};
let action = this._actions[action_id];
let item, target, destroyId, specificSignalId;
if (action.state) {
// Docs have get_state_hint(), except that the DBus protocol
// has no provision for it (so ShellApp does not implement it,
// and neither GApplication), and g_action_get_state_hint()
// always returns null
// Funny :)
switch (String.fromCharCode(action.state.classify())) {
case 'b':
item = new PopupSwitchMenuItem(label, action.state.get_boolean());
action.items.push(item);
specificSignalId = item.connect('toggled', Lang.bind(this, function(item) {
this.actionGroup.activate_action(action_id, null);
}));
break;
case 's':
item = new PopupMenuItem(label);
item._remoteTarget = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null).deep_unpack();
action.items.push(item);
item.setShowDot(action.state.deep_unpack() == item._remoteTarget);
specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget));
}));
break;
default:
log('Action "%s" has state of type %s, which is not supported'.format(action_id, action.state.get_type_string()));
return [null, false, 'action-state-changed'];
}
} else {
target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null);
item = new PopupMenuItem(label);
action.items.push(item);
specificSignalId = item.connect('activate', Lang.bind(this, function() {
this.actionGroup.activate_action(action_id, target);
}));
}
item.actor.reactive = item.actor.can_focus = action.enabled;
if (action.enabled)
item.actor.remove_style_pseudo_class('insensitive');
else
item.actor.add_style_pseudo_class('insensitive');
destroyId = item.connect('destroy', Lang.bind(this, function() {
item.disconnect(destroyId);
item.disconnect(specificSignalId);
let pos = action.items.indexOf(item);
if (pos != -1)
action.items.splice(pos, 1);
}));
return [item, false, ''];
},
_modelChanged: function(model, position, removed, added, target) {
let j, k;
let j0, k0;
let currentItems = target._getMenuItems();
for (j0 = 0, k0 = 0; j0 < position; j0++, k0++) {
if (currentItems[k0] instanceof PopupSeparatorMenuItem)
k0++;
}
if (removed == -1) {
// special flag to indicate we should destroy everything
for (k = k0; k < currentItems.length; k++)
currentItems[k].destroy();
} else {
for (j = j0, k = k0; j < j0 + removed; j++, k++) {
currentItems[k].destroy();
if (currentItems[k] instanceof PopupSeparatorMenuItem)
j--;
}
}
for (j = j0, k = k0; j < j0 + added; j++, k++) {
let [item, addSeparator, changeSignal] = this._createMenuItem(model, j);
if (item) {
// separators must be added in the parent to make autohiding work
if (addSeparator) {
target.addMenuItem(new PopupSeparatorMenuItem(), k+1);
k++;
}
target.addMenuItem(item, k);
if (addSeparator) {
target.addMenuItem(new PopupSeparatorMenuItem(), k+1);
k++;
}
} else if (changeSignal) {
let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function() {
this.actionGroup.disconnect(signalId);
// force a full update
this._modelChanged(model, 0, -1, model.get_n_items(), target);
}));
}
}
if (!model._changedId) {
model._changedId = model.connect('items-changed', Lang.bind(this, this._modelChanged, target));
model._destroyId = target.connect('destroy', function() {
if (model._changedId)
model.disconnect(model._changedId);
if (model._destroyId)
target.disconnect(model._destroyId);
model._changedId = 0;
model._destroyId = 0;
});
}
if (target instanceof PopupMenuSection) {
target.actor.visible = target.numMenuItems != 0;
} else {
let sourceItem = target.sourceActor._delegate;
if (sourceItem instanceof PopupSubMenuMenuItem)
sourceItem.actor.visible = target.numMenuItems != 0;
}
},
_actionStateChanged: function(actionGroup, action_id) {
let action = this._actions[action_id];
if (!action)
return;
action.state = actionGroup.get_action_state(action_id);
if (action.items.length) {
switch (String.fromCharCode(action.state.classify())) {
case 'b':
for (let i = 0; i < action.items.length; i++)
action.items[i].setToggleState(action.state.get_boolean());
break;
case 'd':
for (let i = 0; i < action.items.length; i++)
action.items[i].setValue(action.state.get_double());
break;
case 's':
for (let i = 0; i < action.items.length; i++)
action.items[i].setShowDot(action.items[i]._remoteTarget == action.state.deep_unpack());
}
}
},
_actionEnabledChanged: function(actionGroup, action_id) {
let action = this._actions[action_id];
if (!action)
return;
action.enabled = actionGroup.get_action_enabled(action_id);
if (action.items.length) {
for (let i = 0; i < action.items.length; i++) {
let item = action.items[i];
item.actor.reactive = item.actor.can_focus = action.enabled;
if (action.enabled)
item.actor.remove_style_pseudo_class('insensitive');
else
item.actor.add_style_pseudo_class('insensitive');
}
}
}
});
};
/* Basic implementation of a menu manager.
* Call addMenu to add menus
*/
const PopupMenuManager = new Lang.Class({
Name: 'PopupMenuManager',
function PopupMenuManager(owner) {
this._init(owner);
}
PopupMenuManager.prototype = {
_init: function(owner) {
this._owner = owner;
this.grabbed = false;
@ -2216,4 +1981,4 @@ const PopupMenuManager = new Lang.Class({
if (this._activeMenu != null)
this._activeMenu.close(true);
}
});
};

View File

@ -30,9 +30,11 @@ const EXEC_ARG_KEY = 'exec-arg';
const DIALOG_GROW_TIME = 0.1;
const CommandCompleter = new Lang.Class({
Name: 'CommandCompleter',
function CommandCompleter() {
this._init();
}
CommandCompleter.prototype = {
_init : function() {
this._changedCount = 0;
this._paths = GLib.getenv('PATH').split(':');
@ -160,14 +162,16 @@ const CommandCompleter = new Lang.Class({
return common.substr(text.length);
return common;
}
});
};
const RunDialog = new Lang.Class({
Name: 'RunDialog',
Extends: ModalDialog.ModalDialog,
function RunDialog() {
this._init();
}
RunDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init : function() {
this.parent({ styleClass: 'run-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'run-dialog' });
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._terminalSettings = new Gio.Settings({ schema: TERMINAL_SCHEMA });
@ -380,7 +384,8 @@ const RunDialog = new Lang.Class({
if (this._lockdownSettings.get_boolean(DISABLE_COMMAND_LINE_KEY))
return;
this.parent();
ModalDialog.ModalDialog.prototype.open.call(this);
},
});
};
Signals.addSignalMethods(RunDialog.prototype);

View File

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -69,21 +70,24 @@ function waitLeisure() {
};
}
const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
<method name="CreateWindow">
<arg type="i" direction="in" />
<arg type="i" direction="in" />
<arg type="b" direction="in" />
<arg type="b" direction="in" />
</method>
<method name="WaitWindows" />
<method name="DestroyWindows" />
</interface>;
const PerfHelperIface = {
name: 'org.gnome.Shell.PerfHelper',
methods: [{ name: 'CreateWindow', inSignature: 'iibb', outSignature: '' },
{ name: 'WaitWindows', inSignature: '', outSignature: '' },
{ name: 'DestroyWindows', inSignature: '', outSignature: ''}]
};
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
function PerfHelper() {
return new PerfHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
}
const PerfHelper = function () {
this._init();
};
PerfHelper.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
}
};
DBus.proxifyPrototype(PerfHelper.prototype, PerfHelperIface);
let _perfHelper = null;
function _getPerfHelper() {

View File

@ -23,9 +23,11 @@ const MatchType = {
MULTIPLE_PREFIX: 4
};
const SearchResultDisplay = new Lang.Class({
Name: 'SearchResultDisplay',
function SearchResultDisplay(provider) {
this._init(provider);
}
SearchResultDisplay.prototype = {
_init: function(provider) {
this.provider = provider;
this.actor = null;
@ -94,7 +96,7 @@ const SearchResultDisplay = new Lang.Class({
activateSelected: function() {
throw new Error('Not implemented');
}
});
};
/**
* SearchProvider:
@ -103,9 +105,11 @@ const SearchResultDisplay = new Lang.Class({
* to the search system, then call registerProvider()
* in SearchSystem with an instance.
*/
const SearchProvider = new Lang.Class({
Name: 'SearchProvider',
function SearchProvider(title) {
this._init(title);
}
SearchProvider.prototype = {
_init: function(title) {
this.title = title;
this.searchSystem = null;
@ -239,12 +243,14 @@ const SearchProvider = new Lang.Class({
activateResult: function(id) {
throw new Error('Not implemented');
}
});
};
Signals.addSignalMethods(SearchProvider.prototype);
const OpenSearchSystem = new Lang.Class({
Name: 'OpenSearchSystem',
function OpenSearchSystem() {
this._init();
}
OpenSearchSystem.prototype = {
_init: function() {
this._providers = [];
global.settings.connect('changed::' + DISABLED_OPEN_SEARCH_PROVIDERS_KEY, Lang.bind(this, this._refresh));
@ -332,12 +338,14 @@ const OpenSearchSystem = new Lang.Class({
}
}));
}
});
}
Signals.addSignalMethods(OpenSearchSystem.prototype);
const SearchSystem = new Lang.Class({
Name: 'SearchSystem',
function SearchSystem() {
this._init();
}
SearchSystem.prototype = {
_init: function() {
this._providers = [];
this.reset();
@ -425,5 +433,5 @@ const SearchSystem = new Lang.Class({
this._previousResults = results;
this.emit('search-completed', results);
},
});
};
Signals.addSignalMethods(SearchSystem.prototype);

View File

@ -15,9 +15,11 @@ const Search = imports.ui.search;
const MAX_SEARCH_RESULTS_ROWS = 1;
const SearchResult = new Lang.Class({
Name: 'SearchResult',
function SearchResult(provider, metaInfo, terms) {
this._init(provider, metaInfo, terms);
}
SearchResult.prototype = {
_init: function(provider, metaInfo, terms) {
this.provider = provider;
this.metaInfo = metaInfo;
@ -95,16 +97,18 @@ const SearchResult = new Lang.Class({
else
this.provider.activateResult(this.metaInfo.id, params);
}
});
};
const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: Search.SearchResultDisplay,
function GridSearchResults(provider, grid) {
this._init(provider, grid);
}
GridSearchResults.prototype = {
__proto__: Search.SearchResultDisplay.prototype,
_init: function(provider, grid) {
this.parent(provider);
Search.SearchResultDisplay.prototype._init.call(this, provider);
this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this.actor = new St.Bin({ x_align: St.Align.START });
@ -175,11 +179,14 @@ const GridSearchResults = new Lang.Class({
let targetActor = this._grid.getItemAtIndex(this.selectionIndex);
targetActor._delegate.activate();
}
});
};
const SearchResults = new Lang.Class({
Name: 'SearchResults',
function SearchResults(searchSystem, openSearchSystem) {
this._init(searchSystem, openSearchSystem);
}
SearchResults.prototype = {
_init: function(searchSystem, openSearchSystem) {
this._searchSystem = searchSystem;
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateCurrentResults));
@ -479,4 +486,4 @@ const SearchResults = new Lang.Class({
resultDisplay.activateSelected();
Main.overview.hide();
}
});
};

View File

@ -1,77 +1,79 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Config = imports.misc.config;
const ExtensionSystem = imports.ui.extensionSystem;
const Main = imports.ui.main;
const GnomeShellIface = <interface name="org.gnome.Shell">
<method name="Eval">
<arg type="s" direction="in" name="script" />
<arg type="b" direction="out" name="success" />
<arg type="s" direction="out" name="result" />
</method>
<method name="ListExtensions">
<arg type="a{sa{sv}}" direction="out" name="extensions" />
</method>
<method name="GetExtensionInfo">
<arg type="s" direction="in" name="extension" />
<arg type="a{sv}" direction="out" name="info" />
</method>
<method name="GetExtensionErrors">
<arg type="s" direction="in" name="extension" />
<arg type="as" direction="out" name="errors" />
</method>
<method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="ScreenshotWindow">
<arg type="b" direction="in" name="include_frame"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="Screenshot">
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="EnableExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="DisableExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="InstallRemoteExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="in" name="version"/>
</method>
<method name="UninstallExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="b" direction="out" name="success"/>
</method>
<property name="OverviewActive" type="b" access="readwrite" />
<property name="ApiVersion" type="i" access="read" />
<property name="ShellVersion" type="s" access="read" />
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
</interface>;
const GnomeShellIface = {
name: 'org.gnome.Shell',
methods: [{ name: 'Eval',
inSignature: 's',
outSignature: 'bs'
},
{ name: 'ListExtensions',
inSignature: '',
outSignature: 'a{sa{sv}}'
},
{ name: 'GetExtensionInfo',
inSignature: 's',
outSignature: 'a{sv}'
},
{ name: 'GetExtensionErrors',
inSignature: 's',
outSignature: 'as'
},
{ name: 'ScreenshotArea',
inSignature: 'iiiis',
outSignature: 'b'
},
{ name: 'ScreenshotWindow',
inSignature: 'bs',
outSignature: 'b'
},
{ name: 'Screenshot',
inSignature: 's',
outSignature: 'b'
},
{ name: 'EnableExtension',
inSignature: 's',
outSignature: ''
},
{ name: 'DisableExtension',
inSignature: 's',
outSignature: ''
},
{ name: 'InstallRemoteExtension',
inSignature: 'ss',
outSignature: ''
},
{ name: 'UninstallExtension',
inSignature: 's',
outSignature: 'b'
}
],
signals: [{ name: 'ExtensionStatusChanged',
inSignature: 'sis' }],
properties: [{ name: 'OverviewActive',
signature: 'b',
access: 'readwrite' },
{ name: 'ApiVersion',
signature: 'i',
access: 'read' },
{ name: 'ShellVersion',
signature: 's',
access: 'read' }]
};
const GnomeShell = new Lang.Class({
Name: 'GnomeShellDBus',
function GnomeShell() {
this._init();
}
GnomeShell.prototype = {
_init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
DBus.session.exportObject('/org/gnome/Shell', this);
ExtensionSystem.connect('extension-state-changed',
Lang.bind(this, this._extensionStateChanged));
},
@ -91,9 +93,6 @@ const GnomeShell = new Lang.Class({
*
*/
Eval: function(code) {
if (!global.settings.get_boolean('development-tools'))
return [false, null];
let returnValue;
let success;
try {
@ -154,33 +153,11 @@ const GnomeShell = new Lang.Class({
},
ListExtensions: function() {
let out = {};
for (let uuid in ExtensionSystem.extensionMeta) {
let dbusObj = this.GetExtensionInfo(uuid);
out[uuid] = dbusObj;
}
return out;
return ExtensionSystem.extensionMeta;
},
GetExtensionInfo: function(uuid) {
let meta = ExtensionSystem.extensionMeta[uuid] || {};
let out = {};
for (let key in meta) {
let val = meta[key];
let type;
switch (typeof val) {
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
default:
continue;
}
out[key] = GLib.Variant.new(type, val);
}
return out;
return ExtensionSystem.extensionMeta[uuid] || {};
},
GetExtensionErrors: function(uuid) {
@ -225,7 +202,12 @@ const GnomeShell = new Lang.Class({
ShellVersion: Config.PACKAGE_VERSION,
_extensionStateChanged: function(_, newState) {
this._dbusImpl.emit_signal('ExtensionStatusChanged',
GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
DBus.session.emit_signal('/org/gnome/Shell',
'org.gnome.Shell',
'ExtensionStatusChanged', 'sis',
[newState.uuid, newState.state, newState.error]);
}
});
};
DBus.conformExport(GnomeShell.prototype, GnomeShellIface);

View File

@ -7,14 +7,18 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const _EntryMenu = new Lang.Class({
Name: 'ShellEntryMenu',
Extends: PopupMenu.PopupMenu,
function _EntryMenu(entry, params) {
this._init(entry, params);
};
_EntryMenu.prototype = {
__proto__: PopupMenu.PopupMenu.prototype,
_init: function(entry, params) {
params = Params.parse (params, { isPassword: false });
this.parent(entry, 0, St.Side.TOP);
PopupMenu.PopupMenu.prototype._init.call(this, entry, 0, St.Side.TOP);
this.actor.add_style_class_name('entry-context-menu');
@ -56,7 +60,7 @@ const _EntryMenu = new Lang.Class({
if (!this.actor.navigate_focus(null, direction, false))
this.actor.grab_key_focus();
this.parent();
PopupMenu.PopupMenu.prototype.open.call(this);
},
_updateCopyItem: function() {
@ -99,7 +103,8 @@ const _EntryMenu = new Lang.Class({
let visible = !!(this._entry.clutter_text.password_char);
this._entry.clutter_text.set_password_char(visible ? '' : '\u25cf');
}
});
};
function _setMenuAlignment(entry, stageX) {
let [success, entryX, entryY] = entry.transform_stage_point(stageX, 0);

View File

@ -50,9 +50,11 @@ function _setLabelsForMessage(dialog, message) {
/* -------------------------------------------------------- */
const ListItem = new Lang.Class({
Name: 'ListItem',
function ListItem(app) {
this._init(app);
}
ListItem.prototype = {
_init: function(app) {
this._app = app;
@ -84,12 +86,14 @@ const ListItem = new Lang.Class({
this.emit('activate');
this._app.activate();
}
});
};
Signals.addSignalMethods(ListItem.prototype);
const ShellMountOperation = new Lang.Class({
Name: 'ShellMountOperation',
function ShellMountOperation(source, params) {
this._init(source, params);
}
ShellMountOperation.prototype = {
_init: function(source, params) {
params = Params.parse(params, { reaskPassword: false });
@ -186,14 +190,17 @@ const ShellMountOperation = new Lang.Class({
this._processesDialog.update(message, processes, choices);
},
});
}
const ShellMountQuestionDialog = new Lang.Class({
Name: 'ShellMountQuestionDialog',
Extends: ModalDialog.ModalDialog,
function ShellMountQuestionDialog(icon) {
this._init(icon);
}
ShellMountQuestionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(icon) {
this.parent({ styleClass: 'mount-question-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'mount-question-dialog' });
let mainContentLayout = new St.BoxLayout();
this.contentLayout.add(mainContentLayout, { x_fill: true,
@ -229,16 +236,19 @@ const ShellMountQuestionDialog = new Lang.Class({
_setLabelsForMessage(this, message);
_setButtonsForChoices(this, choices);
}
});
}
Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
const ShellMountPasswordSource = new Lang.Class({
Name: 'ShellMountPasswordSource',
Extends: MessageTray.Source,
function ShellMountPasswordSource(message, icon, reaskPassword) {
this._init(message, icon, reaskPassword);
}
ShellMountPasswordSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(message, icon, reaskPassword) {
let strings = message.split('\n');
this.parent(strings[0]);
MessageTray.Source.prototype._init.call(this, strings[0]);
this._notification = new ShellMountPasswordNotification(this, strings, icon, reaskPassword);
@ -246,15 +256,21 @@ const ShellMountPasswordSource = new Lang.Class({
Main.messageTray.add(this);
this.notify(this._notification);
},
});
}
Signals.addSignalMethods(ShellMountPasswordSource.prototype);
const ShellMountPasswordNotification = new Lang.Class({
Name: 'ShellMountPasswordNotification',
Extends: MessageTray.Notification,
function ShellMountPasswordNotification(source, strings, icon, reaskPassword) {
this._init(source, strings, icon, reaskPassword);
}
ShellMountPasswordNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, strings, icon, reaskPassword) {
this.parent(source, strings[0], null, { customContent: true, icon: icon });
MessageTray.Notification.prototype._init.call(this, source,
strings[0], null,
{ customContent: true,
icon: icon });
// set the notification to transient and urgent, so that it
// expands out
@ -289,14 +305,17 @@ const ShellMountPasswordNotification = new Lang.Class({
this.source.emit('password-ready', text);
}
});
}
const ShellProcessesDialog = new Lang.Class({
Name: 'ShellProcessesDialog',
Extends: ModalDialog.ModalDialog,
function ShellProcessesDialog(icon) {
this._init(icon);
}
ShellProcessesDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(icon) {
this.parent({ styleClass: 'show-processes-dialog' });
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'show-processes-dialog' });
let mainContentLayout = new St.BoxLayout();
this.contentLayout.add(mainContentLayout, { x_fill: true,
@ -382,5 +401,5 @@ const ShellProcessesDialog = new Lang.Class({
_setLabelsForMessage(this, message);
_setButtonsForChoices(this, choices);
}
});
}
Signals.addSignalMethods(ShellProcessesDialog.prototype);

View File

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GDesktopEnums = imports.gi.GDesktopEnums;
const DBus = imports.dbus;
const GConf = imports.gi.GConf;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
@ -29,8 +30,8 @@ const DPI_FACTOR_LARGE = 1.25;
const DPI_FACTOR_LARGER = 1.5;
const DPI_FACTOR_LARGEST = 2.0;
const WM_SCHEMA = 'org.gnome.desktop.wm.preferences';
const KEY_VISUAL_BELL = 'visual-bell';
const KEY_META_DIR = '/apps/metacity/general';
const KEY_VISUAL_BELL = KEY_META_DIR + '/visual_bell';
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
const KEY_GTK_THEME = 'gtk-theme';
@ -39,12 +40,19 @@ const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
const HIGH_CONTRAST_THEME = 'HighContrast';
const ATIndicator = new Lang.Class({
Name: 'ATIndicator',
Extends: PanelMenu.SystemStatusButton,
function ATIndicator() {
this._init.apply(this, arguments);
}
ATIndicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
this.parent('preferences-desktop-accessibility', null);
PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-accessibility', null);
let client = GConf.Client.get_default();
client.add_dir(KEY_META_DIR, GConf.ClientPreloadType.PRELOAD_ONELEVEL, null);
client.notify_add(KEY_META_DIR, Lang.bind(this, this._keyChanged), null, null);
let highContrast = this._buildHCItem();
this.menu.addMenuItem(highContrast);
@ -64,7 +72,7 @@ const ATIndicator = new Lang.Class({
'screen-keyboard-enabled');
this.menu.addMenuItem(screenKeyboard);
let visualBell = this._buildItem(_("Visual Alerts"), WM_SCHEMA, KEY_VISUAL_BELL);
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
this.menu.addMenuItem(visualBell);
let stickyKeys = this._buildItem(_("Sticky Keys"), A11Y_SCHEMA, KEY_STICKY_KEYS_ENABLED);
@ -94,6 +102,22 @@ const ATIndicator = new Lang.Class({
return widget;
},
_buildItemGConf: function(string, client, key) {
function on_get() {
return client.get_bool(key);
}
let widget = this._buildItemExtended(string,
client.get_bool(key),
client.key_is_writable(key),
function(enabled) {
client.set_bool(key, enabled);
});
this.connect('gconf-changed', function() {
widget.setToggleState(client.get_bool(key));
});
return widget;
},
_buildItem: function(string, schema, key) {
let settings = new Gio.Settings({ schema: schema });
let widget = this._buildItemExtended(string,
@ -167,5 +191,10 @@ const ATIndicator = new Lang.Class({
widget.setToggleState(active);
});
return widget;
},
_keyChanged: function() {
this.emit('gconf-changed');
}
});
};
Signals.addSignalMethods(ATIndicator.prototype);

View File

@ -23,13 +23,17 @@ const ConnectionState = {
CONNECTING: 3
}
const Indicator = new Lang.Class({
Name: 'BTIndicator',
Extends: PanelMenu.SystemStatusButton,
function Indicator() {
this._init.apply(this, arguments);
}
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
this.parent('bluetooth-disabled', null);
PanelMenu.SystemStatusButton.prototype._init.call(this, 'bluetooth-disabled', null);
GLib.spawn_command_line_sync ('pkill -f "^bluetooth-applet$"');
this._applet = new GnomeBluetoothApplet.Applet();
this._killswitch = new PopupMenu.PopupSwitchMenuItem(_("Bluetooth"), false);
@ -200,10 +204,9 @@ const Indicator = new Lang.Class({
_buildDeviceSubMenu: function(item, device) {
if (device.can_connect) {
let menuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
item._connected = device.connected;
item._connectedMenuItem = menuitem;
menuitem.connect('toggled', Lang.bind(this, function() {
item._connectedMenuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
item._connectedMenuitem.connect('toggled', Lang.bind(this, function() {
if (item._connected > ConnectionState.CONNECTED) {
// operation already in progress, revert
// (should not happen anyway)
@ -238,7 +241,7 @@ const Indicator = new Lang.Class({
}
}));
item.menu.addMenuItem(menuitem);
item.menu.addMenuItem(item._connectedMenuitem);
}
if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_PUSH) {
@ -331,14 +334,17 @@ const Indicator = new Lang.Class({
_cancelRequest: function() {
this._source.destroy();
}
});
}
const Source = new Lang.Class({
Name: 'BluetoothSource',
Extends: MessageTray.Source,
function Source() {
this._init.apply(this, arguments);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function() {
this.parent(_("Bluetooth"));
MessageTray.Source.prototype._init.call(this, _("Bluetooth"));
this._setSummaryIcon(this.createNotificationIcon());
},
@ -352,7 +358,7 @@ const Source = new Lang.Class({
}
}));
this.parent(notification);
MessageTray.Source.prototype.notify.call(this, notification);
},
createNotificationIcon: function() {
@ -360,17 +366,21 @@ const Source = new Lang.Class({
icon_type: St.IconType.SYMBOLIC,
icon_size: this.ICON_SIZE });
}
});
}
const AuthNotification = new Lang.Class({
Name: 'AuthNotification',
Extends: MessageTray.Notification,
function AuthNotification() {
this._init.apply(this, arguments);
}
AuthNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, applet, device_path, name, long_name, uuid) {
this.parent(source,
_("Bluetooth"),
_("Authorization request from %s").format(name),
{ customContent: true });
MessageTray.Notification.prototype._init.call(this,
source,
_("Bluetooth"),
_("Authorization request from %s").format(name),
{ customContent: true });
this.setResident(true);
this._applet = applet;
@ -396,17 +406,21 @@ const AuthNotification = new Lang.Class({
this.destroy();
}));
}
});
}
const ConfirmNotification = new Lang.Class({
Name: 'ConfirmNotification',
Extends: MessageTray.Notification,
function ConfirmNotification() {
this._init.apply(this, arguments);
}
ConfirmNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, applet, device_path, name, long_name, pin) {
this.parent(source,
_("Bluetooth"),
_("Pairing confirmation for %s").format(name),
{ customContent: true });
MessageTray.Notification.prototype._init.call(this,
source,
_("Bluetooth"),
_("Pairing confirmation for %s").format(name),
{ customContent: true });
this.setResident(true);
this._applet = applet;
@ -425,17 +439,21 @@ const ConfirmNotification = new Lang.Class({
this.destroy();
}));
}
});
}
const PinNotification = new Lang.Class({
Name: 'PinNotification',
Extends: MessageTray.Notification,
function PinNotification() {
this._init.apply(this, arguments);
}
PinNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, applet, device_path, name, long_name, numeric) {
this.parent(source,
_("Bluetooth"),
_("Pairing request for %s").format(name),
{ customContent: true });
MessageTray.Notification.prototype._init.call(this,
source,
_("Bluetooth"),
_("Pairing request for %s").format(name),
{ customContent: true });
this.setResident(true);
this._applet = applet;
@ -484,7 +502,7 @@ const PinNotification = new Lang.Class({
},
grabFocus: function(lockTray) {
this.parent(lockTray);
MessageTray.Notification.prototype.grabFocus.call(this, lockTray);
global.stage.set_key_focus(this._entry);
}
});
}

View File

@ -14,12 +14,15 @@ const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const Util = imports.misc.util;
const LayoutMenuItem = new Lang.Class({
Name: 'LayoutMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
function LayoutMenuItem() {
this._init.apply(this, arguments);
}
LayoutMenuItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(config, id, indicator, long_name) {
this.parent();
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
this._config = config;
this._id = id;
@ -30,18 +33,20 @@ const LayoutMenuItem = new Lang.Class({
},
activate: function(event) {
this.parent(event);
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
this._config.lock_group(this._id);
}
});
};
const XKBIndicator = new Lang.Class({
Name: 'XKBIndicator',
Extends: PanelMenu.Button,
function XKBIndicator() {
this._init.call(this);
}
XKBIndicator.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
this.parent(0.0);
PanelMenu.Button.prototype._init.call(this, St.Align.START);
this._container = new Shell.GenericContainer();
this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
@ -216,4 +221,4 @@ const XKBIndicator = new Lang.Class({
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
}
});
};

View File

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const ByteArray = imports.byteArray;
const DBus = imports.dbus;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
@ -97,12 +98,15 @@ function ssidToLabel(ssid) {
return label;
}
const NMNetworkMenuItem = new Lang.Class({
Name: 'NMNetworkMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
function NMNetworkMenuItem() {
this._init.apply(this, arguments);
}
NMNetworkMenuItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(accessPoints, title, params) {
this.parent(params);
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
accessPoints = sortAccessPoints(accessPoints);
this.bestAP = accessPoints[0];
@ -181,18 +185,21 @@ const NMNetworkMenuItem = new Lang.Class({
apObj.updateId = 0;
}
this.parent();
PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this);
}
});
};
const NMWiredSectionTitleMenuItem = new Lang.Class({
Name: 'NMWiredSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem,
function NMWiredSectionTitleMenuItem() {
this._init.apply(this, arguments);
}
NMWiredSectionTitleMenuItem.prototype = {
__proto__: PopupMenu.PopupSwitchMenuItem.prototype,
_init: function(label, params) {
params = params || { };
params.style_class = 'popup-subtitle-menu-item';
this.parent(label, false, params);
PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, label, false, params);
},
updateForDevice: function(device) {
@ -205,7 +212,7 @@ const NMWiredSectionTitleMenuItem = new Lang.Class({
},
activate: function(event) {
this.parent(event);
PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
if (!this._device) {
log('Section title activated when there is more than one device, should be non reactive');
@ -224,16 +231,19 @@ const NMWiredSectionTitleMenuItem = new Lang.Class({
else
this._device.deactivate();
}
});
};
const NMWirelessSectionTitleMenuItem = new Lang.Class({
Name: 'NMWirelessSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem,
function NMWirelessSectionTitleMenuItem() {
this._init.apply(this, arguments);
}
NMWirelessSectionTitleMenuItem.prototype = {
__proto__: PopupMenu.PopupSwitchMenuItem.prototype,
_init: function(client, property, title, params) {
params = params || { };
params.style_class = 'popup-subtitle-menu-item';
this.parent(title, false, params);
PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, title, false, params);
this._client = client;
this._property = property + '_enabled';
@ -249,11 +259,9 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
updateForDevice: function(device) {
// we show the switch
// - if there not just one device
// - if the switch is off (but it can be turned on)
// - if the switch is off
// - if the device is activated or disconnected
if (!this._hardwareEnabled) {
this.setStatus(_("hardware disabled"));
} else if (device && this._softwareEnabled) {
if (device && this._softwareEnabled && this._hardwareEnabled) {
let text = device.getStatusLabel();
this.setStatus(text);
} else
@ -261,7 +269,7 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
},
activate: function(event) {
this.parent(event);
PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
this._client[this._setEnabledFunc](this._switch.state);
},
@ -278,12 +286,13 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
this.emit('enabled-changed', enabled);
}
});
};
const NMDevice = new Lang.Class({
Name: 'NMDevice',
Abstract: true,
function NMDevice() {
throw new TypeError('Instantanting abstract class NMDevice');
}
NMDevice.prototype = {
_init: function(client, device, connections) {
this.device = device;
if (device) {
@ -329,7 +338,7 @@ const NMDevice = new Lang.Class({
}
this.section = new PopupMenu.PopupMenuSection();
this._deferredWorkId = Main.initializeDeferredWork(this.section.actor, Lang.bind(this, this._createSection));
this._createSection();
},
destroy: function() {
@ -396,29 +405,16 @@ const NMDevice = new Lang.Class({
this._activeConnection = activeConnection;
this._clearSection();
this._queueCreateSection();
this._createSection();
},
checkConnection: function(connection) {
let pos = this._findConnection(connection._uuid);
let exists = pos != -1;
let exists = this._findConnection(connection._uuid) != -1;
let valid = this.connectionValid(connection);
if (exists && !valid)
this.removeConnection(connection);
else if (!exists && valid)
this.addConnection(connection);
else if (exists && valid) {
// propagate changes and update the UI
if (this._connections[pos].timestamp != connection._timestamp) {
this._connections[pos].timestamp = connection._timestamp;
this._connections.sort(this._connectionSortFunction);
this._clearSection();
this._queueCreateSection();
}
}
},
addConnection: function(connection) {
@ -433,7 +429,7 @@ const NMDevice = new Lang.Class({
this._connections.sort(this._connectionSortFunction);
this._clearSection();
this._queueCreateSection();
this._createSection();
},
removeConnection: function(connection) {
@ -457,7 +453,7 @@ const NMDevice = new Lang.Class({
// (or in the case of NMDeviceWired, we want to hide
// the only explicit connection)
this._clearSection();
this._queueCreateSection();
this._createSection();
}
},
@ -541,11 +537,6 @@ const NMDevice = new Lang.Class({
return -1;
},
_queueCreateSection: function() {
this._clearSection();
Main.queueDeferredWork(this._deferredWorkId);
},
_clearSection: function() {
// Clear everything
this.section.removeAll();
@ -640,7 +631,7 @@ const NMDevice = new Lang.Class({
this._updateStatusItem();
this._clearSection();
this._queueCreateSection();
this._createSection();
this.emit('state-changed');
},
@ -683,23 +674,26 @@ const NMDevice = new Lang.Class({
return out;
}
});
};
Signals.addSignalMethods(NMDevice.prototype);
const NMDeviceWired = new Lang.Class({
Name: 'NMDeviceWired',
Extends: NMDevice,
function NMDeviceWired() {
this._init.apply(this, arguments);
}
NMDeviceWired.prototype = {
__proto__: NMDevice.prototype,
_init: function(client, device, connections) {
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED;
this.parent(client, device, connections);
NMDevice.prototype._init.call(this, client, device, connections);
},
_createSection: function() {
this.parent();
NMDevice.prototype._createSection.call(this);
// if we have only one connection (normal or automatic)
// we hide the connection list, and use the switch to control
@ -724,11 +718,14 @@ const NMDeviceWired = new Lang.Class({
}));
return connection;
}
});
};
const NMDeviceModem = new Lang.Class({
Name: 'NMDeviceModem',
Extends: NMDevice,
function NMDeviceModem() {
this._init.apply(this, arguments);
}
NMDeviceModem.prototype = {
__proto__: NMDevice.prototype,
_init: function(client, device, connections) {
let is_wwan = false;
@ -777,7 +774,7 @@ const NMDeviceModem = new Lang.Class({
}));
}
this.parent(client, device, connections);
NMDevice.prototype._init.call(this, client, device, connections);
},
setEnabled: function(enabled) {
@ -790,7 +787,7 @@ const NMDeviceModem = new Lang.Class({
this.statusItem.setStatus(this.getStatusLabel());
}
this.parent(enabled);
NMDevice.prototype.setEnabled.call(this, enabled);
},
get connected() {
@ -807,7 +804,7 @@ const NMDeviceModem = new Lang.Class({
this._signalQualityId = 0;
}
this.parent();
NMDevice.prototype.destroy.call(this);
},
_getSignalIcon: function() {
@ -828,13 +825,13 @@ const NMDeviceModem = new Lang.Class({
this.section.addMenuItem(this._operatorItem);
}
this.parent();
NMDevice.prototype._createSection.call(this);
},
_clearSection: function() {
this._operatorItem = null;
this.parent();
NMDevice.prototype._clearSection.call(this);
},
_createAutomaticConnection: function() {
@ -844,11 +841,14 @@ const NMDeviceModem = new Lang.Class({
'connect-3g', this.device.get_path()]);
return null;
}
});
};
const NMDeviceBluetooth = new Lang.Class({
Name: 'NMDeviceBluetooth',
Extends: NMDevice,
function NMDeviceBluetooth() {
this._init.apply(this, arguments);
}
NMDeviceBluetooth.prototype = {
__proto__: NMDevice.prototype,
_init: function(client, device, connections) {
this._autoConnectionName = this._makeConnectionName(device);
@ -856,7 +856,7 @@ const NMDeviceBluetooth = new Lang.Class({
this.category = NMConnectionCategory.WWAN;
this.parent(client, device, connections);
NMDevice.prototype._init.call(this, client, device, connections);
},
_createAutomaticConnection: function() {
@ -884,27 +884,25 @@ const NMDeviceBluetooth = new Lang.Class({
this._autoConnectionName = this._makeConnectionName(this.device);
this._clearSection();
this._queueCreateSection();
this._updateStatusItem();
},
_getDescription: function() {
return this.device.name || _("Bluetooth");
this._createSection();
}
});
};
// Not a real device, but I save a lot code this way
const NMDeviceVPN = new Lang.Class({
Name: 'NMDeviceVPN',
Extends: NMDevice,
function NMDeviceVPN() {
this._init.apply(this, arguments);
}
NMDeviceVPN.prototype = {
__proto__: NMDevice.prototype,
_init: function(client) {
// Disable autoconnections
this._autoConnectionName = null;
this.category = NMConnectionCategory.VPN;
this.parent(client, null, [ ]);
NMDevice.prototype._init.call(this, client, null, [ ]);
},
connectionValid: function(connection) {
@ -920,7 +918,7 @@ const NMDeviceVPN = new Lang.Class({
},
setActiveConnection: function(activeConnection) {
this.parent(activeConnection);
NMDevice.prototype.setActiveConnection.call(this, activeConnection);
this.emit('active-connection-changed');
},
@ -937,11 +935,14 @@ const NMDeviceVPN = new Lang.Class({
getStatusLabel: function() {
return null;
}
});
};
const NMDeviceWireless = new Lang.Class({
Name: 'NMDeviceWireless',
Extends: NMDevice,
function NMDeviceWireless() {
this._init.apply(this, arguments);
}
NMDeviceWireless.prototype = {
__proto__: NMDevice.prototype,
_init: function(client, device, connections) {
this.category = NMConnectionCategory.WIRELESS;
@ -1013,7 +1014,7 @@ const NMDeviceWireless = new Lang.Class({
this._apAddedId = device.connect('access-point-added', Lang.bind(this, this._accessPointAdded));
this._apRemovedId = device.connect('access-point-removed', Lang.bind(this, this._accessPointRemoved));
this.parent(client, device, validConnections);
NMDevice.prototype._init.call(this, client, device, validConnections);
},
destroy: function() {
@ -1033,7 +1034,7 @@ const NMDeviceWireless = new Lang.Class({
this._apRemovedId = 0;
}
this.parent();
NMDevice.prototype.destroy.call(this);
},
setEnabled: function(enabled) {
@ -1234,6 +1235,7 @@ const NMDeviceWireless = new Lang.Class({
accessPoints: [ accessPoint ]
};
apObj.ssidText = ssidToLabel(apObj.ssid);
needsupdate = true;
}
// check if this enables new connections for this group
@ -1248,13 +1250,37 @@ const NMDeviceWireless = new Lang.Class({
}
}
if (pos == -1 || needsupdate) {
if (needsupdate) {
if (apObj.item)
apObj.item.destroy();
if (pos != -1)
this._networks.splice(pos, 1);
pos = Util.insertSorted(this._networks, apObj, this._networkSortFunction);
this._clearSection();
this._queueCreateSection();
if (this._networks.length == 0) {
// only network in the list
this._networks.push(apObj);
this._clearSection();
this._createSection();
return;
}
// skip networks that should appear earlier
let menuPos = 0;
for (pos = 0;
pos < this._networks.length &&
this._networkSortFunction(this._networks[pos], apObj) < 0; ++pos) {
if (this._networks[pos] != this._activeNetwork)
menuPos++;
}
// (re-)add the network
this._networks.splice(pos, 0, apObj);
if (this._shouldShowConnectionList()) {
menuPos += (this._activeConnectionItem ? 1 : 0);
this._createNetworkItem(apObj, menuPos);
}
}
},
@ -1322,7 +1348,7 @@ const NMDeviceWireless = new Lang.Class({
},
_clearSection: function() {
this.parent();
NMDevice.prototype._clearSection.call(this);
for (let i = 0; i < this._networks.length; i++)
this._networks[i].item = null;
@ -1341,7 +1367,7 @@ const NMDeviceWireless = new Lang.Class({
let obj = this._connections[pos];
this._connections.splice(pos, 1);
let forceupdate = false;
let anyauto = false, forceupdate = false;
for (let i = 0; i < this._networks.length; i++) {
let apObj = this._networks[i];
let connections = apObj.connections;
@ -1349,14 +1375,16 @@ const NMDeviceWireless = new Lang.Class({
if (connections[k]._uuid == connection._uuid) {
// remove the connection from the access point group
connections.splice(k);
forceupdate = forceupdate || connections.length == 0;
anyauto = connections.length == 0;
if (forceupdate)
if (anyauto) {
// this potentially changes the sorting order
forceupdate = true;
break;
}
if (apObj.item) {
if (apObj.item instanceof PopupMenu.PopupSubMenuMenuItem) {
let items = apObj.item.menu._getMenuItems();
let items = apObj.item.menu.getMenuItems();
if (items.length == 2) {
// we need to update the connection list to convert this to a normal item
forceupdate = true;
@ -1378,10 +1406,10 @@ const NMDeviceWireless = new Lang.Class({
}
}
if (forceupdate) {
if (forceupdate || anyauto) {
this._networks.sort(this._networkSortFunction);
this._clearSection();
this._queueCreateSection();
this._createSection();
}
},
@ -1414,13 +1442,13 @@ const NMDeviceWireless = new Lang.Class({
if (forceupdate) {
this._networks.sort(this._networkSortFunction);
this._clearSection();
this._queueCreateSection();
this._createSection();
}
},
_createActiveConnectionItem: function() {
let icon, title;
if (this._activeConnection && this._activeConnection._connection) {
if (this._activeConnection._connection) {
let connection = this._activeConnection._connection;
if (this._activeNetwork)
this._activeConnectionItem = new NMNetworkMenuItem(this._activeNetwork.accessPoints, undefined,
@ -1513,7 +1541,7 @@ const NMDeviceWireless = new Lang.Class({
if (!this._shouldShowConnectionList())
return;
if (this._activeNetwork) {
if(this._activeConnection) {
this._createActiveConnectionItem();
this.section.addMenuItem(this._activeConnectionItem);
}
@ -1522,22 +1550,22 @@ const NMDeviceWireless = new Lang.Class({
for(let j = 0; j < this._networks.length; j++) {
let apObj = this._networks[j];
if (apObj == this._activeNetwork) {
activeOffset--;
if (apObj == this._activeNetwork)
continue;
}
this._createNetworkItem(apObj, j + activeOffset);
}
},
});
};
const NMApplet = new Lang.Class({
Name: 'NMApplet',
Extends: PanelMenu.SystemStatusButton,
function NMApplet() {
this._init.apply(this, arguments);
}
NMApplet.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
this.parent('network-error', null);
PanelMenu.SystemStatusButton.prototype._init.call(this, 'network-error');
this._client = NMClient.Client.new();
@ -2037,11 +2065,10 @@ const NMApplet = new Lang.Class({
}
this.setIcon('network-wireless-connected');
} else {
if (this._activeAccessPoint != ap) {
if (this._accessPointUpdateId)
this._activeAccessPoint.disconnect(this._accessPointUpdateId);
if (this._accessPointUpdateId && this._activeAccessPoint != ap) {
this._activeAccessPoint.disconnect(this._accessPointUpdateId);
this._activeAccessPoint = ap;
this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(this, function() {
this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(function() {
this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength));
}));
}
@ -2068,9 +2095,8 @@ const NMApplet = new Lang.Class({
break;
}
if (dev.mobileDevice != this._mobileUpdateDevice) {
if (this._mobileUpdateId)
this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
if (this._mobileUpdateId && this._mobileUpdateDevice != dev) {
this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
this._mobileUpdateDevice = dev.mobileDevice;
this._mobileUpdateId = dev.mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality));
@ -2103,14 +2129,17 @@ const NMApplet = new Lang.Class({
this._mobileUpdateId = 0;
}
}
});
};
const NMMessageTraySource = new Lang.Class({
Name: 'NMMessageTraySource',
Extends: MessageTray.Source,
function NMMessageTraySource() {
this._init();
}
NMMessageTraySource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function() {
this.parent(_("Network Manager"));
MessageTray.Source.prototype._init.call(this, _("Network Manager"));
let icon = new St.Icon({ icon_name: 'network-transmit-receive',
icon_type: St.IconType.SYMBOLIC,
@ -2118,4 +2147,4 @@ const NMMessageTraySource = new Lang.Class({
});
this._setSummaryIcon(icon);
}
});
};

View File

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
@ -39,27 +40,31 @@ const UPDeviceState = {
PENDING_DISCHARGE: 6
};
const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
<method name="GetDevices">
<arg type="a(susdut)" direction="out" />
</method>
<method name="GetPrimaryDevice">
<arg type="(susdut)" direction="out" />
</method>
<signal name="Changed" />
<property name="Icon" type="s" access="read" />
</interface>;
const PowerManagerInterface = {
name: 'org.gnome.SettingsDaemon.Power',
methods: [
{ name: 'GetDevices', inSignature: '', outSignature: 'a(susdut)' },
{ name: 'GetPrimaryDevice', inSignature: '', outSignature: '(susdut)' },
],
signals: [
{ name: 'Changed', inSignature: '' },
],
properties: [
{ name: 'Icon', signature: 's', access: 'read' },
]
};
let PowerManagerProxy = DBus.makeProxyClass(PowerManagerInterface);
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
function Indicator() {
this._init.apply(this, arguments);
}
const Indicator = new Lang.Class({
Name: 'PowerIndicator',
Extends: PanelMenu.SystemStatusButton,
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
this.parent('battery-missing', null);
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
PanelMenu.SystemStatusButton.prototype._init.call(this, 'battery-missing');
this._proxy = new PowerManagerProxy(DBus.session, BUS_NAME, OBJECT_PATH);
this._deviceItems = [ ];
this._hasPrimary = false;
@ -76,19 +81,19 @@ const Indicator = new Lang.Class({
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
this._proxy.connectSignal('Changed', Lang.bind(this, this._devicesChanged));
this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
this._devicesChanged();
},
_readPrimaryDevice: function() {
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(device, error) {
if (error) {
this._hasPrimary = false;
this._primaryDeviceId = null;
this._batteryItem.actor.hide();
return;
}
let [[device_id, device_type, icon, percentage, state, seconds]] = result;
let [device_id, device_type, icon, percentage, state, seconds] = device;
if (device_type == UPDeviceType.BATTERY) {
this._hasPrimary = true;
let time = Math.round(seconds / 60);
@ -125,7 +130,7 @@ const Indicator = new Lang.Class({
},
_readOtherDevices: function() {
this._proxy.GetDevicesRemote(Lang.bind(this, function(result, error) {
this._proxy.GetDevicesRemote(Lang.bind(this, function(devices, error) {
this._deviceItems.forEach(function(i) { i.destroy(); });
this._deviceItems = [];
@ -134,7 +139,6 @@ const Indicator = new Lang.Class({
}
let position = 0;
let [devices] = result;
for (let i = 0; i < devices.length; i++) {
let [device_id, device_type] = devices[i];
if (device_type == UPDeviceType.AC_POWER || device_id == this._primaryDeviceId)
@ -149,26 +153,30 @@ const Indicator = new Lang.Class({
},
_devicesChanged: function() {
let icon = this._proxy.Icon;
if (icon) {
let gicon = Gio.icon_new_for_string(icon);
this.setGIcon(gicon);
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
this._proxy.GetRemote('Icon', Lang.bind(this, function(icon, error) {
if (icon) {
let gicon = Gio.icon_new_for_string(icon);
this.setGIcon(gicon);
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
}));
this._readPrimaryDevice();
this._readOtherDevices();
}
});
};
const DeviceItem = new Lang.Class({
Name: 'DeviceItem',
Extends: PopupMenu.PopupBaseMenuItem,
function DeviceItem() {
this._init.apply(this, arguments);
}
DeviceItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(device) {
this.parent({ reactive: false });
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
let [device_id, device_type, icon, percentage, state, time] = device;
@ -215,4 +223,4 @@ const DeviceItem = new Lang.Class({
return _("Unknown");
}
}
});
}

View File

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
@ -17,12 +18,15 @@ const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */
const VOLUME_NOTIFY_ID = 1;
const Indicator = new Lang.Class({
Name: 'VolumeIndicator',
Extends: PanelMenu.SystemStatusButton,
function Indicator() {
this._init.apply(this, arguments);
}
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
this.parent('audio-volume-muted', null);
PanelMenu.SystemStatusButton.prototype._init.call(this, 'audio-volume-muted', null);
this._control = new Gvc.MixerControl({ name: 'GNOME Shell Volume Control' });
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
@ -211,4 +215,4 @@ const Indicator = new Lang.Class({
if (property == '_output' && !this._output.is_muted)
this.setIcon(this._volumeToIcon(this._output.volume));
}
});
};

View File

@ -23,9 +23,11 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'ibus-ui-gtk': 'input-method'
};
const StatusIconDispatcher = new Lang.Class({
Name: 'StatusIconDispatcher',
function StatusIconDispatcher() {
this._init();
}
StatusIconDispatcher.prototype = {
_init: function() {
this._traymanager = new Shell.TrayManager();
this._traymanager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
@ -59,5 +61,5 @@ const StatusIconDispatcher = new Lang.Class({
else
this.emit('message-icon-removed', icon);
}
});
};
Signals.addSignalMethods(StatusIconDispatcher.prototype);

View File

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
@ -72,9 +73,11 @@ function makeMessageFromTplEvent(event) {
};
}
const Client = new Lang.Class({
Name: 'Client',
function Client() {
this._init();
};
Client.prototype = {
_init : function() {
// channel path -> ChatSource
this._chatSources = {};
@ -197,11 +200,11 @@ const Client = new Lang.Class({
_handleChannels: function(handler, account, conn, channels,
requests, user_action_time, context) {
this._handlingChannels(account, conn, channels, true);
this._handlingChannels(account, conn, channels);
context.accept();
},
_handlingChannels: function(account, conn, channels, notify) {
_handlingChannels: function(account, conn, channels) {
let len = channels.length;
for (let i = 0; i < len; i++) {
let channel = channels[i];
@ -212,18 +215,7 @@ const Client = new Lang.Class({
continue;
}
// 'notify' will be true when coming from an actual HandleChannels
// call, and not when from a successful Claim call. The point is
// we don't want to notify for a channel we just claimed which
// has no new messages (for example, a new channel which only has
// a delivery notification). We rely on _displayPendingMessages()
// and _messageReceived() to notify for new messages.
// But we should still notify from HandleChannels because the
// Telepathy spec states that handlers must foreground channels
// in HandleChannels calls which are already being handled.
if (notify && this._tpClient.is_handling_channel(channel)) {
if (this._tpClient.is_handling_channel(channel)) {
// We are already handling the channel, display the source
let source = this._chatSources[channel.get_object_path()];
if (source)
@ -296,7 +288,7 @@ const Client = new Lang.Class({
Lang.bind(this, function(dispatchOp, result) {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
this._handlingChannels(account, conn, [channel]);
} catch (err) {
throw new Error('Failed to Claim channel: ' + err);
}}));
@ -488,14 +480,17 @@ const Client = new Lang.Class({
return this._accountSource;
}
});
};
const ChatSource = new Lang.Class({
Name: 'ChatSource',
Extends: MessageTray.Source,
function ChatSource(account, conn, channel, contact, client) {
this._init(account, conn, channel, contact, client);
}
ChatSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(account, conn, channel, contact, client) {
this.parent(contact.get_alias());
MessageTray.Source.prototype._init.call(this, contact.get_alias());
this.isChat = true;
@ -513,9 +508,15 @@ const ChatSource = new Lang.Class({
this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notifyTimeoutId = 0;
// We ack messages when the user expands the new notification or views the summary
// notification, in which case the notification is also expanded.
this._notification.connect('expanded', Lang.bind(this, this._ackMessages));
// We ack messages when the message box is collapsed if user has
// interacted with it before and so read the messages:
// - user clicked on it the tray
// - user expanded the notification by hovering over the toaster notification
this._shouldAck = false;
this.connect('summary-item-clicked', Lang.bind(this, this._summaryItemClicked));
this._notification.connect('expanded', Lang.bind(this, this._notificationExpanded));
this._notification.connect('collapsed', Lang.bind(this, this._notificationCollapsed));
this._presence = contact.get_presence_type();
@ -697,7 +698,7 @@ const ChatSource = new Lang.Class({
},
notify: function() {
this.parent(this._notification);
MessageTray.Source.prototype.notify.call(this, this._notification);
},
respond: function(text) {
@ -779,15 +780,36 @@ const ChatSource = new Lang.Class({
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(Lang.bind(this, function(src, result) {
this._channel.ack_all_pending_messages_finish(result);}));
}
});
},
const ChatNotification = new Lang.Class({
Name: 'ChatNotification',
Extends: MessageTray.Notification,
_summaryItemClicked: function(source, button) {
if (button != 1)
return;
this._shouldAck = true;
},
_notificationExpanded: function() {
this._shouldAck = true;
},
_notificationCollapsed: function() {
if (this._shouldAck)
this._ackMessages();
this._shouldAck = false;
}
};
function ChatNotification(source) {
this._init(source);
}
ChatNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source) {
this.parent(source, source.title, null, { customContent: true });
MessageTray.Notification.prototype._init.call(this, source, source.title, null, { customContent: true });
this.setResident(true);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
@ -878,7 +900,7 @@ const ChatNotification = new Lang.Class({
}
let groups = this._contentArea.get_children();
for (let i = 0; i < groups.length; i++) {
for (let i = 0; i < groups.length; i ++) {
let group = groups[i];
if (group.get_children().length == 0)
group.destroy();
@ -916,7 +938,7 @@ const ChatNotification = new Lang.Class({
let body = highlighter.actor;
let styles = props.styles;
for (let i = 0; i < styles.length; i++)
for (let i = 0; i < styles.length; i ++)
body.add_style_class_name(styles[i]);
let group = props.group;
@ -1070,14 +1092,17 @@ const ChatNotification = new Lang.Class({
this.source.setChatState(Tp.ChannelChatState.ACTIVE);
}
}
});
};
const ApproverSource = new Lang.Class({
Name: 'ApproverSource',
Extends: MessageTray.Source,
function ApproverSource(dispatchOp, text, gicon) {
this._init(dispatchOp, text, gicon);
}
ApproverSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(dispatchOp, text, gicon) {
this.parent(text);
MessageTray.Source.prototype._init.call(this, text);
this._gicon = gicon;
this._setSummaryIcon(this.createNotificationIcon());
@ -1098,7 +1123,7 @@ const ApproverSource = new Lang.Class({
this._invalidId = 0;
}
this.parent();
MessageTray.Source.prototype.destroy.call(this);
},
createNotificationIcon: function() {
@ -1106,19 +1131,23 @@ const ApproverSource = new Lang.Class({
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
});
}
const RoomInviteNotification = new Lang.Class({
Name: 'RoomInviteNotification',
Extends: MessageTray.Notification,
function RoomInviteNotification(source, dispatchOp, channel, inviter) {
this._init(source, dispatchOp, channel, inviter);
}
RoomInviteNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, dispatchOp, channel, inviter) {
this.parent(source,
/* translators: argument is a room name like
* room@jabber.org for example. */
_("Invitation to %s").format(channel.get_identifier()),
null,
{ customContent: true });
MessageTray.Notification.prototype._init.call(this,
source,
/* translators: argument is a room name like
* room@jabber.org for example. */
_("Invitation to %s").format(channel.get_identifier()),
null,
{ customContent: true });
this.setResident(true);
/* translators: first argument is the name of a contact and the second
@ -1145,12 +1174,15 @@ const RoomInviteNotification = new Lang.Class({
this.destroy();
}));
}
});
};
// Audio Video
const AudioVideoNotification = new Lang.Class({
Name: 'AudioVideoNotification',
Extends: MessageTray.Notification,
function AudioVideoNotification(source, dispatchOp, channel, contact, isVideo) {
this._init(source, dispatchOp, channel, contact, isVideo);
}
AudioVideoNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, dispatchOp, channel, contact, isVideo) {
let title = '';
@ -1162,7 +1194,11 @@ const AudioVideoNotification = new Lang.Class({
/* translators: argument is a contact name like Alice for example. */
title = _("Call from %s").format(contact.get_alias());
this.parent(this, source, title, null, { customContent: true });
MessageTray.Notification.prototype._init.call(this,
source,
title,
null,
{ customContent: true });
this.setResident(true);
this.addButton('reject', _("Reject"));
@ -1185,25 +1221,28 @@ const AudioVideoNotification = new Lang.Class({
this.destroy();
}));
}
});
};
// File Transfer
const FileTransferNotification = new Lang.Class({
Name: 'FileTransferNotification',
Extends: MessageTray.Notification,
function FileTransferNotification(source, dispatchOp, channel, contact) {
this._init(source, dispatchOp, channel, contact);
}
FileTransferNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, dispatchOp, channel, contact) {
this.parent(this,
source,
/* To translators: The first parameter is
* the contact's alias and the second one is the
* file name. The string will be something
* like: "Alice is sending you test.ogg"
*/
_("%s is sending you %s").format(contact.get_alias(),
channel.get_filename()),
null,
{ customContent: true });
MessageTray.Notification.prototype._init.call(this,
source,
/* To translators: The first parameter is
* the contact's alias and the second one is the
* file name. The string will be something
* like: "Alice is sending you test.ogg"
*/
_("%s is sending you %s").format(contact.get_alias(),
channel.get_filename()),
null,
{ customContent: true });
this.setResident(true);
this.addButton('decline', _("Decline"));
@ -1225,15 +1264,18 @@ const FileTransferNotification = new Lang.Class({
this.destroy();
}));
}
});
};
// A notification source that can embed multiple notifications
const MultiNotificationSource = new Lang.Class({
Name: 'MultiNotificationSource',
Extends: MessageTray.Source,
function MultiNotificationSource(title, icon) {
this._init(title, icon);
}
MultiNotificationSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(title, icon) {
this.parent(title);
MessageTray.Source.prototype._init.call(this, title);
this._icon = icon;
this._setSummaryIcon(this.createNotificationIcon());
@ -1241,7 +1283,7 @@ const MultiNotificationSource = new Lang.Class({
},
notify: function(notification) {
this.parent(notification);
MessageTray.Source.prototype.notify.call(this, notification);
this._nbNotifications += 1;
@ -1255,22 +1297,25 @@ const MultiNotificationSource = new Lang.Class({
},
createNotificationIcon: function() {
return new St.Icon({ gicon: Gio.icon_new_for_string(this._icon),
return new St.Icon({ gicon: Shell.util_icon_from_string(this._icon),
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
});
};
// Subscription request
const SubscriptionRequestNotification = new Lang.Class({
Name: 'SubscriptionRequestNotification',
Extends: MessageTray.Notification,
function SubscriptionRequestNotification(source, contact) {
this._init(source, contact);
}
SubscriptionRequestNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, contact) {
this.parent(this, source,
/* To translators: The parameter is the contact's alias */
_("%s would like permission to see when you are online").format(contact.get_alias()),
null, { customContent: true });
MessageTray.Notification.prototype._init.call(this, source,
/* To translators: The parameter is the contact's alias */
_("%s would like permission to see when you are online").format(contact.get_alias()),
null, { customContent: true });
this._contact = contact;
this._connection = contact.get_connection();
@ -1344,7 +1389,7 @@ const SubscriptionRequestNotification = new Lang.Class({
this._invalidatedId = 0;
}
this.parent();
MessageTray.Notification.prototype.destroy.call(this);
},
_subscriptionStatesChangedCb: function(contact, subscribe, publish, msg) {
@ -1353,7 +1398,12 @@ const SubscriptionRequestNotification = new Lang.Class({
if (publish != Tp.SubscriptionState.ASK)
this.destroy();
}
});
};
function AccountNotification(source, account, connectionError) {
this._init(source, account, connectionError);
}
// Messages from empathy/libempathy/empathy-utils.c
// create_errors_to_message_hash()
@ -1408,16 +1458,15 @@ _connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_INSECURE)]
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_LIMIT_EXCEEDED)]
= _("The length of the server certificate, or the depth of the server certificate chain, exceed the limits imposed by the cryptography library");
const AccountNotification = new Lang.Class({
Name: 'AccountNotification',
Extends: MessageTray.Notification,
AccountNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, account, connectionError) {
this.parent(source,
/* translators: argument is the account name, like
* name@jabber.org for example. */
_("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true });
MessageTray.Notification.prototype._init.call(this, source,
/* translators: argument is the account name, like
* name@jabber.org for example. */
_("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true });
this._label = new St.Label();
this.addActor(this._label);
@ -1493,6 +1542,6 @@ const AccountNotification = new Lang.Class({
this._connectionStatusId = 0;
}
this.parent();
MessageTray.Notification.prototype.destroy.call(this);
}
});
};

View File

@ -202,9 +202,11 @@ function registerSpecialPropertySplitter(name, splitFunction, parameters) {
// time updates; even better is to pay attention to the vertical
// vblank and sync to that when possible.)
//
const ClutterFrameTicker = new Lang.Class({
Name: 'ClutterFrameTicker',
function ClutterFrameTicker() {
this._init();
}
ClutterFrameTicker.prototype = {
FRAME_RATE : 60,
_init : function() {
@ -259,6 +261,6 @@ const ClutterFrameTicker = new Lang.Class({
this._startTime = -1;
global.end_work();
}
});
};
Signals.addSignalMethods(ClutterFrameTicker.prototype);

View File

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const AccountsService = imports.gi.AccountsService;
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
@ -40,12 +41,15 @@ const IMStatus = {
// Copyright (C) 2008,2009 Red Hat, Inc.
const IMStatusItem = new Lang.Class({
Name: 'IMStatusItem',
Extends: PopupMenu.PopupBaseMenuItem,
function IMStatusItem(label, iconName) {
this._init(label, iconName);
}
IMStatusItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(label, iconName) {
this.parent();
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
this.actor.add_style_class_name('status-chooser-status-item');
@ -58,15 +62,19 @@ const IMStatusItem = new Lang.Class({
this.label = new St.Label({ text: label });
this.addActor(this.label);
}
});
};
const IMUserNameItem = new Lang.Class({
Name: 'IMUserNameItem',
Extends: PopupMenu.PopupBaseMenuItem,
function IMUserNameItem() {
this._init();
}
IMUserNameItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function() {
this.parent({ reactive: false,
style_class: 'status-chooser-user-name' });
PopupMenu.PopupBaseMenuItem.prototype._init.call(this,
{ reactive: false,
style_class: 'status-chooser-user-name' });
this._wrapper = new Shell.GenericContainer();
this._wrapper.connect('get-preferred-width',
@ -95,15 +103,19 @@ const IMUserNameItem = new Lang.Class({
_wrapperAllocate: function(actor, box, flags) {
this.label.allocate(box, flags);
}
});
};
const IMStatusChooserItem = new Lang.Class({
Name: 'IMStatusChooserItem',
Extends: PopupMenu.PopupBaseMenuItem,
function IMStatusChooserItem() {
this._init();
}
IMStatusChooserItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function() {
this.parent({ reactive: false,
style_class: 'status-chooser' });
PopupMenu.PopupBaseMenuItem.prototype._init.call (this,
{ reactive: false,
style_class: 'status-chooser' });
this._iconBin = new St.Button({ style_class: 'status-chooser-user-icon' });
this.addActor(this._iconBin);
@ -146,31 +158,21 @@ const IMStatusChooserItem = new Lang.Class({
Lang.bind(this, this._changeIMStatus));
this._presence = new GnomeSession.Presence();
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
this._sessionStatusChanged(status);
}));
this._presence.connect('StatusChanged',
Lang.bind(this, this._sessionStatusChanged));
this._sessionPresenceRestored = false;
this._imPresenceRestored = false;
this._currentPresence = undefined;
this._accountMgr = Tp.AccountManager.dup();
this._accountMgr = Tp.AccountManager.dup()
this._accountMgr.connect('most-available-presence-changed',
Lang.bind(this, this._IMStatusChanged));
this._accountMgr.connect('account-enabled',
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.connect('account-disabled',
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.connect('account-removed',
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.prepare_async(null, Lang.bind(this,
function(mgr) {
let [presence, status, msg] = mgr.get_most_available_presence();
let savedPresence = global.settings.get_int('saved-im-presence');
this._IMAccountsChanged(mgr);
if (savedPresence == presence) {
this._IMStatusChanged(mgr, presence, status, msg);
} else {
@ -197,21 +199,6 @@ const IMStatusChooserItem = new Lang.Class({
}));
},
destroy: function() {
// clean up signal handlers
if (this._userLoadedId != 0) {
this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0;
}
if (this._userChangedId != 0) {
this._user.disconnect(this._userChangedId);
this._userChangedId = 0;
}
this.parent();
},
// Override getColumnWidths()/setColumnWidths() to make the item
// independent from the overall column layout of the menu
getColumnWidths: function() {
@ -280,13 +267,6 @@ const IMStatusChooserItem = new Lang.Class({
}
},
_IMAccountsChanged: function(mgr) {
let accounts = mgr.get_valid_accounts().filter(function(account) {
return account.enabled;
});
this._combo.setSensitive(accounts.length > 0);
},
_IMStatusChanged: function(accountMgr, presence, status, message) {
if (!this._imPresenceRestored)
this._imPresenceRestored = true;
@ -298,12 +278,12 @@ const IMStatusChooserItem = new Lang.Class({
this._setComboboxPresence(presence);
if (!this._sessionPresenceRestored) {
this._sessionStatusChanged(this._presence.status);
this._presence.getStatus(Lang.bind(this, this._sessionStatusChanged));
return;
}
if (presence == Tp.ConnectionPresenceType.AVAILABLE)
this._presence.status = GnomeSession.PresenceStatus.AVAILABLE;
this._presence.setStatus(GnomeSession.PresenceStatus.AVAILABLE);
// We ignore the actual value of _expectedPresence and never safe
// the first presence change after an "automatic" change, assuming
@ -382,14 +362,14 @@ const IMStatusChooserItem = new Lang.Class({
return this._currentPresence;
},
_sessionStatusChanged: function(sessionStatus) {
_sessionStatusChanged: function(sessionPresence, sessionStatus) {
if (!this._imPresenceRestored)
return;
if (!this._sessionPresenceRestored) {
let savedStatus = global.settings.get_int('saved-session-presence');
if (sessionStatus != savedStatus) {
this._presence.status = savedStatus;
this._presence.setStatus(savedStatus);
return;
}
this._sessionPresenceRestored = true;
@ -411,16 +391,18 @@ const IMStatusChooserItem = new Lang.Class({
this._expectedPresence = newPresence;
this._accountMgr.set_all_requested_presences(newPresence, status, msg);
}
});
};
const UserMenuButton = new Lang.Class({
Name: 'UserMenuButton',
Extends: PanelMenu.Button,
function UserMenuButton() {
this._init();
}
UserMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
this.parent(0.0);
PanelMenu.Button.prototype._init.call(this, 0.0);
let box = new St.BoxLayout({ name: 'panelUserMenu' });
this.actor.add_actor(box);
@ -433,7 +415,7 @@ const UserMenuButton = new Lang.Class({
this._session = new GnomeSession.SessionManager();
this._haveShutdown = true;
this._accountMgr = Tp.AccountManager.dup();
this._account_mgr = Tp.AccountManager.dup()
this._upClient = new UPowerGlib.Client();
this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
@ -456,9 +438,13 @@ const UserMenuButton = new Lang.Class({
this._idleIcon = new St.Icon({ icon_name: 'user-idle',
style_class: 'popup-menu-icon' });
this._accountMgr.connect('most-available-presence-changed',
this._presence.connect('StatusChanged',
Lang.bind(this, this._updateSwitch));
this._presence.getStatus(Lang.bind(this, this._updateSwitch));
this._account_mgr.connect('most-available-presence-changed',
Lang.bind(this, this._updatePresenceIcon));
this._accountMgr.prepare_async(null, Lang.bind(this,
this._account_mgr.prepare_async(null, Lang.bind(this,
function(mgr) {
let [presence, s, msg] = mgr.get_most_available_presence();
this._updatePresenceIcon(mgr, presence, s, msg);
@ -471,16 +457,8 @@ const UserMenuButton = new Lang.Class({
this._updateUserName();
this._createSubMenu();
this._updateSwitch(this._presence.status);
this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
this._updateSwitch(status);
}));
this._userManager.connect('notify::is-loaded',
Lang.bind(this, this._updateSwitchUser));
this._userManager.connect('notify::has-multiple-users',
Lang.bind(this, this._updateSwitchUser));
this._userManager.connect('user-added',
Lang.bind(this, this._updateSwitchUser));
this._userManager.connect('user-removed',
@ -525,9 +503,7 @@ const UserMenuButton = new Lang.Class({
_updateSwitchUser: function() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
if (allowSwitch &&
this._userManager.can_switch() &&
this._userManager.has_multiple_users)
if (allowSwitch && this._userManager.can_switch ())
this._loginScreenItem.actor.show();
else
this._loginScreenItem.actor.hide();
@ -581,7 +557,7 @@ const UserMenuButton = new Lang.Class({
}
},
_updateSwitch: function(status) {
_updateSwitch: function(presence, status) {
let active = status == GnomeSession.PresenceStatus.AVAILABLE;
this._notificationsSwitch.setToggleState(active);
},
@ -662,7 +638,7 @@ const UserMenuButton = new Lang.Class({
} else {
status = GnomeSession.PresenceStatus.BUSY;
let [presence, s, msg] = this._accountMgr.get_most_available_presence();
let [presence, s, msg] = this._account_mgr.get_most_available_presence();
let newPresence = this._statusChooser.getIMPresenceForSessionStatus(status);
if (newPresence != presence &&
newPresence == Tp.ConnectionPresenceType.BUSY)
@ -670,7 +646,7 @@ const UserMenuButton = new Lang.Class({
_("Notifications are now disabled, including chat messages. Your online status has been adjusted to let others know that you might not see their messages."));
}
this._presence.status = status;
this._presence.setStatus(status);
},
_onMyAccountActivate: function() {
@ -723,4 +699,4 @@ const UserMenuButton = new Lang.Class({
this._session.ShutdownRemote();
}
}
});
};

View File

@ -15,9 +15,11 @@ const SearchDisplay = imports.ui.searchDisplay;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const BaseTab = new Lang.Class({
Name: 'BaseTab',
function BaseTab(titleActor, pageActor, name, a11yIcon) {
this._init(titleActor, pageActor, name, a11yIcon);
}
BaseTab.prototype = {
_init: function(titleActor, pageActor, name, a11yIcon) {
this.title = titleActor;
this.page = new St.Bin({ child: pageActor,
@ -73,13 +75,16 @@ const BaseTab = new Lang.Class({
_activate: function() {
this.emit('activated');
}
});
};
Signals.addSignalMethods(BaseTab.prototype);
const ViewTab = new Lang.Class({
Name: 'ViewTab',
Extends: BaseTab,
function ViewTab(id, label, pageActor, a11yIcon) {
this._init(id, label, pageActor, a11yIcon);
}
ViewTab.prototype = {
__proto__: BaseTab.prototype,
_init: function(id, label, pageActor, a11yIcon) {
this.id = id;
@ -88,14 +93,17 @@ const ViewTab = new Lang.Class({
style_class: 'view-tab-title' });
titleActor.connect('clicked', Lang.bind(this, this._activate));
this.parent(titleActor, pageActor, label, a11yIcon);
BaseTab.prototype._init.call(this, titleActor, pageActor, label, a11yIcon);
}
});
};
const SearchTab = new Lang.Class({
Name: 'SearchTab',
Extends: BaseTab,
function SearchTab() {
this._init();
}
SearchTab.prototype = {
__proto__: BaseTab.prototype,
_init: function() {
this.active = false;
@ -128,7 +136,11 @@ const SearchTab = new Lang.Class({
this._iconClickedId = 0;
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
this.parent(this._entry, this._searchResults.actor, _("Search"), 'edit-find');
BaseTab.prototype._init.call(this,
this._entry,
this._searchResults.actor,
_("Search"),
'edit-find');
this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
@ -154,7 +166,7 @@ const SearchTab = new Lang.Class({
},
hide: function() {
this.parent();
BaseTab.prototype.hide.call(this);
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
@ -298,12 +310,14 @@ const SearchTab = new Lang.Class({
return false;
}
});
};
const ViewSelector = new Lang.Class({
Name: 'ViewSelector',
function ViewSelector() {
this._init();
}
ViewSelector.prototype = {
_init : function() {
this.actor = new St.BoxLayout({ name: 'viewSelector',
vertical: true });
@ -419,6 +433,29 @@ const ViewSelector = new Lang.Class({
// not when setting the initially selected one.
if (!tab.visible)
tab.show(!firstSwitch);
// Pull a Meg Ryan:
if (!firstSwitch && Main.overview.workspaces) {
if (tab != this._tabs[0]) {
Tweener.addTween(Main.overview.workspaces.actor,
{ opacity: 0,
time: 0.1,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
Main.overview.workspaces.actor.hide();
Main.overview.workspaces.actor.opacity = 255;
})
});
} else {
Main.overview.workspaces.actor.opacity = 0;
Main.overview.workspaces.actor.show();
Tweener.addTween(Main.overview.workspaces.actor,
{ opacity: 255,
time: 0.1,
transition: 'easeOutQuad' });
}
}
},
switchTab: function(id) {
@ -540,5 +577,5 @@ const ViewSelector = new Lang.Class({
removeSearchProvider: function(provider) {
this._searchTab.removeSearchProvider(provider);
}
});
};
Signals.addSignalMethods(ViewSelector.prototype);

View File

@ -1,210 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Search = imports.ui.search;
// we could make these gsettings
const FISH_NAME = 'wanda';
const FISH_SPEED = 300;
const FISH_COMMAND = 'fortune';
const GNOME_PANEL_PIXMAPDIR = '../gnome-panel/pixmaps';
const FISH_GROUP = 'Fish Animation';
const MAGIC_FISH_KEY = 'free the fish';
const WandaIcon = new Lang.Class({
Name: 'WandaIcon',
Extends: IconGrid.BaseIcon,
_init : function(fish, label, params) {
this._fish = fish;
let file = GLib.build_filenamev([global.datadir, GNOME_PANEL_PIXMAPDIR, fish + '.fish']);
if (GLib.file_test(file, GLib.FileTest.EXISTS)) {
this._keyfile = new GLib.KeyFile();
this._keyfile.load_from_file(file, GLib.KeyFileFlags.NONE);
this._imageFile = GLib.build_filenamev([global.datadir, GNOME_PANEL_PIXMAPDIR,
this._keyfile.get_string(FISH_GROUP, 'image')]);
let tmpPixbuf = GdkPixbuf.Pixbuf.new_from_file(this._imageFile);
this._imgHeight = tmpPixbuf.height;
this._imgWidth = tmpPixbuf.width / this._keyfile.get_integer(FISH_GROUP, 'frames');
} else {
this._imageFile = null;
}
this.parent(label, params);
},
createIcon: function(iconSize) {
if (this._animations)
this._animations.destroy();
if (!this._imageFile) {
return new St.Icon({ icon_name: 'face-smile',
icon_type: St.IconType.FULLCOLOR,
icon_size: iconSize
});
}
this._animations = St.TextureCache.get_default().load_sliced_image(this._imageFile, this._imgWidth, this._imgHeight);
this._animations.connect('destroy', Lang.bind(this, function() {
if (this._timeoutId)
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
this._animations = null;
}));
this._animations.connect('notify::mapped', Lang.bind(this, function() {
if (this._animations.mapped && !this._timeoutId) {
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, FISH_SPEED, Lang.bind(this, this._update));
this._i = 0;
this._update();
} else if (!this._animations.mapped && this._timeoutId) {
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
}));
this._i = 0;
return this._animations;
},
_update: function() {
let n = this._animations.get_n_children();
if (n == 0) {
return true;
}
this._animations.get_nth_child(this._i).hide();
this._i = (this._i + 1) % n;
this._animations.get_nth_child(this._i).show();
return true;
},
});
const WandaIconBin = new Lang.Class({
Name: 'WandaIconBin',
_init: function(fish, label, params) {
this.actor = new St.Bin({ style_class: 'search-result-content',
reactive: true,
track_hover: true });
this.icon = new WandaIcon(fish, label, params);
this.actor.child = this.icon.actor;
this.actor.label_actor = this.icon.label;
},
});
const FortuneDialog = new Lang.Class({
Name: 'FortuneDialog',
_init: function(name, command) {
let text;
try {
let [res, stdout, stderr, status] = GLib.spawn_command_line_sync(command);
text = String.fromCharCode.apply(null, stdout);
} catch(e) {
text = _("Sorry, no wisdom for you today:\n%s").format(e.message);
}
this._title = new St.Label({ style_class: 'polkit-dialog-headline',
text: _("%s the Oracle says").format(name) });
this._label = new St.Label({ style_class: 'polkit-dialog-description',
text: text });
this._label.clutter_text.line_wrap = true;
this._box = new St.BoxLayout({ vertical: true,
style_class: 'polkit-dialog' // this is just to force a reasonable width
});
this._box.add(this._title, { align: St.Align.MIDDLE });
this._box.add(this._label, { expand: true });
this._button = new St.Button({ button_mask: St.ButtonMask.ONE,
style_class: 'modal-dialog',
reactive: true });
this._button.connect('clicked', Lang.bind(this, this.destroy));
this._button.child = this._box;
let monitor = Main.layoutManager.primaryMonitor;
Main.layoutManager.addChrome(this._button);
this._button.set_position(Math.floor(monitor.width / 2 - this._button.width / 2),
Math.floor(monitor.height / 2 - this._button.height / 2));
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, Lang.bind(this, this.destroy));
},
destroy: function() {
this._button.destroy();
}
});
function capitalize(str) {
return str[0].toUpperCase() + str.substring(1, str.length);
}
const WandaSearchProvider = new Lang.Class({
Name: 'WandaSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
this.parent(_("Your favorite Easter Egg"));
},
getResultMeta: function(fish) {
return { 'id': fish,
'name': capitalize(fish),
'createIcon': function(iconSize) {
// for DND only (maybe could be improved)
// DON'T use St.Icon here, it crashes the shell
// (dnd.js code assumes it can query the actor size
// without parenting it, while StWidget accesses
// StThemeNode in get_preferred_width/height, which
// triggers an assertion failure)
return St.TextureCache.get_default().load_icon_name(null,
'face-smile',
St.IconType.FULLCOLOR,
iconSize);
}
};
},
getInitialResultSet: function(terms) {
if (terms.join(' ') == MAGIC_FISH_KEY) {
return [ FISH_NAME ];
}
return [];
},
getSubsearchResultSet: function(previousResults, terms) {
return this.getInitialResultSet(terms);
},
activateResult: function(fish, params) {
if (this._dialog)
this._dialog.destroy();
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
},
createResultActor: function (resultMeta, terms) {
let icon = new WandaIconBin(resultMeta.id, resultMeta.name);
return icon.actor;
}
});

View File

@ -6,9 +6,11 @@ const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const WindowAttentionHandler = new Lang.Class({
Name: 'WindowAttentionHandler',
function WindowAttentionHandler() {
this._init();
}
WindowAttentionHandler.prototype = {
_init : function() {
this._tracker = Shell.WindowTracker.get_default();
global.display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
@ -41,14 +43,17 @@ const WindowAttentionHandler = new Lang.Class({
notification.update(title, banner);
})));
}
});
};
const Source = new Lang.Class({
Name: 'WindowAttentionSource',
Extends: MessageTray.Source,
function Source(app, window) {
this._init(app, window);
}
Source.prototype = {
__proto__ : MessageTray.Source.prototype,
_init: function(app, window) {
this.parent(app.get_name());
MessageTray.Source.prototype._init.call(this, app.get_name());
this._window = window;
this._app = app;
this._setSummaryIcon(this.createNotificationIcon());
@ -76,4 +81,4 @@ const Source = new Lang.Class({
Main.activateWindow(this._window);
this.destroy();
}
});
};

View File

@ -31,9 +31,11 @@ function getTopInvisibleBorder(metaWindow) {
return outerRect.y - inputRect.y;
}
const WindowDimmer = new Lang.Class({
Name: 'WindowDimmer',
function WindowDimmer(actor) {
this._init(actor);
}
WindowDimmer.prototype = {
_init: function(actor) {
if (Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL)) {
this._effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
@ -73,7 +75,7 @@ const WindowDimmer = new Lang.Class({
},
_dimFraction: 0.0
});
};
function getWindowDimmer(actor) {
if (!actor._windowDimmer)
@ -82,12 +84,15 @@ function getWindowDimmer(actor) {
return actor._windowDimmer;
}
const WindowManager = new Lang.Class({
Name: 'WindowManager',
function WindowManager() {
this._init();
}
WindowManager.prototype = {
_init : function() {
this._shellwm = global.window_manager;
this._keyBindingHandlers = [];
this._minimizing = [];
this._maximizing = [];
this._unmaximizing = [];
@ -116,24 +121,15 @@ const WindowManager = new Lang.Class({
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
this._workspaceSwitcherPopup = null;
Meta.keybindings_set_custom_handler('switch-to-workspace-left',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-right',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-up',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-down',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-windows',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-windows-backward',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group-backward',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-panels',
Lang.bind(this, this._startA11ySwitcher));
this.setKeybindingHandler('switch_to_workspace_left', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_to_workspace_right', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_to_workspace_up', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_to_workspace_down', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_windows', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_group', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_windows_backward', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_group_backward', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_panels', Lang.bind(this, this._startA11ySwitcher));
Main.overview.connect('showing', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++)
@ -145,6 +141,16 @@ const WindowManager = new Lang.Class({
}));
},
setKeybindingHandler: function(keybinding, handler){
if (this._keyBindingHandlers[keybinding])
this._shellwm.disconnect(this._keyBindingHandlers[keybinding]);
else
this._shellwm.takeover_keybinding(keybinding);
this._keyBindingHandlers[keybinding] =
this._shellwm.connect('keybinding::' + keybinding, handler);
},
blockAnimations: function() {
this._animationBlockCount++;
},
@ -154,7 +160,7 @@ const WindowManager = new Lang.Class({
},
_shouldAnimate : function(actor) {
if (Main.overview.visible || this._animationBlockCount > 0)
if (Main.overview.visible || this._animationsBlocked > 0)
return false;
if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL))
return false;
@ -528,41 +534,37 @@ const WindowManager = new Lang.Class({
shellwm.completed_switch_workspace();
},
_startAppSwitcher : function(display, screen, window, binding) {
_startAppSwitcher : function(shellwm, binding, mask, window, backwards) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.actor.hide();
let tabPopup = new AltTab.AltTabPopup();
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
if (!tabPopup.show(backwards, binding, mask))
tabPopup.destroy();
},
_startA11ySwitcher : function(display, screen, window, binding) {
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
_startA11ySwitcher : function(shellwm, binding, mask, window, backwards) {
Main.ctrlAltTabManager.popup(backwards, mask);
},
_showWorkspaceSwitcher : function(display, screen, window, binding) {
if (screen.n_workspaces == 1)
_showWorkspaceSwitcher : function(shellwm, binding, mask, window, backwards) {
if (global.screen.n_workspaces == 1)
return;
if (this._workspaceSwitcherPopup == null)
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
if (binding.get_name() == 'switch-to-workspace-up')
if (binding == 'switch_to_workspace_up')
this.actionMoveWorkspaceUp();
else if (binding.get_name() == 'switch-to-workspace-down')
else if (binding == 'switch_to_workspace_down')
this.actionMoveWorkspaceDown();
// left/right would effectively act as synonyms for up/down if we enabled them;
// but that could be considered confusing.
// else if (binding.get_name() == 'switch-to-workspace-left')
// else if (binding == 'switch_to_workspace_left')
// this.actionMoveWorkspaceLeft();
// else if (binding.get_name() == 'switch-to-workspace-right')
// else if (binding == 'switch_to_workspace_right')
// this.actionMoveWorkspaceRight();
},
@ -623,4 +625,4 @@ const WindowManager = new Lang.Class({
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate);
}
});
};

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GConf = imports.gi.GConf;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -28,8 +28,7 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100;
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.shell.overrides';
const BUTTON_LAYOUT_KEY = 'button-layout';
const BUTTON_LAYOUT_KEY = '/desktop/gnome/shell/windows/button_layout';
// Define a layout scheme for small window counts. For larger
// counts we fall back to an algorithm. We need more schemes here
@ -56,13 +55,11 @@ function _clamp(value, min, max) {
}
const ScaledPoint = new Lang.Class({
Name: 'ScaledPoint',
_init: function(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
},
function ScaledPoint(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
}
ScaledPoint.prototype = {
getPosition : function() {
return [this.x, this.y];
},
@ -88,17 +85,18 @@ const ScaledPoint = new Lang.Class({
return [_interpolate(this.scaleX, other.scaleX, step),
_interpolate(this.scaleY, other.scaleY, step)];
}
});
};
const WindowClone = new Lang.Class({
Name: 'WindowClone',
function WindowClone(realWindow) {
this._init(realWindow);
}
_init : function(realWindow, workspace) {
WindowClone.prototype = {
_init : function(realWindow) {
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
this.metaWindow._delegate = this;
this._workspace = workspace;
let [borderX, borderY] = this._getInvisibleBorderPadding();
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
@ -384,12 +382,19 @@ const WindowClone = new Lang.Class({
this.emit('drag-begin');
},
_getWorkspaceActor : function() {
let index = this.metaWindow.get_workspace().index();
return Main.overview.workspaces.getWorkspaceByIndex(index);
},
handleDragOver : function(source, actor, x, y, time) {
return this._workspace.handleDragOver(source, actor, x, y, time);
let workspace = this._getWorkspaceActor();
return workspace.handleDragOver(source, actor, x, y, time);
},
acceptDrop : function(source, actor, x, y, time) {
this._workspace.acceptDrop(source, actor, x, y, time);
let workspace = this._getWorkspaceActor();
workspace.acceptDrop(source, actor, x, y, time);
},
_onDragCancelled : function (draggable, time) {
@ -412,7 +417,7 @@ const WindowClone = new Lang.Class({
this.emit('drag-end');
}
});
};
Signals.addSignalMethods(WindowClone.prototype);
@ -421,9 +426,11 @@ Signals.addSignalMethods(WindowClone.prototype);
* @parentActor: The actor which will be the parent of all overlay items
* such as app icon and window caption
*/
const WindowOverlay = new Lang.Class({
Name: 'WindowOverlay',
function WindowOverlay(windowClone, parentActor) {
this._init(windowClone, parentActor);
}
WindowOverlay.prototype = {
_init : function(windowClone, parentActor) {
let metaWindow = windowClone.metaWindow;
@ -488,9 +495,6 @@ const WindowOverlay = new Lang.Class({
},
fadeIn: function() {
if (!this._hidden)
return;
this.show();
this.title.opacity = 0;
this._parentActor.raise_top();
@ -519,12 +523,12 @@ const WindowOverlay = new Lang.Class({
// get_transformed_position() and get_transformed_size(),
// as windowClone might be moving.
// See Workspace._showWindowOverlay
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, animate) {
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight) {
let button = this.closeButton;
let title = this.title;
let settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
let layout = settings.get_string(BUTTON_LAYOUT_KEY);
let gconf = GConf.Client.get_default();
let layout = gconf.get_string(BUTTON_LAYOUT_KEY);
let rtl = St.Widget.get_default_direction() == St.TextDirection.RTL;
let split = layout.split(":");
@ -541,34 +545,15 @@ const WindowOverlay = new Lang.Class({
else
buttonX = cloneX + (cloneWidth - button._overlap);
if (animate)
this._animateOverlayActor(button, Math.floor(buttonX), Math.floor(buttonY), button.width);
else
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
if (!title.fullWidth)
title.fullWidth = title.width;
let titleWidth = Math.min(title.fullWidth, cloneWidth);
title.width = Math.min(title.fullWidth, cloneWidth);
let titleX = cloneX + (cloneWidth - titleWidth) / 2;
let titleX = cloneX + (cloneWidth - title.width) / 2;
let titleY = cloneY + cloneHeight + title._spacing;
if (animate)
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), titleWidth);
else {
title.width = titleWidth;
title.set_position(Math.floor(titleX), Math.floor(titleY));
}
},
_animateOverlayActor: function(actor, x, y, width) {
Tweener.addTween(actor,
{ x: x,
y: y,
width: width,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad'
});
title.set_position(Math.floor(titleX), Math.floor(titleY));
},
_closeWindow: function(actor) {
@ -656,7 +641,7 @@ const WindowOverlay = new Lang.Class({
this._parentActor.queue_relayout();
}
});
};
Signals.addSignalMethods(WindowOverlay.prototype);
const WindowPositionFlags = {
@ -667,9 +652,11 @@ const WindowPositionFlags = {
/**
* @metaWorkspace: a #Meta.Workspace, or null
*/
const Workspace = new Lang.Class({
Name: 'Workspace',
function Workspace(metaWorkspace, monitorIndex) {
this._init(metaWorkspace, monitorIndex);
}
Workspace.prototype = {
_init : function(metaWorkspace, monitorIndex) {
// When dragging a window, we use this slot for reserve space.
this._reservedSlot = null;
@ -1033,7 +1020,7 @@ const Workspace = new Lang.Class({
let [x, y, scale] = this._computeWindowLayout(metaWindow, slot);
if (overlay && initialPositioning)
if (overlay)
overlay.hide();
if (animate && isOnCurrentWorkspace) {
if (!metaWindow.showing_on_its_workspace()) {
@ -1056,11 +1043,20 @@ const Workspace = new Lang.Class({
});
}
this._animateClone(clone, overlay, x, y, scale, initialPositioning);
Tweener.addTween(clone.actor,
{ x: x,
y: y,
scale_x: scale,
scale_y: scale,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._showWindowOverlay(clone, overlay, true);
})
});
} else {
clone.actor.set_position(x, y);
clone.actor.set_scale(scale, scale);
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
}
}
@ -1082,35 +1078,23 @@ const Workspace = new Lang.Class({
}
},
_animateClone: function(clone, overlay, x, y, scale, initialPositioning) {
Tweener.addTween(clone.actor,
{ x: x,
y: y,
scale_x: scale,
scale_y: scale,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._showWindowOverlay(clone, overlay, true);
})
});
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, true);
},
_updateWindowOverlayPositions: function(clone, overlay, x, y, scale, animate) {
let [cloneWidth, cloneHeight] = clone.actor.get_size();
cloneWidth = scale * cloneWidth;
cloneHeight = scale * cloneHeight;
if (overlay)
overlay.updatePositions(x, y, cloneWidth, cloneHeight, animate);
},
_showWindowOverlay: function(clone, overlay, fade) {
if (clone.inDrag)
return;
// This is a little messy and complicated because when we
// start the fade-in we may not have done the final positioning
// of the workspaces. (Tweener doesn't necessarily finish
// all animations before calling onComplete callbacks.)
// So we need to manually compute where the window will
// be after the workspace animation finishes.
let [cloneX, cloneY] = clone.actor.get_position();
let [cloneWidth, cloneHeight] = clone.actor.get_size();
cloneWidth = clone.actor.scale_x * cloneWidth;
cloneHeight = clone.actor.scale_y * cloneHeight;
if (overlay) {
overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
if (fade)
overlay.fadeIn();
else
@ -1128,16 +1112,6 @@ const Workspace = new Lang.Class({
}
},
_hideAllOverlays: function() {
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
Tweener.removeTweens(clone.actor);
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
}
},
_delayedWindowRepositioning: function() {
if (this._windowIsZooming)
return true;
@ -1159,6 +1133,18 @@ const Workspace = new Lang.Class({
return false;
},
showWindowsOverlays: function() {
if (this.leavingOverview)
return;
this._windowOverlaysGroup.show();
this._showAllOverlays();
},
hideWindowsOverlays: function() {
this._windowOverlaysGroup.hide();
},
_doRemoveWindow : function(metaWin) {
let win = metaWin.get_compositor_private();
@ -1312,7 +1298,7 @@ const Workspace = new Lang.Class({
this.leavingOverview = true;
this._hideAllOverlays();
this.hideWindowsOverlays();
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
@ -1403,7 +1389,7 @@ const Workspace = new Lang.Class({
// Create a clone of a (non-desktop) window and add it to the window list
_addWindowClone : function(win) {
let clone = new WindowClone(win, this);
let clone = new WindowClone(win);
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
clone.connect('selected',
@ -1531,6 +1517,6 @@ const Workspace = new Lang.Class({
return false;
}
});
};
Signals.addSignalMethods(Workspace.prototype);

View File

@ -15,9 +15,11 @@ const DISPLAY_TIMEOUT = 600;
const UP = -1;
const DOWN = 1;
const WorkspaceSwitcherPopup = new Lang.Class({
Name: 'WorkspaceSwitcherPopup',
function WorkspaceSwitcherPopup() {
this._init();
}
WorkspaceSwitcherPopup.prototype = {
_init : function() {
this.actor = new St.Group({ reactive: true,
x: 0,
@ -156,4 +158,4 @@ const WorkspaceSwitcherPopup = new Lang.Class({
onCompleteScope: this
});
}
});
};

View File

@ -20,14 +20,11 @@ let MAX_THUMBNAIL_SCALE = 1/8.;
const RESCALE_ANIMATION_TIME = 0.2;
const SLIDE_ANIMATION_TIME = 0.2;
// When we create workspaces by dragging, we add a "cut" into the top and
// bottom of each workspace so that the user doesn't have to hit the
// placeholder exactly.
const WORKSPACE_CUT_SIZE = 10;
const WindowClone = new Lang.Class({
Name: 'WindowClone',
function WindowClone(realWindow) {
this._init(realWindow);
}
WindowClone.prototype = {
_init : function(realWindow) {
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
reactive: true });
@ -51,7 +48,6 @@ const WindowClone = new Lang.Class({
dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
this.inDrag = false;
},
@ -109,10 +105,6 @@ const WindowClone = new Lang.Class({
this.emit('drag-begin');
},
_onDragCancelled : function (draggable, time) {
this.emit('drag-cancelled');
},
_onDragEnd : function (draggable, time, snapback) {
this.inDrag = false;
@ -129,7 +121,7 @@ const WindowClone = new Lang.Class({
this.emit('drag-end');
}
});
};
Signals.addSignalMethods(WindowClone.prototype);
@ -147,13 +139,17 @@ const ThumbnailState = {
/**
* @metaWorkspace: a #Meta.Workspace
*/
const WorkspaceThumbnail = new Lang.Class({
Name: 'WorkspaceThumbnail',
function WorkspaceThumbnail(metaWorkspace) {
this._init(metaWorkspace);
}
WorkspaceThumbnail.prototype = {
_init : function(metaWorkspace) {
this.metaWorkspace = metaWorkspace;
this.monitorIndex = Main.layoutManager.primaryIndex;
this._removed = false;
this.actor = new St.Group({ reactive: true,
clip_to_allocation: true,
style_class: 'workspace-thumbnail' });
@ -179,17 +175,21 @@ const WorkspaceThumbnail = new Lang.Class({
let monitor = Main.layoutManager.primaryMonitor;
this.setPorthole(monitor.x, monitor.y, monitor.width, monitor.height);
let windows = global.get_window_actors().filter(this._isMyWindow, this);
let windows = global.get_window_actors().filter(this._isWorkspaceWindow, this);
// Create clones for windows that should be visible in the Overview
this._windows = [];
this._allWindows = [];
this._minimizedChangedIds = [];
for (let i = 0; i < windows.length; i++) {
windows[i].meta_window._minimizedChangedId =
let minimizedChangedId =
windows[i].meta_window.connect('notify::minimized',
Lang.bind(this,
this._updateMinimized));
this._allWindows.push(windows[i].meta_window);
this._minimizedChangedIds.push(minimizedChangedId);
if (this._isOverviewWindow(windows[i])) {
if (this._isMyWindow(windows[i]) && this._isOverviewWindow(windows[i])) {
this._addWindowClone(windows[i]);
}
}
@ -274,17 +274,11 @@ const WorkspaceThumbnail = new Lang.Class({
let clone = this._windows[index];
this._windows.splice(index, 1);
if (win && this._isOverviewWindow(win)) {
if (metaWin._minimizedChangedId) {
metaWin.disconnect(metaWin._minimizedChangedId);
delete metaWin._minimizedChangedId;
}
}
clone.destroy();
},
_doAddWindow : function(metaWin) {
if (this.leavingOverview)
if (this._removed)
return;
let win = metaWin.get_compositor_private();
@ -294,7 +288,7 @@ const WorkspaceThumbnail = new Lang.Class({
// the compositor finds out about them...
Mainloop.idle_add(Lang.bind(this,
function () {
if (this.actor &&
if (!this._removed &&
metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace)
this._doAddWindow(metaWin);
@ -303,16 +297,19 @@ const WorkspaceThumbnail = new Lang.Class({
return;
}
if (this._allWindows.indexOf(metaWin) == -1) {
let minimizedChangedId = metaWin.connect('notify::minimized',
Lang.bind(this,
this._updateMinimized));
this._allWindows.push(metaWin);
this._minimizedChangedIds.push(minimizedChangedId);
}
// We might have the window in our list already if it was on all workspaces and
// now was moved to this workspace
if (this._lookupIndex (metaWin) != -1)
return;
if (!metaWin._minimizedChangedId)
metaWin._minimizedChangedId = metaWin.connect('notify::minimized',
Lang.bind(this,
this._updateMinimized));
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
return;
@ -324,6 +321,13 @@ const WorkspaceThumbnail = new Lang.Class({
},
_windowRemoved : function(metaWorkspace, metaWin) {
let index = this._allWindows.indexOf(metaWin);
if (index != -1) {
metaWin.disconnect(this._minimizedChangedIds[index]);
this._allWindows.splice(index, 1);
this._minimizedChangedIds.splice(index, 1);
}
this._doRemoveWindow(metaWin);
},
@ -350,27 +354,36 @@ const WorkspaceThumbnail = new Lang.Class({
this.actor.destroy();
},
_onDestroy: function(actor) {
workspaceRemoved : function() {
if (this._removed)
return;
this._removed = true;
this.metaWorkspace.disconnect(this._windowAddedId);
this.metaWorkspace.disconnect(this._windowRemovedId);
global.screen.disconnect(this._windowEnteredMonitorId);
global.screen.disconnect(this._windowLeftMonitorId);
for (let i = 0; i < this._windows.length; i++) {
let metaWin = this._windows[i].metaWindow;
if (metaWin._minimizedChangedId) {
metaWin.disconnect(metaWin._minimizedChangedId);
delete metaWin._minimizedChangedId;
}
}
for (let i = 0; i < this._allWindows.length; i++)
this._allWindows[i].disconnect(this._minimizedChangedIds[i]);
},
_onDestroy: function(actor) {
this.workspaceRemoved();
this._windows = [];
this.actor = null;
},
// Tests if @win belongs to this workspace
_isWorkspaceWindow : function (win) {
return Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index());
},
// Tests if @win belongs to this workspace and monitor
_isMyWindow : function (win) {
return Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index()) &&
return this._isWorkspaceWindow(win) &&
(!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex);
},
@ -391,10 +404,6 @@ const WorkspaceThumbnail = new Lang.Class({
Lang.bind(this, function(clone) {
Main.overview.beginWindowDrag();
}));
clone.connect('drag-cancelled',
Lang.bind(this, function(clone) {
Main.overview.cancelledWindowDrag();
}));
clone.connect('drag-end',
Lang.bind(this, function(clone) {
Main.overview.endWindowDrag();
@ -432,11 +441,6 @@ const WorkspaceThumbnail = new Lang.Class({
if (this.state > ThumbnailState.NORMAL)
return DND.DragMotionResult.CONTINUE;
let [w, h] = this.actor.get_transformed_size();
// Bubble up if we're in the "workspace cut".
if (y < WORKSPACE_CUT_SIZE || y > h - WORKSPACE_CUT_SIZE)
return DND.DragMotionResult.CONTINUE;
if (source.realWindow && !this._isMyWindow(source.realWindow))
return DND.DragMotionResult.MOVE_DROP;
if (source.shellWorkspaceLaunch)
@ -474,21 +478,22 @@ const WorkspaceThumbnail = new Lang.Class({
return false;
}
});
};
Signals.addSignalMethods(WorkspaceThumbnail.prototype);
const ThumbnailsBox = new Lang.Class({
Name: 'ThumbnailsBox',
function ThumbnailsBox() {
this._init();
}
ThumbnailsBox.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'workspace-thumbnails',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
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.actor._delegate = this;
// When we animate the scale, we don't animate the requested size of the thumbnails, rather
// we ask for our final size and then animate within that size. This slightly simplifies the
@ -512,10 +517,6 @@ const ThumbnailsBox = new Lang.Class({
this._indicator = indicator;
this.actor.add_actor(indicator);
this._dropPlaceholderPos = -1;
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
this.actor.add_actor(this._dropPlaceholder);
this._targetScale = 0;
this._scale = 0;
this._pendingScaleUpdate = false;
@ -530,83 +531,6 @@ const ThumbnailsBox = new Lang.Class({
this._thumbnails = [];
},
// Draggable target interface
handleDragOver : function(source, actor, x, y, time) {
if (!source.realWindow && !source.shellWorkspaceLaunch)
return DND.DragMotionResult.CONTINUE;
let spacing = this.actor.get_theme_node().get_length('spacing');
let thumbHeight = this._porthole.height * this._scale;
let workspace = -1;
let firstThumbY = this._thumbnails[0].actor.y;
for (let i = 0; i < this._thumbnails.length; i ++) {
let targetBase = firstThumbY + (thumbHeight + spacing) * i;
// Allow the reorder target to have a 10px "cut" into
// each side of the thumbnail, to make dragging onto the
// placeholder easier
let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE;
let targetBottom = targetBase + WORKSPACE_CUT_SIZE;
// Expand the target to include the placeholder, if it exists.
if (i == this._dropPlaceholderPos)
targetBottom += this._dropPlaceholder.get_height();
if (y > targetTop && y <= targetBottom) {
workspace = i;
break;
}
}
this._dropPlaceholderPos = workspace;
this.actor.queue_relayout();
if (workspace == -1)
return DND.DragMotionResult.CONTINUE;
return DND.DragMotionResult.MOVE_DROP;
},
acceptDrop: function(source, actor, x, y, time) {
if (this._dropPlaceholderPos == -1)
return false;
if (!source.realWindow && !source.shellWorkspaceLaunch)
return false;
let isWindow = !!source.realWindow;
// To create a new workspace, we first slide all the windows on workspaces
// below us to the next workspace, leaving a blank workspace for us to recycle.
let newWorkspaceIndex;
[newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1];
// Nab all the windows below us.
let windows = global.get_window_actors().filter(function(win) {
if (isWindow)
return win.get_workspace() >= newWorkspaceIndex && win != source;
else
return win.get_workspace() >= newWorkspaceIndex;
});
// ... move them down one.
windows.forEach(function(win) {
win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
true, time);
});
if (isWindow)
// ... and bam, a workspace, good as new.
source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
true, time);
else if (source.shellWorkspaceLaunch)
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time });
return true;
},
show: function() {
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
@ -679,8 +603,10 @@ const ThumbnailsBox = new Lang.Class({
if (thumbnail.state > ThumbnailState.NORMAL)
continue;
if (currentPos >= start && currentPos < start + count)
if (currentPos >= start && currentPos < start + count) {
thumbnail.workspaceRemoved();
this._setThumbnailState(thumbnail, ThumbnailState.REMOVING);
}
currentPos++;
}
@ -935,18 +861,20 @@ const ThumbnailsBox = new Lang.Class({
let y = contentBox.y1;
if (this._dropPlaceholderPos == -1) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._dropPlaceholder.hide();
}));
}
for (let i = 0; i < this._thumbnails.length; i++) {
let thumbnail = this._thumbnails[i];
if (i > 0)
y += spacing - Math.round(thumbnail.collapseFraction * spacing);
// We might end up with thumbnailHeight being something like 99.33
// pixels. To make this work and not end up with a gap at the bottom,
// we need some thumbnails to be 99 pixels and some 100 pixels height;
// we compute an actual scale separately for each thumbnail.
let y1 = Math.round(y);
let y2 = Math.round(y + thumbnailHeight);
let roundedVScale = (y2 - y1) / portholeHeight;
let x1, x2;
if (rtl) {
x1 = contentBox.x1 + slideOffset * thumbnail.slidePosition;
@ -956,27 +884,6 @@ const ThumbnailsBox = new Lang.Class({
x2 = x1 + thumbnailWidth;
}
if (i == this._dropPlaceholderPos) {
let [minHeight, placeholderHeight] = this._dropPlaceholder.get_preferred_height(-1);
childBox.x1 = x1;
childBox.x2 = x1 + thumbnailWidth;
childBox.y1 = Math.round(y);
childBox.y2 = Math.round(y + placeholderHeight);
this._dropPlaceholder.allocate(childBox, flags);
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._dropPlaceholder.show();
}));
y += placeholderHeight + spacing;
}
// We might end up with thumbnailHeight being something like 99.33
// pixels. To make this work and not end up with a gap at the bottom,
// we need some thumbnails to be 99 pixels and some 100 pixels height;
// we compute an actual scale separately for each thumbnail.
let y1 = Math.round(y);
let y2 = Math.round(y + thumbnailHeight);
let roundedVScale = (y2 - y1) / portholeHeight;
if (thumbnail.metaWorkspace == indicatorWorkspace)
indicatorY = y1;
@ -1031,4 +938,4 @@ const ThumbnailsBox = new Lang.Class({
onCompleteScope: this
});
}
});
};

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -20,14 +19,15 @@ const WORKSPACE_SWITCH_TIME = 0.25;
// Note that mutter has a compile-time limit of 36
const MAX_WORKSPACES = 16;
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
const CONTROLS_POP_IN_TIME = 0.1;
const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView',
function WorkspacesView(workspaces) {
this._init(workspaces);
}
WorkspacesView.prototype = {
_init: function(workspaces) {
this.actor = new St.Group({ style_class: 'workspaces-view' });
@ -42,6 +42,8 @@ const WorkspacesView = new Lang.Class({
this._spacing = node.get_length('spacing');
this._updateWorkspaceActors(false);
}));
this.actor.connect('notify::mapped',
Lang.bind(this, this._onMappedChanged));
this._width = 0;
this._height = 0;
@ -59,11 +61,6 @@ const WorkspacesView = new Lang.Class({
this._zoomOut = false; // zoom to a larger area
this._inDrag = false; // dragging a window
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._updateExtraWorkspacesId =
this._settings.connect('changed::workspaces-only-on-primary',
Lang.bind(this, this._updateExtraWorkspaces));
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
this._workspaces = workspaces;
@ -72,7 +69,17 @@ const WorkspacesView = new Lang.Class({
this._workspaces[w].actor.reparent(this.actor);
this._workspaces[activeWorkspaceIndex].actor.raise_top();
this._updateExtraWorkspaces();
this._extraWorkspaces = [];
let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
if (i == Main.layoutManager.primaryIndex)
continue;
let ws = new Workspace.Workspace(null, i);
this._extraWorkspaces[m++] = ws;
ws.setGeometry(monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
global.overlay_group.add_actor(ws.actor);
}
// Position/scale the desktop windows and their children after the
// workspaces have been created. This cannot be done first because
@ -83,8 +90,6 @@ const WorkspacesView = new Lang.Class({
Lang.bind(this, function() {
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomToOverview();
if (!this._extraWorkspaces)
return;
for (let w = 0; w < this._extraWorkspaces.length; w++)
this._extraWorkspaces[w].zoomToOverview();
}));
@ -95,14 +100,14 @@ const WorkspacesView = new Lang.Class({
this._clipWidth, this._clipHeight);
}));
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: this._workspaces.length });
this.scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: this._workspaces.length });
this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
@ -116,35 +121,8 @@ const WorkspacesView = new Lang.Class({
Lang.bind(this, this._dragBegin));
this._windowDragEndId = Main.overview.connect('window-drag-end',
Lang.bind(this, this._dragEnd));
},
_updateExtraWorkspaces: function() {
this._destroyExtraWorkspaces();
if (!this._settings.get_boolean('workspaces-only-on-primary'))
return;
this._extraWorkspaces = [];
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
if (i == Main.layoutManager.primaryIndex)
continue;
let ws = new Workspace.Workspace(null, i);
ws.setGeometry(monitors[i].x, monitors[i].y,
monitors[i].width, monitors[i].height);
global.overlay_group.add_actor(ws.actor);
this._extraWorkspaces.push(ws);
}
},
_destroyExtraWorkspaces: function() {
if (!this._extraWorkspaces)
return;
for (let m = 0; m < this._extraWorkspaces.length; m++)
this._extraWorkspaces[m].destroy();
this._extraWorkspaces = null;
this._swipeScrollBeginId = 0;
this._swipeScrollEndId = 0;
},
setGeometry: function(x, y, width, height, spacing) {
@ -181,6 +159,10 @@ const WorkspacesView = new Lang.Class({
return this._workspaces[active];
},
getWorkspaceByIndex: function(index) {
return this._workspaces[index];
},
hide: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
@ -191,8 +173,6 @@ const WorkspacesView = new Lang.Class({
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomFromOverview();
if (!this._extraWorkspaces)
return;
for (let w = 0; w < this._extraWorkspaces.length; w++)
this._extraWorkspaces[w].zoomFromOverview();
},
@ -204,8 +184,6 @@ const WorkspacesView = new Lang.Class({
syncStacking: function(stackIndices) {
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].syncStacking(stackIndices);
if (!this._extraWorkspaces)
return;
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].syncStacking(stackIndices);
},
@ -267,8 +245,10 @@ const WorkspacesView = new Lang.Class({
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
if (this._animating || this._scrolling) {
workspace.hideWindowsOverlays();
workspace.actor.show();
} else {
workspace.showWindowsOverlays();
if (this._inDrag)
workspace.actor.visible = (Math.abs(w - active) <= 1);
else
@ -284,7 +264,7 @@ const WorkspacesView = new Lang.Class({
this._animatingScroll = true;
if (showAnimation) {
Tweener.addTween(this.scrollAdjustment, {
Tweener.addTween(this._scrollAdjustment, {
value: index,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad',
@ -294,7 +274,7 @@ const WorkspacesView = new Lang.Class({
})
});
} else {
this.scrollAdjustment.value = index;
this._scrollAdjustment.value = index;
this._animatingScroll = false;
}
},
@ -302,7 +282,7 @@ const WorkspacesView = new Lang.Class({
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
let active = global.screen.get_active_workspace_index();
Tweener.addTween(this.scrollAdjustment,
Tweener.addTween(this._scrollAdjustment,
{ upper: newNumWorkspaces,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad'
@ -329,12 +309,12 @@ const WorkspacesView = new Lang.Class({
},
_onDestroy: function() {
this._destroyExtraWorkspaces();
this.scrollAdjustment.run_dispose();
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].destroy();
this._scrollAdjustment.run_dispose();
Main.overview.disconnect(this._overviewShowingId);
Main.overview.disconnect(this._overviewShownId);
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
this._settings.disconnect(this._updateExtraWorkspacesId);
if (this._inDrag)
this._dragEnd();
@ -357,6 +337,21 @@ const WorkspacesView = new Lang.Class({
}
},
_onMappedChanged: function() {
if (this.actor.mapped) {
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(this._scrollAdjustment,
direction);
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
Lang.bind(this, this._swipeScrollBegin));
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
Lang.bind(this, this._swipeScrollEnd));
} else {
Main.overview.disconnect(this._swipeScrollBeginId);
Main.overview.disconnect(this._swipeScrollEndId);
}
},
_dragBegin: function() {
if (this._scrolling)
return;
@ -378,9 +373,6 @@ const WorkspacesView = new Lang.Class({
this._firstDragMotion = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
if (!this._extraWorkspaces)
return DND.DragMotionResult.CONTINUE;
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
}
@ -394,18 +386,15 @@ const WorkspacesView = new Lang.Class({
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(null);
if (!this._extraWorkspaces)
return;
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].setReservedSlot(null);
},
startSwipeScroll: function() {
_swipeScrollBegin: function() {
this._scrolling = true;
},
endSwipeScroll: function(result) {
_swipeScrollEnd: function(overview, result) {
this._scrolling = false;
if (result == Overview.SwipeScrollResult.CLICK) {
@ -454,6 +443,7 @@ const WorkspacesView = new Lang.Class({
let dy = newY - currentY;
for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].hideWindowsOverlays();
this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
this._workspaces[i].actor.y += dy;
}
@ -462,20 +452,20 @@ const WorkspacesView = new Lang.Class({
_getWorkspaceIndexToRemove: function() {
return global.screen.get_active_workspace_index();
}
});
};
Signals.addSignalMethods(WorkspacesView.prototype);
const WorkspacesDisplay = new Lang.Class({
Name: 'WorkspacesDisplay',
function WorkspacesDisplay() {
this._init();
}
WorkspacesDisplay.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.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
this.actor.set_clip_to_allocation(true);
let controls = new St.Bin({ style_class: 'workspace-controls',
@ -492,19 +482,12 @@ const WorkspacesDisplay = new Lang.Class({
controls.connect('scroll-event',
Lang.bind(this, this._onScrollEvent));
this._primaryIndex = Main.layoutManager.primaryIndex;
this._monitorIndex = Main.layoutManager.primaryIndex;
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
controls.add_actor(this._thumbnailsBox.actor);
this._workspacesViews = null;
this._primaryScrollAdjustment = null;
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._settings.connect('changed::workspaces-only-on-primary',
Lang.bind(this,
this._workspacesOnlyOnPrimaryChanged));
this._workspacesOnlyOnPrimaryChanged();
this.workspacesView = null;
this._inDrag = false;
this._cancelledDrag = false;
@ -515,8 +498,6 @@ const WorkspacesDisplay = new Lang.Class({
this._updateAlwaysZoom();
// If we stop hiding the overview on layout changes, we will need to
// update the _workspacesViews here
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom));
Main.xdndHandler.connect('drag-begin', Lang.bind(this, function(){
@ -537,9 +518,6 @@ const WorkspacesDisplay = new Lang.Class({
this._windowDragBeginId = 0;
this._windowDragCancelledId = 0;
this._windowDragEndId = 0;
this._notifyOpacityId = 0;
this._swipeScrollBeginId = 0;
this._swipeScrollEndId = 0;
},
show: function() {
@ -550,7 +528,16 @@ const WorkspacesDisplay = new Lang.Class({
this._controls.show();
this._thumbnailsBox.show();
this._updateWorkspacesViews();
this._workspaces = [];
for (let i = 0; i < global.screen.n_workspaces; i++) {
let metaWorkspace = global.screen.get_workspace_by_index(i);
this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
}
if (this.workspacesView)
this.workspacesView.destroy();
this.workspacesView = new WorkspacesView(this._workspaces);
this._updateWorkspacesGeometry();
this._restackedNotifyId =
global.screen.connect('restacked',
@ -581,12 +568,6 @@ const WorkspacesDisplay = new Lang.Class({
this._onRestacked();
},
zoomFromOverview: function() {
for (let i = 0; i < this._workspacesViews.length; i++) {
this._workspacesViews[i].hide();
}
},
hide: function() {
this._controls.hide();
this._thumbnailsBox.hide();
@ -620,120 +601,12 @@ const WorkspacesDisplay = new Lang.Class({
this._windowDragEndId = 0;
}
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy();
this._workspacesViews = null;
for (let i = 0; i < this._workspaces.length; i++)
for (let w = 0; w < this._workspaces[i].length; w++) {
this._workspaces[i][w].disconnectAll();
this._workspaces[i][w].destroy();
}
},
_setupSwipeScrolling: function() {
if (this._swipeScrollBeginId)
Main.overview.disconnect(this._swipeScrollBeginId);
this._swipeScrollBeginId = 0;
if (this._swipeScrollEndId)
Main.overview.disconnect(this._swipeScrollEndId);
this._swipeScrollEndId = 0;
if (!this.actor.mapped)
return;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(this._scrollAdjustment,
direction);
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
Lang.bind(this, function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
}));
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
Lang.bind(this, function(overview, result) {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll(result);
}));
},
_workspacesOnlyOnPrimaryChanged: function() {
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
if (!Main.overview.visible)
return;
this._updateWorkspacesViews();
},
_updateWorkspacesViews: function() {
if (this._workspacesViews)
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy();
if (this._workspaces)
for (let i = 0; i < this._workspaces.length; i++)
for (let w = 0; w < this._workspaces[i].length; w++)
this._workspaces[i][w].destroy();
this._workspacesViews = [];
this._workspaces = [];
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
if (this._workspacesOnlyOnPrimary && i != this._primaryIndex)
continue; // we are only interested in the primary monitor
let monitorWorkspaces = [];
for (let w = 0; w < global.screen.n_workspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
monitorWorkspaces.push(new Workspace.Workspace(metaWorkspace, i));
}
this._workspaces.push(monitorWorkspaces);
let view = new WorkspacesView(monitorWorkspaces);
if (this._workspacesOnlyOnPrimary || i == this._primaryIndex) {
this._scrollAdjustment = view.scrollAdjustment;
this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._scrollValueChanged));
this._setupSwipeScrolling();
}
this._workspacesViews.push(view);
this.workspacesView.destroy();
this.workspacesView = null;
for (let w = 0; w < this._workspaces.length; w++) {
this._workspaces[w].disconnectAll();
this._workspaces[w].destroy();
}
this._updateWorkspacesGeometry();
for (let i = 0; i < this._workspacesViews.length; i++)
global.overlay_group.add_actor(this._workspacesViews[i].actor);
},
_scrollValueChanged: function() {
if (this._workspacesOnlyOnPrimary)
return;
for (let i = 0; i < this._workspacesViews.length; i++) {
if (i == this._primaryIndex)
continue;
let adjustment = this._workspacesViews[i].scrollAdjustment;
// the adjustments work in terms of workspaces, so the
// values map directly
adjustment.value = this._scrollAdjustment.value;
}
},
_getPrimaryView: function() {
if (!this._workspacesViews)
return null;
if (this._workspacesOnlyOnPrimary)
return this._workspacesViews[0];
else
return this._workspacesViews[this._primaryIndex];
},
activeWorkspaceHasMaximizedWindows: function() {
return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows();
},
// zoomFraction property allows us to tween the controls sliding in and out
@ -806,37 +679,8 @@ const WorkspacesDisplay = new Lang.Class({
this._updateWorkspacesGeometry();
},
_parentSet: function(actor, oldParent) {
if (oldParent && this._notifyOpacityId)
oldParent.disconnect(this._notifyOpacityId);
this._notifyOpacityId = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function() {
let newParent = this.actor.get_parent();
if (!newParent)
return;
// This is kinda hackish - we want the primary view to
// appear as parent of this.actor, though in reality it
// is added directly to overlay_group
this._notifyOpacityId = newParent.connect('notify::opacity',
Lang.bind(this, function() {
let opacity = this.actor.get_parent().opacity;
let primaryView = this._getPrimaryView();
if (!primaryView)
return;
primaryView.actor.opacity = opacity;
if (opacity == 0)
primaryView.actor.hide();
else
primaryView.actor.show();
}));
}));
},
_updateWorkspacesGeometry: function() {
if (!this._workspacesViews)
if (!this.workspacesView)
return;
let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
@ -857,6 +701,8 @@ const WorkspacesDisplay = new Lang.Class({
let clipX = rtl ? x + controlsVisible : x;
let clipY = y + (fullHeight - clipHeight) / 2;
this.workspacesView.setClipRect(clipX, clipY, clipWidth, clipHeight);
if (this._zoomOut) {
width -= controlsNatural;
if (rtl)
@ -871,28 +717,7 @@ const WorkspacesDisplay = new Lang.Class({
let difference = fullHeight - height;
y += difference / 2;
let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
if (i == this._primaryIndex) {
this._workspacesViews[m].setClipRect(clipX, clipY,
clipWidth, clipHeight);
this._workspacesViews[m].setGeometry(x, y, width, height,
difference);
m++;
} else if (!this._workspacesOnlyOnPrimary) {
this._workspacesViews[m].setClipRect(monitors[i].x,
monitors[i].y,
monitors[i].width,
monitors[i].height);
this._workspacesViews[m].setGeometry(monitors[i].x,
monitors[i].y,
monitors[i].width,
monitors[i].height, 0);
m++;
}
}
this.workspacesView.setGeometry(x, y, width, height, difference);
},
_onRestacked: function() {
@ -904,14 +729,12 @@ const WorkspacesDisplay = new Lang.Class({
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
}
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].syncStacking(stackIndices);
this.workspacesView.syncStacking(stackIndices);
this._thumbnailsBox.syncStacking(stackIndices);
},
_workspacesChanged: function() {
let oldNumWorkspaces = this._workspaces[0].length;
let oldNumWorkspaces = this._workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
let active = global.screen.get_active_workspace_index();
@ -921,24 +744,15 @@ const WorkspacesDisplay = new Lang.Class({
this._updateAlwaysZoom();
this._updateZoom();
if (this._workspacesViews == null)
if (this.workspacesView == null)
return;
let lostWorkspaces = [];
if (newNumWorkspaces > oldNumWorkspaces) {
let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
if (this._workspacesOnlyOnPrimaryChanged &&
i != this._primaryIndex)
continue;
// Assume workspaces are only added at the end
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
this._workspaces[m++][w] =
new Workspace.Workspace(metaWorkspace, i);
}
// Assume workspaces are only added at the end
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
this._workspaces[w] = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
}
this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
@ -949,28 +763,25 @@ const WorkspacesDisplay = new Lang.Class({
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
if (this._workspaces[0][w].metaWorkspace != metaWorkspace) {
if (this._workspaces[w].metaWorkspace != metaWorkspace) {
removedIndex = w;
break;
}
}
for (let i = 0; i < this._workspaces.length; i++) {
lostWorkspaces = this._workspaces[i].splice(removedIndex,
removedNum);
lostWorkspaces = this._workspaces.splice(removedIndex,
removedNum);
for (let l = 0; l < lostWorkspaces.length; l++) {
lostWorkspaces[l].disconnectAll();
lostWorkspaces[l].destroy();
}
for (let l = 0; l < lostWorkspaces.length; l++) {
lostWorkspaces[l].disconnectAll();
lostWorkspaces[l].destroy();
}
this._thumbnailsBox.removeThumbmails(removedIndex, removedNum);
}
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces,
newNumWorkspaces);
this.workspacesView.updateWorkspaces(oldNumWorkspaces,
newNumWorkspaces);
},
_updateZoom : function() {
@ -982,7 +793,7 @@ const WorkspacesDisplay = new Lang.Class({
this._zoomOut = shouldZoom;
this._updateWorkspacesGeometry();
if (!this._workspacesViews)
if (!this.workspacesView)
return;
Tweener.addTween(this,
@ -990,8 +801,7 @@ const WorkspacesDisplay = new Lang.Class({
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad' });
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].updateWindowPositions();
this.workspacesView.updateWindowPositions();
}
},
@ -1042,5 +852,5 @@ const WorkspacesDisplay = new Lang.Class({
break;
}
}
});
};
Signals.addSignalMethods(WorkspacesDisplay.prototype);

View File

@ -6,9 +6,11 @@ const Shell = imports.gi.Shell;
const Signals = imports.signals;
const DND = imports.ui.dnd;
const XdndHandler = new Lang.Class({
Name: 'XdndHandler',
function XdndHandler() {
this._init();
}
XdndHandler.prototype = {
_init: function() {
// Used to display a clone of the cursor window when the
// window group is hidden (like it happens in the overview)
@ -123,6 +125,6 @@ const XdndHandler = new Lang.Class({
pickedActor = pickedActor.get_parent();
}
}
});
}
Signals.addSignalMethods(XdndHandler.prototype);

View File

@ -35,7 +35,6 @@ kn
ku
lt
lv
mk
mr
ms
nb

View File

@ -36,7 +36,6 @@ js/ui/status/volume.js
js/ui/telepathyClient.js
js/ui/userMenu.js
js/ui/viewSelector.js
js/ui/wanda.js
js/ui/windowAttentionHandler.js
src/gvc/gvc-mixer-control.c
src/main.c

111
po/bg.po
View File

@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Project-Id-Version: gnome-shell gnome-3-2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-10-21 23:34+0300\n"
"PO-Revision-Date: 2011-10-21 23:34+0300\n"
"POT-Creation-Date: 2011-10-21 23:30+0300\n"
"PO-Revision-Date: 2011-10-21 23:30+0300\n"
"Last-Translator: Ivaylo Valkov <ivaylo@e-valkov.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@ -204,7 +204,7 @@ msgid "Not listed?"
msgstr "Липсва в списъка?"
#: ../js/gdm/loginDialog.js:1035 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:520 ../js/ui/networkAgent.js:148
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:148
#: ../js/ui/polkitAuthenticationAgent.js:173 ../js/ui/status/bluetooth.js:480
msgid "Cancel"
msgstr "Отказване"
@ -218,16 +218,18 @@ msgstr "Регистриране"
msgid "Login Window"
msgstr "Екран за идентификация"
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:569
#: ../js/ui/userMenu.js:571 ../js/ui/userMenu.js:640
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:554
#: ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:625
msgid "Suspend"
msgstr "Приспиване"
#: ../js/gdm/powerMenu.js:121
#: ../js/gdm/powerMenu.js:121 ../js/ui/endSessionDialog.js:89
#: ../js/ui/endSessionDialog.js:97 ../js/ui/endSessionDialog.js:106
msgid "Restart"
msgstr "Рестартиране"
#: ../js/gdm/powerMenu.js:126
#: ../js/gdm/powerMenu.js:126 ../js/ui/endSessionDialog.js:80
#: ../js/ui/endSessionDialog.js:91
msgid "Power Off"
msgstr "Изключване"
@ -530,12 +532,10 @@ msgstr "СКОРО ОТВАРЯНИ"
#: ../js/ui/endSessionDialog.js:60
#, c-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Изход на „%s“"
#: ../js/ui/endSessionDialog.js:61
msgctxt "title"
#: ../js/ui/endSessionDialog.js:61 ../js/ui/endSessionDialog.js:75
msgid "Log Out"
msgstr "Изход"
@ -564,16 +564,6 @@ msgstr[1] "Ще излезете от системата автоматично
msgid "Logging out of the system."
msgstr "Излизане от системата."
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "Изход"
#: ../js/ui/endSessionDialog.js:80
msgctxt "title"
msgid "Power Off"
msgstr "Изключване"
#: ../js/ui/endSessionDialog.js:81
msgid "Click Power Off to quit these applications and power off the system."
msgstr ""
@ -591,21 +581,6 @@ msgstr[1] "Системата ще се изключи автоматично с
msgid "Powering off the system."
msgstr "Изключване на системата."
#: ../js/ui/endSessionDialog.js:89 ../js/ui/endSessionDialog.js:106
msgctxt "button"
msgid "Restart"
msgstr "Рестартиране"
#: ../js/ui/endSessionDialog.js:91
msgctxt "button"
msgid "Power Off"
msgstr "Изключване"
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "Рестартиране"
#: ../js/ui/endSessionDialog.js:98
msgid "Click Restart to quit these applications and restart the system."
msgstr ""
@ -623,11 +598,11 @@ msgstr[1] "Системата ще се рестартира автоматич
msgid "Restarting the system."
msgstr "Рестартиране на системата."
#: ../js/ui/extensionSystem.js:524
#: ../js/ui/extensionSystem.js:481
msgid "Install"
msgstr "Инсталиране"
#: ../js/ui/extensionSystem.js:528
#: ../js/ui/extensionSystem.js:485
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Да се изтегли и инсталира ли „%s“ от from extensions.gnome.org?"
@ -640,51 +615,37 @@ msgstr "област за уведомяване"
msgid "Keyboard"
msgstr "Клавиатура"
#: ../js/ui/lookingGlass.js:664
#: ../js/ui/lookingGlass.js:646
msgid "No extensions installed"
msgstr "Няма инсталирани разширения"
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:719
#, c-format
msgid "%s has not emitted any errors."
msgstr "Разширението %s не е обозначило никави грешки."
#: ../js/ui/lookingGlass.js:725
msgid "Hide Errors"
msgstr "Скриване на грешките"
#: ../js/ui/lookingGlass.js:729 ../js/ui/lookingGlass.js:779
msgid "Show Errors"
msgstr "Показване на грешките"
#: ../js/ui/lookingGlass.js:738
#: ../js/ui/lookingGlass.js:692
msgid "Enabled"
msgstr "Включено"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:740 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:694 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Изключено"
#: ../js/ui/lookingGlass.js:742
#: ../js/ui/lookingGlass.js:696
msgid "Error"
msgstr "Грешка"
#: ../js/ui/lookingGlass.js:744
#: ../js/ui/lookingGlass.js:698
msgid "Out of date"
msgstr "Остаряло"
#: ../js/ui/lookingGlass.js:746
#: ../js/ui/lookingGlass.js:700
msgid "Downloading"
msgstr "Изтегляне"
#: ../js/ui/lookingGlass.js:767
#: ../js/ui/lookingGlass.js:721
msgid "View Source"
msgstr "Преглед на изходния код"
#: ../js/ui/lookingGlass.js:773
#: ../js/ui/lookingGlass.js:727
msgid "Web Page"
msgstr "Домашна страница"
@ -1545,39 +1506,39 @@ msgstr "Бездействие"
msgid "Unavailable"
msgstr "Недостъпно"
#: ../js/ui/userMenu.js:567 ../js/ui/userMenu.js:571 ../js/ui/userMenu.js:641
#: ../js/ui/userMenu.js:552 ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:626
msgid "Power Off..."
msgstr "Изключване..."
#: ../js/ui/userMenu.js:603
#: ../js/ui/userMenu.js:588
msgid "Notifications"
msgstr "Известяване"
#: ../js/ui/userMenu.js:611
#: ../js/ui/userMenu.js:596
msgid "Online Accounts"
msgstr "Мрежови регистрации"
#: ../js/ui/userMenu.js:615
#: ../js/ui/userMenu.js:600
msgid "System Settings"
msgstr "Настройки на системата"
#: ../js/ui/userMenu.js:622
#: ../js/ui/userMenu.js:607
msgid "Lock Screen"
msgstr "Заключване на екрана"
#: ../js/ui/userMenu.js:627
#: ../js/ui/userMenu.js:612
msgid "Switch User"
msgstr "Смяна на потребител"
#: ../js/ui/userMenu.js:632
#: ../js/ui/userMenu.js:617
msgid "Log Out..."
msgstr "Изход…"
#: ../js/ui/userMenu.js:660
#: ../js/ui/userMenu.js:645
msgid "Your chat status will be set to busy"
msgstr "Състоянието ви ще се зададе да е „Зает“"
#: ../js/ui/userMenu.js:661
#: ../js/ui/userMenu.js:646
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1594,7 +1555,7 @@ msgstr ""
msgid "Type to search..."
msgstr "Търсене на написаното…"
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:244
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:261
msgid "Search"
msgstr "Търсене"
@ -1650,15 +1611,13 @@ msgstr "Стандартно"
msgid "Authentication dialog was dismissed by the user"
msgstr "Прозорецът за упълномощаване беше затворен от потребителя"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:89
msgid "Home"
#: ../src/shell-util.c:100
msgid "Home Folder"
msgstr "Домашна папка"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:98
#: ../src/shell-util.c:115
msgid "File System"
msgstr "Файлова система"
@ -1667,7 +1626,7 @@ msgstr "Файлова система"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-util.c:294
#: ../src/shell-util.c:311
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

260
po/ca.po
View File

@ -8,10 +8,10 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-10-04 23:29+0200\n"
"PO-Revision-Date: 2011-10-04 23:30+0200\n"
"POT-Creation-Date: 2011-10-23 23:42+0200\n"
"PO-Revision-Date: 2011-10-23 23:41+0200\n"
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
"Language-Team: català; valencià <tradgnome@softcatala.org>\n"
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -187,42 +187,42 @@ msgstr "Quin tipus de teclat s'ha d'utilitzar"
msgid "disabled OpenSearch providers"
msgstr "inhabilita els proveïdors d'OpenSearch"
#: ../js/gdm/loginDialog.js:617
#: ../js/gdm/loginDialog.js:633
msgid "Session..."
msgstr "Sessió..."
#: ../js/gdm/loginDialog.js:785
#: ../js/gdm/loginDialog.js:804
msgctxt "title"
msgid "Sign In"
msgstr "Entrada"
#. translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:830
#: ../js/gdm/loginDialog.js:849
msgid "(or swipe finger)"
msgstr "(o passeu el dit)"
#: ../js/gdm/loginDialog.js:848
#: ../js/gdm/loginDialog.js:867
msgid "Not listed?"
msgstr "No esteu llistat?"
#: ../js/gdm/loginDialog.js:1004 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:165
#: ../js/ui/polkitAuthenticationAgent.js:171 ../js/ui/status/bluetooth.js:480
#: ../js/gdm/loginDialog.js:1035 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:148
#: ../js/ui/polkitAuthenticationAgent.js:173 ../js/ui/status/bluetooth.js:480
msgid "Cancel"
msgstr "Cancel·la"
#: ../js/gdm/loginDialog.js:1009
#: ../js/gdm/loginDialog.js:1040
msgctxt "button"
msgid "Sign In"
msgstr "Entra"
#: ../js/gdm/loginDialog.js:1358
#: ../js/gdm/loginDialog.js:1392
msgid "Login Window"
msgstr "Finestra d'entrada"
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:514
#: ../js/ui/userMenu.js:516 ../js/ui/userMenu.js:585
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:554
#: ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:625
msgid "Suspend"
msgstr "Atura temporalment"
@ -445,32 +445,32 @@ msgstr "Aquesta setmana"
msgid "Next week"
msgstr "La setmana que ve"
#: ../js/ui/contactDisplay.js:59 ../js/ui/notificationDaemon.js:444
#: ../js/ui/status/power.js:223 ../src/shell-app.c:355
#: ../js/ui/contactDisplay.js:65 ../js/ui/notificationDaemon.js:459
#: ../js/ui/status/power.js:223 ../src/shell-app.c:353
msgid "Unknown"
msgstr "Desconegut"
#: ../js/ui/contactDisplay.js:80 ../js/ui/userMenu.js:139
#: ../js/ui/contactDisplay.js:86 ../js/ui/userMenu.js:139
msgid "Available"
msgstr "Disponible"
#: ../js/ui/contactDisplay.js:85 ../js/ui/userMenu.js:148
#: ../js/ui/contactDisplay.js:91 ../js/ui/userMenu.js:148
msgid "Away"
msgstr "Absent"
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:142
#: ../js/ui/contactDisplay.js:95 ../js/ui/userMenu.js:142
msgid "Busy"
msgstr "Ocupat"
#: ../js/ui/contactDisplay.js:93
#: ../js/ui/contactDisplay.js:99
msgid "Offline"
msgstr "Fora de línia"
#: ../js/ui/contactDisplay.js:140
#: ../js/ui/contactDisplay.js:146
msgid "CONTACTS"
msgstr "Contactes"
#: ../js/ui/dash.js:172 ../js/ui/messageTray.js:1204
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1206
msgid "Remove"
msgstr "Suprimeix"
@ -604,100 +604,96 @@ msgstr "Instal·la"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Voleu baixar i instal·lar «%s» de extensions.gnome.org?"
#: ../js/ui/keyboard.js:308
#: ../js/ui/keyboard.js:325
msgid "tray"
msgstr "safata"
#: ../js/ui/keyboard.js:530 ../js/ui/status/power.js:211
#: ../js/ui/keyboard.js:547 ../js/ui/status/power.js:211
msgid "Keyboard"
msgstr "Teclat"
#: ../js/ui/lookingGlass.js:645
#: ../js/ui/lookingGlass.js:646
msgid "No extensions installed"
msgstr "No hi ha cap extensió instal·lada"
#: ../js/ui/lookingGlass.js:691
#: ../js/ui/lookingGlass.js:692
msgid "Enabled"
msgstr "Habilitat"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:693 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:694 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Inhabilitat"
#: ../js/ui/lookingGlass.js:695
#: ../js/ui/lookingGlass.js:696
msgid "Error"
msgstr "Error"
#: ../js/ui/lookingGlass.js:697
#: ../js/ui/lookingGlass.js:698
msgid "Out of date"
msgstr "Fora d'hora"
#: ../js/ui/lookingGlass.js:699
#: ../js/ui/lookingGlass.js:700
msgid "Downloading"
msgstr "S'està baixant"
#: ../js/ui/lookingGlass.js:720
#: ../js/ui/lookingGlass.js:721
msgid "View Source"
msgstr "Mostra el codi font"
#: ../js/ui/lookingGlass.js:726
#: ../js/ui/lookingGlass.js:727
msgid "Web Page"
msgstr "Pàgina web"
#: ../js/ui/messageTray.js:1197
#: ../js/ui/messageTray.js:1199
msgid "Open"
msgstr "Obre"
#: ../js/ui/messageTray.js:2406
#: ../js/ui/messageTray.js:2408
msgid "System Information"
msgstr "Informació de l'ordinador"
#: ../js/ui/networkAgent.js:145
msgid "Show password"
msgstr "Mostra la contrasenya"
#: ../js/ui/networkAgent.js:160
#: ../js/ui/networkAgent.js:143
msgid "Connect"
msgstr "Connecta"
#. Cisco LEAP
#: ../js/ui/networkAgent.js:255 ../js/ui/networkAgent.js:267
#: ../js/ui/networkAgent.js:294 ../js/ui/networkAgent.js:314
#: ../js/ui/networkAgent.js:324
#: ../js/ui/networkAgent.js:238 ../js/ui/networkAgent.js:250
#: ../js/ui/networkAgent.js:277 ../js/ui/networkAgent.js:297
#: ../js/ui/networkAgent.js:307
msgid "Password: "
msgstr "Contrasenya:"
#. static WEP
#: ../js/ui/networkAgent.js:260
#: ../js/ui/networkAgent.js:243
msgid "Key: "
msgstr "Clau:"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: ../js/ui/networkAgent.js:292 ../js/ui/networkAgent.js:310
#: ../js/ui/networkAgent.js:275 ../js/ui/networkAgent.js:293
msgid "Username: "
msgstr "Nom d'usuari:"
#: ../js/ui/networkAgent.js:298
#: ../js/ui/networkAgent.js:281
msgid "Identity: "
msgstr "Identitat:"
#: ../js/ui/networkAgent.js:300
#: ../js/ui/networkAgent.js:283
msgid "Private key password: "
msgstr "Contrasenya de la clau privada:"
#: ../js/ui/networkAgent.js:312
#: ../js/ui/networkAgent.js:295
msgid "Service: "
msgstr "Servei:"
#: ../js/ui/networkAgent.js:341
#: ../js/ui/networkAgent.js:324
msgid "Authentication required by wireless network"
msgstr "La xarxa sense fil requereix autenticació"
#: ../js/ui/networkAgent.js:342
#: ../js/ui/networkAgent.js:325
#, c-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -706,35 +702,35 @@ msgstr ""
"Per accedir a la xarxa sense fil «%s» calen les contrasenyes o les claus "
"d'encriptació."
#: ../js/ui/networkAgent.js:346
#: ../js/ui/networkAgent.js:329
msgid "Wired 802.1X authentication"
msgstr "Autenticació 802.1X amb fil"
#: ../js/ui/networkAgent.js:348
#: ../js/ui/networkAgent.js:331
msgid "Network name: "
msgstr "Nom de la xarxa: "
#: ../js/ui/networkAgent.js:353
#: ../js/ui/networkAgent.js:336
msgid "DSL authentication"
msgstr "Autenticació DSL"
#: ../js/ui/networkAgent.js:360
#: ../js/ui/networkAgent.js:343
msgid "PIN code required"
msgstr "Cal que introduïu el codi PIN"
#: ../js/ui/networkAgent.js:361
#: ../js/ui/networkAgent.js:344
msgid "PIN code is needed for the mobile broadband device"
msgstr "Cal que introduïu el codi PIN del dispositiu de banda ampla mòbil"
#: ../js/ui/networkAgent.js:362
#: ../js/ui/networkAgent.js:345
msgid "PIN: "
msgstr "PIN: "
#: ../js/ui/networkAgent.js:368
#: ../js/ui/networkAgent.js:351
msgid "Mobile broadband network password"
msgstr "Contrasenya de la xarxa de banda ampla mòbil"
#: ../js/ui/networkAgent.js:369
#: ../js/ui/networkAgent.js:352
#, c-format
msgid "A password is required to connect to '%s'."
msgstr "Cal que introduïu una contrasenya per connectar-vos a «%s»."
@ -790,15 +786,15 @@ msgstr "Connecta a..."
msgid "PLACES & DEVICES"
msgstr "LLOCS I DISPOSITIUS"
#: ../js/ui/polkitAuthenticationAgent.js:72
#: ../js/ui/polkitAuthenticationAgent.js:73
msgid "Authentication Required"
msgstr "Cal autenticació"
#: ../js/ui/polkitAuthenticationAgent.js:106
#: ../js/ui/polkitAuthenticationAgent.js:107
msgid "Administrator"
msgstr "Administrador"
#: ../js/ui/polkitAuthenticationAgent.js:175
#: ../js/ui/polkitAuthenticationAgent.js:177
msgid "Authenticate"
msgstr "Autentica"
@ -806,11 +802,11 @@ msgstr "Autentica"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: ../js/ui/polkitAuthenticationAgent.js:256
#: ../js/ui/polkitAuthenticationAgent.js:258
msgid "Sorry, that didn't work. Please try again."
msgstr "No ha funcionat. Torneu-ho a provar."
#: ../js/ui/polkitAuthenticationAgent.js:268
#: ../js/ui/polkitAuthenticationAgent.js:270
msgid "Password:"
msgstr "Contrasenya:"
@ -823,7 +819,7 @@ msgstr "Contrasenya:"
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:208
#: ../js/ui/runDialog.js:209
msgid "Please enter a command:"
msgstr "Introduïu una ordre:"
@ -835,6 +831,22 @@ msgstr "S'està cercant..."
msgid "No matching results."
msgstr "No s'ha trobat cap coincidència."
#: ../js/ui/shellEntry.js:30
msgid "Copy"
msgstr "Copia"
#: ../js/ui/shellEntry.js:35
msgid "Paste"
msgstr "Enganxa"
#: ../js/ui/shellEntry.js:81
msgid "Show Text"
msgstr "Mostra el text"
#: ../js/ui/shellEntry.js:83
msgid "Hide Text"
msgstr "Oculta el text"
#: ../js/ui/shellMountOperation.js:285
msgid "Wrong password, please try again"
msgstr "La contrasenya és errònia, torneu-ho a intentar"
@ -968,7 +980,7 @@ msgstr "Permet l'accés sempre"
msgid "Grant this time only"
msgstr "Permet-ho només ara"
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1200
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1204
msgid "Reject"
msgstr "Rebutja"
@ -1254,22 +1266,22 @@ msgstr "Teniu una petició de subscripció"
msgid "Connection error"
msgstr "S'ha produït un error de connexió"
#: ../js/ui/telepathyClient.js:737
#: ../js/ui/telepathyClient.js:741
#, c-format
msgid "%s is online."
msgstr "%s és en línia."
#: ../js/ui/telepathyClient.js:742
#: ../js/ui/telepathyClient.js:746
#, c-format
msgid "%s is offline."
msgstr "%s no hi és."
#: ../js/ui/telepathyClient.js:745
#: ../js/ui/telepathyClient.js:749
#, c-format
msgid "%s is away."
msgstr "%s és lluny."
#: ../js/ui/telepathyClient.js:748
#: ../js/ui/telepathyClient.js:752
#, c-format
msgid "%s is busy."
msgstr "%s està ocupat."
@ -1277,35 +1289,35 @@ msgstr "%s està ocupat."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:982
#: ../js/ui/telepathyClient.js:986
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Enviat a les <b>%X</b> del <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:988
#: ../js/ui/telepathyClient.js:992
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Enviat el <b>%A %d de %B</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:993
#: ../js/ui/telepathyClient.js:997
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Enviat el <b>%A %d de %B</b> de %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:1035
#: ../js/ui/telepathyClient.js:1039
#, c-format
msgid "%s is now known as %s"
msgstr "En/na %s ara es diu %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1144
#: ../js/ui/telepathyClient.js:1148
#, c-format
msgid "Invitation to %s"
msgstr "Us han convidat a entrar a %s"
@ -1313,34 +1325,35 @@ msgstr "Us han convidat a entrar a %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/telepathyClient.js:1152
#: ../js/ui/telepathyClient.js:1156
#, c-format
msgid "%s is inviting you to join %s"
msgstr "En/na %s us convida a entrar a %s"
#: ../js/ui/telepathyClient.js:1154 ../js/ui/telepathyClient.js:1243
#: ../js/ui/telepathyClient.js:1347
#: ../js/ui/telepathyClient.js:1158 ../js/ui/telepathyClient.js:1248
#: ../js/ui/telepathyClient.js:1352
msgid "Decline"
msgstr "Declina"
#: ../js/ui/telepathyClient.js:1155 ../js/ui/telepathyClient.js:1244
#: ../js/ui/telepathyClient.js:1348
#: ../js/ui/telepathyClient.js:1159 ../js/ui/telepathyClient.js:1249
#: ../js/ui/telepathyClient.js:1353
msgid "Accept"
msgstr "Accepta"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1188
#: ../js/ui/telepathyClient.js:1192
#, c-format
msgid "Video call from %s"
msgstr "Videotrucada de %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1191
#: ../js/ui/telepathyClient.js:1195
#, c-format
msgid "Call from %s"
msgstr "Trucada de %s"
#: ../js/ui/telepathyClient.js:1201
#. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1206
msgid "Answer"
msgstr "Contesta"
@ -1349,112 +1362,112 @@ msgstr "Contesta"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1237
#: ../js/ui/telepathyClient.js:1242
#, c-format
msgid "%s is sending you %s"
msgstr "En/na %s us envia %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1312
#: ../js/ui/telepathyClient.js:1317
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s vol poder saber quan esteu en línia"
#: ../js/ui/telepathyClient.js:1410
#: ../js/ui/telepathyClient.js:1415
msgid "Network error"
msgstr "Error de la xarxa"
#: ../js/ui/telepathyClient.js:1412
#: ../js/ui/telepathyClient.js:1417
msgid "Authentication failed"
msgstr "Ha fallat l'autenticació"
#: ../js/ui/telepathyClient.js:1414
#: ../js/ui/telepathyClient.js:1419
msgid "Encryption error"
msgstr "Error d'encriptació"
#: ../js/ui/telepathyClient.js:1416
#: ../js/ui/telepathyClient.js:1421
msgid "Certificate not provided"
msgstr "No s'ha proporcionat el certificat"
#: ../js/ui/telepathyClient.js:1418
#: ../js/ui/telepathyClient.js:1423
msgid "Certificate untrusted"
msgstr "El certificat no és de confiança"
#: ../js/ui/telepathyClient.js:1420
#: ../js/ui/telepathyClient.js:1425
msgid "Certificate expired"
msgstr "El certificat ha vençut"
#: ../js/ui/telepathyClient.js:1422
#: ../js/ui/telepathyClient.js:1427
msgid "Certificate not activated"
msgstr "El certificat no està activat"
#: ../js/ui/telepathyClient.js:1424
#: ../js/ui/telepathyClient.js:1429
msgid "Certificate hostname mismatch"
msgstr "No coincideix el nom de la màquina del certificat"
#: ../js/ui/telepathyClient.js:1426
#: ../js/ui/telepathyClient.js:1431
msgid "Certificate fingerprint mismatch"
msgstr "No coincideix l'empremta digital del certificat"
#: ../js/ui/telepathyClient.js:1428
#: ../js/ui/telepathyClient.js:1433
msgid "Certificate self-signed"
msgstr "Certificat signat per un mateix"
#: ../js/ui/telepathyClient.js:1430
#: ../js/ui/telepathyClient.js:1435
msgid "Status is set to offline"
msgstr "S'ha establert l'estat a fora de línia"
#: ../js/ui/telepathyClient.js:1432
#: ../js/ui/telepathyClient.js:1437
msgid "Encryption is not available"
msgstr "L'encriptació no està disponible"
#: ../js/ui/telepathyClient.js:1434
#: ../js/ui/telepathyClient.js:1439
msgid "Certificate is invalid"
msgstr "El certificat no és vàlid"
#: ../js/ui/telepathyClient.js:1436
#: ../js/ui/telepathyClient.js:1441
msgid "Connection has been refused"
msgstr "S'ha rebutjat la connexió"
#: ../js/ui/telepathyClient.js:1438
#: ../js/ui/telepathyClient.js:1443
msgid "Connection can't be established"
msgstr "No es pot establir la connexió"
#: ../js/ui/telepathyClient.js:1440
#: ../js/ui/telepathyClient.js:1445
msgid "Connection has been lost"
msgstr "S'ha perdut la connexió"
#: ../js/ui/telepathyClient.js:1442
#: ../js/ui/telepathyClient.js:1447
msgid "This resource is already connected to the server"
msgstr "Aquest recurs ja està connectat al servidor"
#: ../js/ui/telepathyClient.js:1444
#: ../js/ui/telepathyClient.js:1449
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"S'ha reemplaçat la connexió per una altra de nova fent servir el mateix "
"recurs"
#: ../js/ui/telepathyClient.js:1446
#: ../js/ui/telepathyClient.js:1451
msgid "The account already exists on the server"
msgstr "Ja existeix aquest compte al servidor"
#: ../js/ui/telepathyClient.js:1448
#: ../js/ui/telepathyClient.js:1453
msgid "Server is currently too busy to handle the connection"
msgstr "El servidor està massa ocupat per gestionar la connexió"
#: ../js/ui/telepathyClient.js:1450
#: ../js/ui/telepathyClient.js:1455
msgid "Certificate has been revoked"
msgstr "S'ha revocat el certificat"
#: ../js/ui/telepathyClient.js:1452
#: ../js/ui/telepathyClient.js:1457
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"El certificat utilitza un algorisme criptògraf no segur o la seva fortalesa "
"criptogràfica és feble"
#: ../js/ui/telepathyClient.js:1454
#: ../js/ui/telepathyClient.js:1459
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1464,20 +1477,20 @@ msgstr ""
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1463
#: ../js/ui/telepathyClient.js:1468
#, c-format
msgid "Connection to %s failed"
msgstr "Ha fallat la connexió a %s"
#: ../js/ui/telepathyClient.js:1472
#: ../js/ui/telepathyClient.js:1477
msgid "Reconnect"
msgstr "Torna a connectar"
#: ../js/ui/telepathyClient.js:1473
#: ../js/ui/telepathyClient.js:1478
msgid "Edit account"
msgstr "Edita el compte"
#: ../js/ui/telepathyClient.js:1519
#: ../js/ui/telepathyClient.js:1524
msgid "Unknown reason"
msgstr "Motiu desconegut"
@ -1493,39 +1506,39 @@ msgstr "Inactiu"
msgid "Unavailable"
msgstr "No disponible"
#: ../js/ui/userMenu.js:512 ../js/ui/userMenu.js:516 ../js/ui/userMenu.js:586
#: ../js/ui/userMenu.js:552 ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:626
msgid "Power Off..."
msgstr "Apaga..."
#: ../js/ui/userMenu.js:548
#: ../js/ui/userMenu.js:588
msgid "Notifications"
msgstr "Notificacions"
#: ../js/ui/userMenu.js:556
#: ../js/ui/userMenu.js:596
msgid "Online Accounts"
msgstr "Comptes en línia"
#: ../js/ui/userMenu.js:560
#: ../js/ui/userMenu.js:600
msgid "System Settings"
msgstr "Paràmetres de l'ordinador"
#: ../js/ui/userMenu.js:567
#: ../js/ui/userMenu.js:607
msgid "Lock Screen"
msgstr "Bloca la pantalla"
#: ../js/ui/userMenu.js:572
#: ../js/ui/userMenu.js:612
msgid "Switch User"
msgstr "Canvia d'usuari"
#: ../js/ui/userMenu.js:577
#: ../js/ui/userMenu.js:617
msgid "Log Out..."
msgstr "Surt..."
#: ../js/ui/userMenu.js:605
#: ../js/ui/userMenu.js:645
msgid "Your chat status will be set to busy"
msgstr "L'estat del xat s'establirà a ocupat"
#: ../js/ui/userMenu.js:606
#: ../js/ui/userMenu.js:646
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1538,11 +1551,11 @@ msgstr ""
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: ../js/ui/viewSelector.js:120
#: ../js/ui/viewSelector.js:121
msgid "Type to search..."
msgstr "Teclegeu per cercar..."
#: ../js/ui/viewSelector.js:140 ../src/shell-util.c:261
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:261
msgid "Search"
msgstr "Cerca"
@ -1581,7 +1594,7 @@ msgstr "Mostra la versió"
msgid "Mode used by GDM for login screen"
msgstr "El mode que utilitzarà el GDM per a la pantalla d'entrada"
#: ../src/shell-app.c:581
#: ../src/shell-app.c:579
#, c-format
msgid "Failed to launch '%s'"
msgstr "No s'ha pogut iniciar «%s»"
@ -1618,6 +1631,9 @@ msgstr "Sistema de fitxers"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Show password"
#~ msgstr "Mostra la contrasenya"
#~ msgid "%s has not emitted any errors."
#~ msgstr "%s no ha emès cap error."

View File

@ -8,10 +8,10 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-10-01 16:04+0200\n"
"PO-Revision-Date: 2011-10-01 16:03+0200\n"
"POT-Creation-Date: 2011-10-23 23:43+0200\n"
"PO-Revision-Date: 2011-10-23 23:41+0200\n"
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
"Language-Team: català; valencià <tradgnome@softcatala.org>\n"
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
"Language: ca-XV\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -187,42 +187,42 @@ msgstr "Quin tipus de teclat s'ha d'utilitzar"
msgid "disabled OpenSearch providers"
msgstr "inhabilita els proveïdors d'OpenSearch"
#: ../js/gdm/loginDialog.js:617
#: ../js/gdm/loginDialog.js:633
msgid "Session..."
msgstr "Sessió..."
#: ../js/gdm/loginDialog.js:785
#: ../js/gdm/loginDialog.js:804
msgctxt "title"
msgid "Sign In"
msgstr "Entrada"
#. translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:830
#: ../js/gdm/loginDialog.js:849
msgid "(or swipe finger)"
msgstr "(o passeu el dit)"
#: ../js/gdm/loginDialog.js:848
#: ../js/gdm/loginDialog.js:867
msgid "Not listed?"
msgstr "No esteu llistat?"
#: ../js/gdm/loginDialog.js:1004 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:165
#: ../js/ui/polkitAuthenticationAgent.js:171 ../js/ui/status/bluetooth.js:480
#: ../js/gdm/loginDialog.js:1035 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:148
#: ../js/ui/polkitAuthenticationAgent.js:173 ../js/ui/status/bluetooth.js:480
msgid "Cancel"
msgstr "Cancel·la"
#: ../js/gdm/loginDialog.js:1009
#: ../js/gdm/loginDialog.js:1040
msgctxt "button"
msgid "Sign In"
msgstr "Entra"
#: ../js/gdm/loginDialog.js:1358
#: ../js/gdm/loginDialog.js:1392
msgid "Login Window"
msgstr "Finestra d'entrada"
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:514
#: ../js/ui/userMenu.js:516 ../js/ui/userMenu.js:585
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:554
#: ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:625
msgid "Suspend"
msgstr "Atura temporalment"
@ -445,32 +445,32 @@ msgstr "Esta setmana"
msgid "Next week"
msgstr "La setmana que ve"
#: ../js/ui/contactDisplay.js:59 ../js/ui/notificationDaemon.js:444
#: ../js/ui/status/power.js:223 ../src/shell-app.c:355
#: ../js/ui/contactDisplay.js:65 ../js/ui/notificationDaemon.js:459
#: ../js/ui/status/power.js:223 ../src/shell-app.c:353
msgid "Unknown"
msgstr "Desconegut"
#: ../js/ui/contactDisplay.js:80 ../js/ui/userMenu.js:139
#: ../js/ui/contactDisplay.js:86 ../js/ui/userMenu.js:139
msgid "Available"
msgstr "Disponible"
#: ../js/ui/contactDisplay.js:85 ../js/ui/userMenu.js:148
#: ../js/ui/contactDisplay.js:91 ../js/ui/userMenu.js:148
msgid "Away"
msgstr "Absent"
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:142
#: ../js/ui/contactDisplay.js:95 ../js/ui/userMenu.js:142
msgid "Busy"
msgstr "Ocupat"
#: ../js/ui/contactDisplay.js:93
#: ../js/ui/contactDisplay.js:99
msgid "Offline"
msgstr "Fora de línia"
#: ../js/ui/contactDisplay.js:140
#: ../js/ui/contactDisplay.js:146
msgid "CONTACTS"
msgstr "Contactes"
#: ../js/ui/dash.js:172 ../js/ui/messageTray.js:1204
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1206
msgid "Remove"
msgstr "Suprimeix"
@ -604,110 +604,96 @@ msgstr "Instal·la"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Voleu baixar i instal·lar «%s» d'extensions.gnome.org?"
#: ../js/ui/keyboard.js:529 ../js/ui/status/power.js:211
#: ../js/ui/keyboard.js:325
msgid "tray"
msgstr "safata"
#: ../js/ui/keyboard.js:547 ../js/ui/status/power.js:211
msgid "Keyboard"
msgstr "Teclat"
#: ../js/ui/lookingGlass.js:645
#: ../js/ui/lookingGlass.js:646
msgid "No extensions installed"
msgstr "No hi ha cap extensió instal·lada"
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:700
#, c-format
msgid "%s has not emitted any errors."
msgstr "%s no ha emés cap error."
#: ../js/ui/lookingGlass.js:706
msgid "Hide Errors"
msgstr "Amaga els errors"
#: ../js/ui/lookingGlass.js:710 ../js/ui/lookingGlass.js:760
msgid "Show Errors"
msgstr "Mostra els errors"
#: ../js/ui/lookingGlass.js:719
#: ../js/ui/lookingGlass.js:692
msgid "Enabled"
msgstr "Habilitat"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:721 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:694 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Inhabilitat"
#: ../js/ui/lookingGlass.js:723
#: ../js/ui/lookingGlass.js:696
msgid "Error"
msgstr "Error"
#: ../js/ui/lookingGlass.js:725
#: ../js/ui/lookingGlass.js:698
msgid "Out of date"
msgstr "Fora d'hora"
#: ../js/ui/lookingGlass.js:727
#: ../js/ui/lookingGlass.js:700
msgid "Downloading"
msgstr "S'està baixant"
#: ../js/ui/lookingGlass.js:748
#: ../js/ui/lookingGlass.js:721
msgid "View Source"
msgstr "Mostra el codi font"
#: ../js/ui/lookingGlass.js:754
#: ../js/ui/lookingGlass.js:727
msgid "Web Page"
msgstr "Pàgina web"
#: ../js/ui/messageTray.js:1197
#: ../js/ui/messageTray.js:1199
msgid "Open"
msgstr "Obri"
#: ../js/ui/messageTray.js:2406
#: ../js/ui/messageTray.js:2408
msgid "System Information"
msgstr "Informació de l'ordinador"
#: ../js/ui/networkAgent.js:145
msgid "Show password"
msgstr "Mostra la contrasenya"
#: ../js/ui/networkAgent.js:160
#: ../js/ui/networkAgent.js:143
msgid "Connect"
msgstr "Connecta"
#. Cisco LEAP
#: ../js/ui/networkAgent.js:255 ../js/ui/networkAgent.js:267
#: ../js/ui/networkAgent.js:294 ../js/ui/networkAgent.js:314
#: ../js/ui/networkAgent.js:324
#: ../js/ui/networkAgent.js:238 ../js/ui/networkAgent.js:250
#: ../js/ui/networkAgent.js:277 ../js/ui/networkAgent.js:297
#: ../js/ui/networkAgent.js:307
msgid "Password: "
msgstr "Contrasenya:"
#. static WEP
#: ../js/ui/networkAgent.js:260
#: ../js/ui/networkAgent.js:243
msgid "Key: "
msgstr "Clau:"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: ../js/ui/networkAgent.js:292 ../js/ui/networkAgent.js:310
#: ../js/ui/networkAgent.js:275 ../js/ui/networkAgent.js:293
msgid "Username: "
msgstr "Nom d'usuari:"
#: ../js/ui/networkAgent.js:298
#: ../js/ui/networkAgent.js:281
msgid "Identity: "
msgstr "Identitat:"
#: ../js/ui/networkAgent.js:300
#: ../js/ui/networkAgent.js:283
msgid "Private key password: "
msgstr "Contrasenya de la clau privada:"
#: ../js/ui/networkAgent.js:312
#: ../js/ui/networkAgent.js:295
msgid "Service: "
msgstr "Servei:"
#: ../js/ui/networkAgent.js:341
#: ../js/ui/networkAgent.js:324
msgid "Authentication required by wireless network"
msgstr "La xarxa sense fil requereix autenticació"
#: ../js/ui/networkAgent.js:342
#: ../js/ui/networkAgent.js:325
#, c-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -716,35 +702,35 @@ msgstr ""
"Per accedir a la xarxa sense fil «%s» calen les contrasenyes o les claus "
"d'encriptació."
#: ../js/ui/networkAgent.js:346
#: ../js/ui/networkAgent.js:329
msgid "Wired 802.1X authentication"
msgstr "Autenticació 802.1X amb fil"
#: ../js/ui/networkAgent.js:348
#: ../js/ui/networkAgent.js:331
msgid "Network name: "
msgstr "Nom de la xarxa: "
#: ../js/ui/networkAgent.js:353
#: ../js/ui/networkAgent.js:336
msgid "DSL authentication"
msgstr "Autenticació DSL"
#: ../js/ui/networkAgent.js:360
#: ../js/ui/networkAgent.js:343
msgid "PIN code required"
msgstr "Cal que introduïu el codi PIN"
#: ../js/ui/networkAgent.js:361
#: ../js/ui/networkAgent.js:344
msgid "PIN code is needed for the mobile broadband device"
msgstr "Cal que introduïu el codi PIN del dispositiu de banda ampla mòbil"
#: ../js/ui/networkAgent.js:362
#: ../js/ui/networkAgent.js:345
msgid "PIN: "
msgstr "PIN: "
#: ../js/ui/networkAgent.js:368
#: ../js/ui/networkAgent.js:351
msgid "Mobile broadband network password"
msgstr "Contrasenya de la xarxa de banda ampla mòbil"
#: ../js/ui/networkAgent.js:369
#: ../js/ui/networkAgent.js:352
#, c-format
msgid "A password is required to connect to '%s'."
msgstr "Cal que introduïu una contrasenya per connectar-vos a «%s»."
@ -800,15 +786,15 @@ msgstr "Connecta a..."
msgid "PLACES & DEVICES"
msgstr "LLOCS I DISPOSITIUS"
#: ../js/ui/polkitAuthenticationAgent.js:72
#: ../js/ui/polkitAuthenticationAgent.js:73
msgid "Authentication Required"
msgstr "Cal autenticació"
#: ../js/ui/polkitAuthenticationAgent.js:106
#: ../js/ui/polkitAuthenticationAgent.js:107
msgid "Administrator"
msgstr "Administrador"
#: ../js/ui/polkitAuthenticationAgent.js:175
#: ../js/ui/polkitAuthenticationAgent.js:177
msgid "Authenticate"
msgstr "Autentica"
@ -816,11 +802,11 @@ msgstr "Autentica"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: ../js/ui/polkitAuthenticationAgent.js:256
#: ../js/ui/polkitAuthenticationAgent.js:258
msgid "Sorry, that didn't work. Please try again."
msgstr "No ha funcionat. Torneu-ho a provar."
#: ../js/ui/polkitAuthenticationAgent.js:268
#: ../js/ui/polkitAuthenticationAgent.js:270
msgid "Password:"
msgstr "Contrasenya:"
@ -833,7 +819,7 @@ msgstr "Contrasenya:"
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:208
#: ../js/ui/runDialog.js:209
msgid "Please enter a command:"
msgstr "Introduïu una orde:"
@ -845,6 +831,22 @@ msgstr "S'està cercant..."
msgid "No matching results."
msgstr "No s'ha trobat cap coincidència."
#: ../js/ui/shellEntry.js:30
msgid "Copy"
msgstr "Copia"
#: ../js/ui/shellEntry.js:35
msgid "Paste"
msgstr "Enganxa"
#: ../js/ui/shellEntry.js:81
msgid "Show Text"
msgstr "Mostra el text"
#: ../js/ui/shellEntry.js:83
msgid "Hide Text"
msgstr "Oculta el text"
#: ../js/ui/shellMountOperation.js:285
msgid "Wrong password, please try again"
msgstr "La contrasenya és errònia, torneu-ho a intentar"
@ -978,7 +980,7 @@ msgstr "Permet l'accés sempre"
msgid "Grant this time only"
msgstr "Permet-ho només ara"
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1200
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1204
msgid "Reject"
msgstr "Rebutja"
@ -1264,22 +1266,22 @@ msgstr "Teniu una petició de subscripció"
msgid "Connection error"
msgstr "S'ha produït un error de connexió"
#: ../js/ui/telepathyClient.js:737
#: ../js/ui/telepathyClient.js:741
#, c-format
msgid "%s is online."
msgstr "%s és en línia."
#: ../js/ui/telepathyClient.js:742
#: ../js/ui/telepathyClient.js:746
#, c-format
msgid "%s is offline."
msgstr "%s no hi és."
#: ../js/ui/telepathyClient.js:745
#: ../js/ui/telepathyClient.js:749
#, c-format
msgid "%s is away."
msgstr "%s és lluny."
#: ../js/ui/telepathyClient.js:748
#: ../js/ui/telepathyClient.js:752
#, c-format
msgid "%s is busy."
msgstr "%s està ocupat."
@ -1287,35 +1289,35 @@ msgstr "%s està ocupat."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:982
#: ../js/ui/telepathyClient.js:986
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Enviat a les <b>%X</b> del <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:988
#: ../js/ui/telepathyClient.js:992
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Enviat el <b>%A %d de %B</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:993
#: ../js/ui/telepathyClient.js:997
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Enviat el <b>%A %d de %B</b> de %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:1035
#: ../js/ui/telepathyClient.js:1039
#, c-format
msgid "%s is now known as %s"
msgstr "En/na %s ara es diu %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1144
#: ../js/ui/telepathyClient.js:1148
#, c-format
msgid "Invitation to %s"
msgstr "Vos han convidat a entrar a %s"
@ -1323,34 +1325,35 @@ msgstr "Vos han convidat a entrar a %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/telepathyClient.js:1152
#: ../js/ui/telepathyClient.js:1156
#, c-format
msgid "%s is inviting you to join %s"
msgstr "En/na %s vos convida a entrar a %s"
#: ../js/ui/telepathyClient.js:1154 ../js/ui/telepathyClient.js:1243
#: ../js/ui/telepathyClient.js:1347
#: ../js/ui/telepathyClient.js:1158 ../js/ui/telepathyClient.js:1248
#: ../js/ui/telepathyClient.js:1352
msgid "Decline"
msgstr "Declina"
#: ../js/ui/telepathyClient.js:1155 ../js/ui/telepathyClient.js:1244
#: ../js/ui/telepathyClient.js:1348
#: ../js/ui/telepathyClient.js:1159 ../js/ui/telepathyClient.js:1249
#: ../js/ui/telepathyClient.js:1353
msgid "Accept"
msgstr "Accepta"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1188
#: ../js/ui/telepathyClient.js:1192
#, c-format
msgid "Video call from %s"
msgstr "Videotrucada de %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1191
#: ../js/ui/telepathyClient.js:1195
#, c-format
msgid "Call from %s"
msgstr "Trucada de %s"
#: ../js/ui/telepathyClient.js:1201
#. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1206
msgid "Answer"
msgstr "Contesta"
@ -1359,112 +1362,112 @@ msgstr "Contesta"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1237
#: ../js/ui/telepathyClient.js:1242
#, c-format
msgid "%s is sending you %s"
msgstr "En/na %s vos envia %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1312
#: ../js/ui/telepathyClient.js:1317
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s vol poder saber quan esteu en línia"
#: ../js/ui/telepathyClient.js:1410
#: ../js/ui/telepathyClient.js:1415
msgid "Network error"
msgstr "Error de la xarxa"
#: ../js/ui/telepathyClient.js:1412
#: ../js/ui/telepathyClient.js:1417
msgid "Authentication failed"
msgstr "Ha fallat l'autenticació"
#: ../js/ui/telepathyClient.js:1414
#: ../js/ui/telepathyClient.js:1419
msgid "Encryption error"
msgstr "Error d'encriptació"
#: ../js/ui/telepathyClient.js:1416
#: ../js/ui/telepathyClient.js:1421
msgid "Certificate not provided"
msgstr "No s'ha proporcionat el certificat"
#: ../js/ui/telepathyClient.js:1418
#: ../js/ui/telepathyClient.js:1423
msgid "Certificate untrusted"
msgstr "El certificat no és de confiança"
#: ../js/ui/telepathyClient.js:1420
#: ../js/ui/telepathyClient.js:1425
msgid "Certificate expired"
msgstr "El certificat ha vençut"
#: ../js/ui/telepathyClient.js:1422
#: ../js/ui/telepathyClient.js:1427
msgid "Certificate not activated"
msgstr "El certificat no està activat"
#: ../js/ui/telepathyClient.js:1424
#: ../js/ui/telepathyClient.js:1429
msgid "Certificate hostname mismatch"
msgstr "No coincideix el nom de la màquina del certificat"
#: ../js/ui/telepathyClient.js:1426
#: ../js/ui/telepathyClient.js:1431
msgid "Certificate fingerprint mismatch"
msgstr "No coincideix l'empremta digital del certificat"
#: ../js/ui/telepathyClient.js:1428
#: ../js/ui/telepathyClient.js:1433
msgid "Certificate self-signed"
msgstr "Certificat signat per un mateix"
#: ../js/ui/telepathyClient.js:1430
#: ../js/ui/telepathyClient.js:1435
msgid "Status is set to offline"
msgstr "S'ha establit l'estat a fora de línia"
#: ../js/ui/telepathyClient.js:1432
#: ../js/ui/telepathyClient.js:1437
msgid "Encryption is not available"
msgstr "L'encriptació no està disponible"
#: ../js/ui/telepathyClient.js:1434
#: ../js/ui/telepathyClient.js:1439
msgid "Certificate is invalid"
msgstr "El certificat no és vàlid"
#: ../js/ui/telepathyClient.js:1436
#: ../js/ui/telepathyClient.js:1441
msgid "Connection has been refused"
msgstr "S'ha rebutjat la connexió"
#: ../js/ui/telepathyClient.js:1438
#: ../js/ui/telepathyClient.js:1443
msgid "Connection can't be established"
msgstr "No es pot establir la connexió"
#: ../js/ui/telepathyClient.js:1440
#: ../js/ui/telepathyClient.js:1445
msgid "Connection has been lost"
msgstr "S'ha perdut la connexió"
#: ../js/ui/telepathyClient.js:1442
#: ../js/ui/telepathyClient.js:1447
msgid "This resource is already connected to the server"
msgstr "Este recurs ja està connectat al servidor"
#: ../js/ui/telepathyClient.js:1444
#: ../js/ui/telepathyClient.js:1449
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"S'ha reemplaçat la connexió per una altra de nova fent servir el mateix "
"recurs"
#: ../js/ui/telepathyClient.js:1446
#: ../js/ui/telepathyClient.js:1451
msgid "The account already exists on the server"
msgstr "Ja existeix este compte al servidor"
#: ../js/ui/telepathyClient.js:1448
#: ../js/ui/telepathyClient.js:1453
msgid "Server is currently too busy to handle the connection"
msgstr "El servidor està massa ocupat per gestionar la connexió"
#: ../js/ui/telepathyClient.js:1450
#: ../js/ui/telepathyClient.js:1455
msgid "Certificate has been revoked"
msgstr "S'ha revocat el certificat"
#: ../js/ui/telepathyClient.js:1452
#: ../js/ui/telepathyClient.js:1457
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"El certificat utilitza un algorisme criptògraf no segur o la seua fortalesa "
"criptogràfica és feble"
#: ../js/ui/telepathyClient.js:1454
#: ../js/ui/telepathyClient.js:1459
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1474,20 +1477,20 @@ msgstr ""
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1463
#: ../js/ui/telepathyClient.js:1468
#, c-format
msgid "Connection to %s failed"
msgstr "Ha fallat la connexió a %s"
#: ../js/ui/telepathyClient.js:1472
#: ../js/ui/telepathyClient.js:1477
msgid "Reconnect"
msgstr "Torna a connectar"
#: ../js/ui/telepathyClient.js:1473
#: ../js/ui/telepathyClient.js:1478
msgid "Edit account"
msgstr "Edita el compte"
#: ../js/ui/telepathyClient.js:1519
#: ../js/ui/telepathyClient.js:1524
msgid "Unknown reason"
msgstr "Motiu desconegut"
@ -1503,39 +1506,39 @@ msgstr "Inactiu"
msgid "Unavailable"
msgstr "No disponible"
#: ../js/ui/userMenu.js:512 ../js/ui/userMenu.js:516 ../js/ui/userMenu.js:586
#: ../js/ui/userMenu.js:552 ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:626
msgid "Power Off..."
msgstr "Apaga..."
#: ../js/ui/userMenu.js:548
#: ../js/ui/userMenu.js:588
msgid "Notifications"
msgstr "Notificacions"
#: ../js/ui/userMenu.js:556
#: ../js/ui/userMenu.js:596
msgid "Online Accounts"
msgstr "Comptes en línia"
#: ../js/ui/userMenu.js:560
#: ../js/ui/userMenu.js:600
msgid "System Settings"
msgstr "Paràmetres de l'ordinador"
#: ../js/ui/userMenu.js:567
#: ../js/ui/userMenu.js:607
msgid "Lock Screen"
msgstr "Bloca la pantalla"
#: ../js/ui/userMenu.js:572
#: ../js/ui/userMenu.js:612
msgid "Switch User"
msgstr "Canvia d'usuari"
#: ../js/ui/userMenu.js:577
#: ../js/ui/userMenu.js:617
msgid "Log Out..."
msgstr "Ix..."
#: ../js/ui/userMenu.js:605
#: ../js/ui/userMenu.js:645
msgid "Your chat status will be set to busy"
msgstr "L'estat del xat s'establirà a ocupat"
#: ../js/ui/userMenu.js:606
#: ../js/ui/userMenu.js:646
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1548,11 +1551,11 @@ msgstr ""
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: ../js/ui/viewSelector.js:120
#: ../js/ui/viewSelector.js:121
msgid "Type to search..."
msgstr "Teclegeu per cercar..."
#: ../js/ui/viewSelector.js:140 ../src/shell-util.c:261
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:261
msgid "Search"
msgstr "Cerca"
@ -1591,7 +1594,7 @@ msgstr "Mostra la versió"
msgid "Mode used by GDM for login screen"
msgstr "El mode que utilitzarà el GDM per a la pantalla d'entrada"
#: ../src/shell-app.c:581
#: ../src/shell-app.c:579
#, c-format
msgid "Failed to launch '%s'"
msgstr "No s'ha pogut iniciar «%s»"
@ -1628,6 +1631,18 @@ msgstr "Sistema de fitxers"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Show password"
#~ msgstr "Mostra la contrasenya"
#~ msgid "%s has not emitted any errors."
#~ msgstr "%s no ha emès cap error."
#~ msgid "Hide Errors"
#~ msgstr "Amaga els errors"
#~ msgid "Show Errors"
#~ msgstr "Mostra els errors"
#~ msgid "%s has finished starting"
#~ msgstr "S'ha acabat d'iniciar %s"

687
po/cs.po

File diff suppressed because it is too large Load Diff

775
po/da.po

File diff suppressed because it is too large Load Diff

221
po/de.po
View File

@ -6,7 +6,7 @@
#
# Hendrik Brandt <heb@gnome-de.org>, 2009.
# Hendrik Richter <hendrikr@gnome.org>, 2009, 2010, 2011.
# Mario Blättermann <mario.blaettermann@gmail.com>, 2009-2011.
# Mario Blättermann <mariobl@freenet.de>, 2009, 2010, 2011.
# Mario Klug <mario@klug.me>, 2010.
# Jakob Kramer <jakob.kramer@gmx.de>, 2010.
# Paul Seyfert <pseyfert@mathphys.fsk.uni-heidelberg.de>, 2010, 2011.
@ -17,9 +17,9 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2011-11-05 13:23+0000\n"
"PO-Revision-Date: 2011-11-05 21:08+0100\n"
"Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\n"
"POT-Creation-Date: 2011-10-17 20:04+0000\n"
"PO-Revision-Date: 2011-10-17 22:05+0100\n"
"Last-Translator: Paul Seyfert <pseyfert@mathphys.fsk.uni-heidelberg.de>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -56,12 +56,10 @@ msgid "Framerate used for recording screencasts."
msgstr "Bildwiederholungsrate zur Aufnahme von Screencasts"
#: ../data/org.gnome.shell.gschema.xml.in.h:5
#, fuzzy
msgid ""
"GNOME Shell extensions have a uuid property; this key lists extensions which "
"should be loaded. Any extension that wants to be loaded needs to be in this "
"list. You can also manipulate this list with the EnableExtension and "
"DisableExtension DBus methods on org.gnome.Shell."
"should be loaded. disabled-extensions overrides this setting for extensions "
"that appear in both lists."
msgstr ""
"Die Erweiterungen der GNOME-Shell besitzen eine UUID-Eigenschaft. Dieser "
"Schlüssel listet Erweiterungen auf, welche geladen werden sollen. »disabled-"
@ -115,11 +113,11 @@ msgstr ""
"Auffüllung haben; die Ausgabe dieser Auffüllung wird in die Ausgabedatei "
"geschrieben. Die Weiterleitung kann auch mit ihrer eigenen Ausgabe umgehen. "
"Das kann zum Senden der Ausgabe über shout2send an einen Icecast-Server oder "
"Ähnliches verwendet werden. Falls nicht (oder auf einen leeren Wert) gesetzt, "
"so wird die vorgegebene Weiterleitung verwendet, welche derzeit »videorate ! "
"vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux« lautet und nach WEBM "
"mittels des VP8-Codecs aufzeichnet. %T wird als Platzhalter für die vermutete "
"optimale Threadanzahl auf dem System verwendet."
"Ähnliches verwendet werden. Falls nicht (oder auf einen leeren Wert) "
"gesetzt, so wird die vorgegebene Weiterleitung verwendet, welche derzeit "
"»videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux« lautet "
"und nach WEBM mittels des VP8-Codecs aufzeichnet. %T wird als Platzhalter "
"für die vermutete optimale Threadanzahl auf dem System verwendet."
#: ../data/org.gnome.shell.gschema.xml.in.h:14
msgid "Show date in clock"
@ -138,8 +136,8 @@ msgid ""
"The applications corresponding to these identifiers will be displayed in the "
"favorites area."
msgstr ""
"Programme, welche auf diese Bezeichner zutreffen, werden im Favoriten-Bereich "
"angezeigt."
"Programme, welche auf diese Bezeichner zutreffen, werden im Favoriten-"
"Bereich angezeigt."
#: ../data/org.gnome.shell.gschema.xml.in.h:18
msgid ""
@ -198,50 +196,52 @@ msgstr "Zu verwendende Tastatur"
msgid "disabled OpenSearch providers"
msgstr "deaktivierte OpenSearch-Provider"
#: ../js/gdm/loginDialog.js:633
#: ../js/gdm/loginDialog.js:617
msgid "Session..."
msgstr "Sitzung …"
#: ../js/gdm/loginDialog.js:804
#: ../js/gdm/loginDialog.js:788
msgctxt "title"
msgid "Sign In"
msgstr "Anmelden"
#. translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:849
#: ../js/gdm/loginDialog.js:833
msgid "(or swipe finger)"
msgstr "(oder benutzen Sie den Fingerabdruckleser)"
#: ../js/gdm/loginDialog.js:867
#: ../js/gdm/loginDialog.js:851
msgid "Not listed?"
msgstr "Nicht aufgeführt?"
#: ../js/gdm/loginDialog.js:1035 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:519 ../js/ui/networkAgent.js:148
#: ../js/gdm/loginDialog.js:1019 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:148
#: ../js/ui/polkitAuthenticationAgent.js:173 ../js/ui/status/bluetooth.js:480
msgid "Cancel"
msgstr "Abbrechen"
#: ../js/gdm/loginDialog.js:1040
#: ../js/gdm/loginDialog.js:1024
msgctxt "button"
msgid "Sign In"
msgstr "Anmelden"
#: ../js/gdm/loginDialog.js:1392
#: ../js/gdm/loginDialog.js:1373
msgid "Login Window"
msgstr "Anmeldefenster"
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:573 ../js/ui/userMenu.js:575
#: ../js/ui/userMenu.js:644
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:549
#: ../js/ui/userMenu.js:551 ../js/ui/userMenu.js:620
msgid "Suspend"
msgstr "Bereitschaft"
#: ../js/gdm/powerMenu.js:121
#: ../js/gdm/powerMenu.js:121 ../js/ui/endSessionDialog.js:89
#: ../js/ui/endSessionDialog.js:97 ../js/ui/endSessionDialog.js:106
msgid "Restart"
msgstr "Neu starten"
#: ../js/gdm/powerMenu.js:126
#: ../js/gdm/powerMenu.js:126 ../js/ui/endSessionDialog.js:80
#: ../js/ui/endSessionDialog.js:91
msgid "Power Off"
msgstr "Ausschalten"
@ -458,8 +458,8 @@ msgstr "Diese Woche"
msgid "Next week"
msgstr "Nächste Woche"
#: ../js/ui/contactDisplay.js:65 ../js/ui/notificationDaemon.js:459
#: ../js/ui/status/power.js:223 ../src/shell-app.c:350
#: ../js/ui/contactDisplay.js:65 ../js/ui/notificationDaemon.js:444
#: ../js/ui/status/power.js:223 ../src/shell-app.c:353
msgid "Unknown"
msgstr "Unbekannt"
@ -483,7 +483,7 @@ msgstr "Abgemeldet"
msgid "CONTACTS"
msgstr "KONTAKTE"
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1214
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1205
msgid "Remove"
msgstr "Entfernen"
@ -548,12 +548,10 @@ msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
#: ../js/ui/endSessionDialog.js:60
#, c-format
msgctxt "title"
msgid "Log Out %s"
msgstr "%s abmelden"
#: ../js/ui/endSessionDialog.js:61
msgctxt "title"
#: ../js/ui/endSessionDialog.js:61 ../js/ui/endSessionDialog.js:75
msgid "Log Out"
msgstr "Abmelden"
@ -581,16 +579,6 @@ msgstr[1] "Sie werden automatisch in %d Sekunden abgemeldet."
msgid "Logging out of the system."
msgstr "Abmeldung vom System."
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "Abmelden"
#: ../js/ui/endSessionDialog.js:80
msgctxt "title"
msgid "Power Off"
msgstr "Ausschalten"
#: ../js/ui/endSessionDialog.js:81
msgid "Click Power Off to quit these applications and power off the system."
msgstr ""
@ -608,21 +596,6 @@ msgstr[1] "Das System wird automatisch in %d Sekunden ausgeschaltet."
msgid "Powering off the system."
msgstr "Das System wird ausgeschaltet."
#: ../js/ui/endSessionDialog.js:89 ../js/ui/endSessionDialog.js:106
msgctxt "button"
msgid "Restart"
msgstr "Neu starten"
#: ../js/ui/endSessionDialog.js:91
msgctxt "button"
msgid "Power Off"
msgstr "Ausschalten"
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "Neu starten"
#: ../js/ui/endSessionDialog.js:98
msgid "Click Restart to quit these applications and restart the system."
msgstr ""
@ -640,11 +613,11 @@ msgstr[1] "Das System wird automatisch in %d Sekunden neu gestartet."
msgid "Restarting the system."
msgstr "Neustart des Systems."
#: ../js/ui/extensionSystem.js:523
#: ../js/ui/extensionSystem.js:481
msgid "Install"
msgstr "Installieren"
#: ../js/ui/extensionSystem.js:527
#: ../js/ui/extensionSystem.js:485
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "»%s« von extensions.gnome.org herunterladen und installieren?"
@ -657,68 +630,45 @@ msgstr "Benachrichtigungsfeld"
msgid "Keyboard"
msgstr "Tastatur"
#: ../js/ui/lookingGlass.js:664
#: ../js/ui/lookingGlass.js:646
msgid "No extensions installed"
msgstr "Keine Erweiterungen installiert"
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:719
#, c-format
msgid "%s has not emitted any errors."
msgstr "%s hat keine Fehler ausgegeben."
#: ../js/ui/lookingGlass.js:725
msgid "Hide Errors"
msgstr "Fehler verbergen"
#: ../js/ui/lookingGlass.js:729 ../js/ui/lookingGlass.js:780
msgid "Show Errors"
msgstr "Fehler anzeigen"
#: ../js/ui/lookingGlass.js:738
#: ../js/ui/lookingGlass.js:692
msgid "Enabled"
msgstr "Aktiviert"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:741 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:694 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Deaktiviert"
#: ../js/ui/lookingGlass.js:743
#: ../js/ui/lookingGlass.js:696
msgid "Error"
msgstr "Fehler"
#: ../js/ui/lookingGlass.js:745
#: ../js/ui/lookingGlass.js:698
msgid "Out of date"
msgstr "Veraltet"
#: ../js/ui/lookingGlass.js:747
#: ../js/ui/lookingGlass.js:700
msgid "Downloading"
msgstr "Herunterladen"
#: ../js/ui/lookingGlass.js:768
#: ../js/ui/lookingGlass.js:721
msgid "View Source"
msgstr "Quelle zeigen"
#: ../js/ui/lookingGlass.js:774
#: ../js/ui/lookingGlass.js:727
msgid "Web Page"
msgstr "Webseite"
#: ../js/ui/messageTray.js:1207
#: ../js/ui/messageTray.js:1198
msgid "Open"
msgstr "Öffnen"
#: ../js/ui/messageTray.js:1224
#, fuzzy
msgid "Unmute"
msgstr "Minute"
#: ../js/ui/messageTray.js:1224
msgid "Mute"
msgstr "Stumm"
#: ../js/ui/messageTray.js:2436
#: ../js/ui/messageTray.js:2407
msgid "System Information"
msgstr "Systeminformationen"
@ -764,7 +714,8 @@ msgstr "Legitimierung für Funknetzwerk wird benötigt"
#: ../js/ui/networkAgent.js:325
#, c-format
msgid ""
"Passwords or encryption keys are required to access the wireless network '%s'."
"Passwords or encryption keys are required to access the wireless network '%"
"s'."
msgstr ""
"Passwörter oder Schlüssel sind erforderlich, um auf das Funknetzwerk »%s« "
"zuzugreifen."
@ -1139,13 +1090,13 @@ msgstr "nicht verfügbar"
msgid "connection failed"
msgstr "Verbindung gescheitert"
#: ../js/ui/status/network.js:575 ../js/ui/status/network.js:1532
#: ../js/ui/status/network.js:575 ../js/ui/status/network.js:1523
msgid "More..."
msgstr "Mehr ..."
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:611 ../js/ui/status/network.js:1467
#: ../js/ui/status/network.js:611 ../js/ui/status/network.js:1458
msgid "Connected (private)"
msgstr "Verbunden (privat)"
@ -1162,7 +1113,7 @@ msgid "Auto dial-up"
msgstr "Einwählverbindung (automatisch)"
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:878 ../js/ui/status/network.js:1479
#: ../js/ui/status/network.js:878 ../js/ui/status/network.js:1470
#, c-format
msgid "Auto %s"
msgstr "%s (automatisch)"
@ -1171,47 +1122,47 @@ msgstr "%s (automatisch)"
msgid "Auto bluetooth"
msgstr "Bluetooth (automatisch)"
#: ../js/ui/status/network.js:1481
#: ../js/ui/status/network.js:1472
msgid "Auto wireless"
msgstr "Drahtlos (automatisch)"
#: ../js/ui/status/network.js:1575
#: ../js/ui/status/network.js:1566
msgid "Enable networking"
msgstr "Netzwerk aktivieren"
#: ../js/ui/status/network.js:1587
#: ../js/ui/status/network.js:1578
msgid "Wired"
msgstr "Kabelgebunden"
#: ../js/ui/status/network.js:1598
#: ../js/ui/status/network.js:1589
msgid "Wireless"
msgstr "Drahtlos"
#: ../js/ui/status/network.js:1608
#: ../js/ui/status/network.js:1599
msgid "Mobile broadband"
msgstr "Mobiles Breitband"
#: ../js/ui/status/network.js:1618
#: ../js/ui/status/network.js:1609
msgid "VPN Connections"
msgstr "VPN-Verbindungen"
#: ../js/ui/status/network.js:1629
#: ../js/ui/status/network.js:1620
msgid "Network Settings"
msgstr "Netzwerkeinstellungen"
#: ../js/ui/status/network.js:1766
#: ../js/ui/status/network.js:1757
msgid "Connection failed"
msgstr "Verbindung gescheitert"
#: ../js/ui/status/network.js:1767
#: ../js/ui/status/network.js:1758
msgid "Activation of network connection failed"
msgstr "Aktivierung der Netzwerkverbindung ist gescheitert"
#: ../js/ui/status/network.js:2017
#: ../js/ui/status/network.js:2008
msgid "Networking is disabled"
msgstr "Netzwerk ist deaktiviert"
#: ../js/ui/status/network.js:2144
#: ../js/ui/status/network.js:2133
msgid "Network Manager"
msgstr "Netzwerk-Verwaltung"
@ -1512,7 +1463,8 @@ msgid "This resource is already connected to the server"
msgstr "Diese Ressource ist bereits mit dem Server verbunden"
#: ../js/ui/telepathyClient.js:1449
msgid "Connection has been replaced by a new connection using the same resource"
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Die Verbindung wurde durch eine neue Verbindung mit der gleichen Ressource "
"ersetzt"
@ -1577,39 +1529,39 @@ msgstr "Untätig"
msgid "Unavailable"
msgstr "Nicht verfügbar"
#: ../js/ui/userMenu.js:571 ../js/ui/userMenu.js:575 ../js/ui/userMenu.js:645
#: ../js/ui/userMenu.js:547 ../js/ui/userMenu.js:551 ../js/ui/userMenu.js:621
msgid "Power Off..."
msgstr "Ausschalten …"
#: ../js/ui/userMenu.js:607
#: ../js/ui/userMenu.js:583
msgid "Notifications"
msgstr "Benachrichtigungen"
#: ../js/ui/userMenu.js:615
#: ../js/ui/userMenu.js:591
msgid "Online Accounts"
msgstr "Online-Konten"
#: ../js/ui/userMenu.js:619
#: ../js/ui/userMenu.js:595
msgid "System Settings"
msgstr "Systemeinstellungen"
#: ../js/ui/userMenu.js:626
#: ../js/ui/userMenu.js:602
msgid "Lock Screen"
msgstr "Bildschirm sperren"
#: ../js/ui/userMenu.js:631
#: ../js/ui/userMenu.js:607
msgid "Switch User"
msgstr "Benutzer wechseln"
#: ../js/ui/userMenu.js:636
#: ../js/ui/userMenu.js:612
msgid "Log Out..."
msgstr "Abmelden …"
#: ../js/ui/userMenu.js:664
#: ../js/ui/userMenu.js:640
msgid "Your chat status will be set to busy"
msgstr "Ihr Anwesenheitsstatus wird auf »Beschäftigt« gesetzt"
#: ../js/ui/userMenu.js:665
#: ../js/ui/userMenu.js:641
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1626,7 +1578,7 @@ msgstr ""
msgid "Type to search..."
msgstr "Suchbegriff eingeben …"
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:244
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:261
msgid "Search"
msgstr "Suchen"
@ -1657,15 +1609,15 @@ msgstr[1] "%u Eingänge"
msgid "System Sounds"
msgstr "Systemklänge"
#: ../src/main.c:483
#: ../src/main.c:480
msgid "Print version"
msgstr "Version ausgeben"
#: ../src/main.c:489
#: ../src/main.c:486
msgid "Mode used by GDM for login screen"
msgstr "Der durch GDM im Anmeldefenster verwendete Modus"
#: ../src/shell-app.c:567
#: ../src/shell-app.c:579
#, c-format
msgid "Failed to launch '%s'"
msgstr "»%s« konnte nicht gestartet werden"
@ -1682,16 +1634,13 @@ msgstr "Vorgabe"
msgid "Authentication dialog was dismissed by the user"
msgstr "Der Dialog zur Legitimierung wurde vom Benutzer geschlossen"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:89
#, fuzzy
msgid "Home"
msgstr "Lautstärke"
#: ../src/shell-util.c:100
msgid "Home Folder"
msgstr "Persönlicher Ordner"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:98
#: ../src/shell-util.c:115
msgid "File System"
msgstr "Dateisystem"
@ -1700,17 +1649,23 @@ msgstr "Dateisystem"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-util.c:294
#: ../src/shell-util.c:311
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Home Folder"
#~ msgstr "Persönlicher Ordner"
#~ msgid "Show password"
#~ msgstr "Passwort anzeigen"
#~ msgid "%s has not emitted any errors."
#~ msgstr "%s hat keine Fehler ausgegeben."
#~ msgid "Hide Errors"
#~ msgstr "Fehler verbergen"
#~ msgid "Show Errors"
#~ msgstr "Fehler anzeigen"
#~ msgid "%s has finished starting"
#~ msgstr "Start von %s ist abgeschlossen"

1405
po/el.po

File diff suppressed because it is too large Load Diff

131
po/eo.po
View File

@ -9,14 +9,14 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2011-10-26 09:56+0000\n"
"PO-Revision-Date: 2011-10-26 19:08+0200\n"
"POT-Creation-Date: 2011-10-24 17:45+0000\n"
"PO-Revision-Date: 2011-10-26 19:01+0200\n"
"Last-Translator: Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>\n"
"Language-Team: Esperanto <ubuntu-l10n-eo@lists.launchpad.net>\n"
"Language: eo\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bits\n"
"Language: eo\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Virtaal 0.7.1-rc1\n"
"X-DamnedLies-Scope: partial\n"
@ -186,7 +186,7 @@ msgid "Not listed?"
msgstr "Ĉu ne en listo?"
#: ../js/gdm/loginDialog.js:1035 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:520 ../js/ui/networkAgent.js:148
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:148
#: ../js/ui/polkitAuthenticationAgent.js:173 ../js/ui/status/bluetooth.js:480
msgid "Cancel"
msgstr "Nuligi"
@ -200,16 +200,18 @@ msgstr "Ensaluti"
msgid "Login Window"
msgstr "Ensalutfenestro"
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:573
#: ../js/ui/userMenu.js:575 ../js/ui/userMenu.js:644
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:554
#: ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:625
msgid "Suspend"
msgstr "Dormeti"
#: ../js/gdm/powerMenu.js:121
#: ../js/gdm/powerMenu.js:121 ../js/ui/endSessionDialog.js:89
#: ../js/ui/endSessionDialog.js:97 ../js/ui/endSessionDialog.js:106
msgid "Restart"
msgstr "Restartigi"
#: ../js/gdm/powerMenu.js:126
#: ../js/gdm/powerMenu.js:126 ../js/ui/endSessionDialog.js:80
#: ../js/ui/endSessionDialog.js:91
msgid "Power Off"
msgstr "Elŝalti"
@ -427,7 +429,7 @@ msgid "Next week"
msgstr "Sekva semajno"
#: ../js/ui/contactDisplay.js:65 ../js/ui/notificationDaemon.js:459
#: ../js/ui/status/power.js:223 ../src/shell-app.c:350
#: ../js/ui/status/power.js:223 ../src/shell-app.c:353
msgid "Unknown"
msgstr "Nekonata"
@ -516,12 +518,10 @@ msgstr "LASTATEMPAJ ELEMENTOJ"
#: ../js/ui/endSessionDialog.js:60
#, c-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Elsaluti %s"
#: ../js/ui/endSessionDialog.js:61
msgctxt "title"
#: ../js/ui/endSessionDialog.js:61 ../js/ui/endSessionDialog.js:75
msgid "Log Out"
msgstr "Elsaluti"
@ -548,16 +548,6 @@ msgstr[1] "Vi aŭtomate elsalutos post %d sekundoj."
msgid "Logging out of the system."
msgstr "Elsalutanta de la sistemo."
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "Elsaluti"
#: ../js/ui/endSessionDialog.js:80
msgctxt "title"
msgid "Power Off"
msgstr "Elŝalti"
#: ../js/ui/endSessionDialog.js:81
msgid "Click Power Off to quit these applications and power off the system."
msgstr "Alklaku \"Elŝalti\" por ĉesi tiujn aplikaĵojn kaj elŝalti la sistemon."
@ -573,21 +563,6 @@ msgstr[1] "La sistemo aŭtomate elŝaltiĝos post %d sekundoj."
msgid "Powering off the system."
msgstr "Elŝaltanta la sistemon."
#: ../js/ui/endSessionDialog.js:89 ../js/ui/endSessionDialog.js:106
msgctxt "button"
msgid "Restart"
msgstr "Restartigi"
#: ../js/ui/endSessionDialog.js:91
msgctxt "button"
msgid "Power Off"
msgstr "Elŝalti"
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "Restartigi"
#: ../js/ui/endSessionDialog.js:98
msgid "Click Restart to quit these applications and restart the system."
msgstr ""
@ -604,11 +579,11 @@ msgstr[1] "La sistemo aŭtomate restartos post %d sekundoj."
msgid "Restarting the system."
msgstr "Restartiganta la sistemon."
#: ../js/ui/extensionSystem.js:524
#: ../js/ui/extensionSystem.js:481
msgid "Install"
msgstr "Instali"
#: ../js/ui/extensionSystem.js:528
#: ../js/ui/extensionSystem.js:485
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Elŝuti kaj instali '%s' de extensions.gnome.org?"
@ -621,51 +596,37 @@ msgstr "pleto"
msgid "Keyboard"
msgstr "Klavaro"
#: ../js/ui/lookingGlass.js:664
#: ../js/ui/lookingGlass.js:646
msgid "No extensions installed"
msgstr "Neniu kromprogramo instalita"
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:719
#, c-format
msgid "%s has not emitted any errors."
msgstr "%s ne eligintaj ajnaj eraroj."
#: ../js/ui/lookingGlass.js:725
msgid "Hide Errors"
msgstr "Kaŝi erarojn"
#: ../js/ui/lookingGlass.js:729 ../js/ui/lookingGlass.js:779
msgid "Show Errors"
msgstr "Montri erarojn"
#: ../js/ui/lookingGlass.js:738
#: ../js/ui/lookingGlass.js:692
msgid "Enabled"
msgstr "Enŝaltita"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:740 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:694 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Elŝaltita"
#: ../js/ui/lookingGlass.js:742
#: ../js/ui/lookingGlass.js:696
msgid "Error"
msgstr "Eraro"
#: ../js/ui/lookingGlass.js:744
#: ../js/ui/lookingGlass.js:698
msgid "Out of date"
msgstr "Neaktuala"
#: ../js/ui/lookingGlass.js:746
#: ../js/ui/lookingGlass.js:700
msgid "Downloading"
msgstr "Elŝutanta"
#: ../js/ui/lookingGlass.js:767
#: ../js/ui/lookingGlass.js:721
msgid "View Source"
msgstr "Montri fonton"
#: ../js/ui/lookingGlass.js:773
#: ../js/ui/lookingGlass.js:727
msgid "Web Page"
msgstr "Retpaĝo"
@ -1528,39 +1489,39 @@ msgstr "Neokupita"
msgid "Unavailable"
msgstr "Nedisponebla"
#: ../js/ui/userMenu.js:571 ../js/ui/userMenu.js:575 ../js/ui/userMenu.js:645
#: ../js/ui/userMenu.js:552 ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:626
msgid "Power Off..."
msgstr "Elŝalti..."
#: ../js/ui/userMenu.js:607
#: ../js/ui/userMenu.js:588
msgid "Notifications"
msgstr "Avizoj"
#: ../js/ui/userMenu.js:615
#: ../js/ui/userMenu.js:596
msgid "Online Accounts"
msgstr "Retaj kontoj"
#: ../js/ui/userMenu.js:619
#: ../js/ui/userMenu.js:600
msgid "System Settings"
msgstr "Sistem-agordoj"
#: ../js/ui/userMenu.js:626
#: ../js/ui/userMenu.js:607
msgid "Lock Screen"
msgstr "Ŝlosi ekranon"
#: ../js/ui/userMenu.js:631
#: ../js/ui/userMenu.js:612
msgid "Switch User"
msgstr "Ŝanĝi uzanton"
#: ../js/ui/userMenu.js:636
#: ../js/ui/userMenu.js:617
msgid "Log Out..."
msgstr "Elsaluti..."
#: ../js/ui/userMenu.js:664
#: ../js/ui/userMenu.js:645
msgid "Your chat status will be set to busy"
msgstr "Vi babila stato agordos okupita"
#: ../js/ui/userMenu.js:665
#: ../js/ui/userMenu.js:646
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1576,7 +1537,7 @@ msgstr ""
msgid "Type to search..."
msgstr "Tajpi por serĉi..."
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:244
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:261
msgid "Search"
msgstr "Serĉi"
@ -1607,15 +1568,15 @@ msgstr[1] "%u enigoj"
msgid "System Sounds"
msgstr "Sistemsonoj"
#: ../src/main.c:483
#: ../src/main.c:480
msgid "Print version"
msgstr "Presi version"
#: ../src/main.c:489
#: ../src/main.c:486
msgid "Mode used by GDM for login screen"
msgstr "Reĝimo uzata de GDM por la ensalutekrano"
#: ../src/shell-app.c:567
#: ../src/shell-app.c:579
#, c-format
msgid "Failed to launch '%s'"
msgstr "Malsukcesis lanĉi '%s'"
@ -1632,15 +1593,13 @@ msgstr "Defaŭlto"
msgid "Authentication dialog was dismissed by the user"
msgstr "La dialogo de la aŭtentokontrolo malakceptis de la uzanto"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:89
msgid "Home"
msgstr "Hejmo"
#: ../src/shell-util.c:100
msgid "Home Folder"
msgstr "Hejma dosierujo"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:98
#: ../src/shell-util.c:115
msgid "File System"
msgstr "Dosiersistemo"
@ -1649,13 +1608,19 @@ msgstr "Dosiersistemo"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-util.c:294
#: ../src/shell-util.c:311
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Home Folder"
#~ msgstr "Hejma dosierujo"
#~ msgid "%s has not emitted any errors."
#~ msgstr "%s ne eligintaj ajnaj eraroj."
#~ msgid "Hide Errors"
#~ msgstr "Kaŝi erarojn"
#~ msgid "Show Errors"
#~ msgstr "Montri erarojn"
#~ msgid "Show password"
#~ msgstr "Montri pasvorton"

777
po/es.po

File diff suppressed because it is too large Load Diff

786
po/et.po

File diff suppressed because it is too large Load Diff

518
po/fi.po

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More