Compare commits

..

3 Commits

Author SHA1 Message Date
986afdc0c5 Port client side code to GDBus
This continues the series of patches for GDBus porting, affecting
all code that accesses remote DBus objects. This includes modemManager,
automount, autorun (for the hotplug sniffer), calendar, network (for
nm-applet only), power, scripting (for perf monitor interface)

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-15 08:55:53 -05:00
e6dc843786 notificationDaemon, magnifierDBus: port to GDBus
Move /org/freedesktop/Notifications and /org/gnome/Magnifier to the
GDBus connection, so they're matched with the appropriate DBus name.

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-15 08:55:35 -05:00
9eb671bb08 screensaver, gnomesession: port to GDBus based bindings
Port org.gnome.ScreenSaver and org.gnome.SessionManager glue code
to use GDBus, and move /org/gnome/Shell/EndSessionDialog to the
GDBus connection, so it is backed by the org.gnome.Shell name.

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-15 08:54:39 -05:00
142 changed files with 10755 additions and 17430 deletions
NEWS
browser-plugin
configure.ac
data
docs/reference
js
po
src
tests

145
NEWS

@ -1,148 +1,3 @@
3.3.4
=====
* https://live.gnome.org/EveryDetailMatters
- Add "browse" for labels for dash items - once a tooltip is
showing, switch to other items without a delay [Seif; #666170]
- Always scale down windows in the overview at least to 70% [Vit; #646704]
- Fix the new-workspace drop indicator sometimes getting stuck
[Stefano; #664201]
- Delay rearranging windows in the overview as long as the pointer
is over a window [Vit; #645325]
* Add a GConf => DConf migration file for overriden Mutter settings
[Florian; #667636]
* When a VPN connection is active, show that as the network icon
[Giovanni; #665115]
* Handle the "ExtendedAway" IM status as away, not offline [Guillaume; #667813]
* Improve the appearance of the labels in "Applications" [Alex; #642392]
* Adjust for GTK+ and Mutter API changes for application menu [Ryan; #668118]
* Add section label support to the application menu [Giovanni; #666681]
* Fix screenshot methods to work again [Cosimo; #667662]
* Fix several crashers related to updating workspace thumbnails [Owen; #667652]
* Fix memory management error causing gnome-shell-hotplug-sniffer to crash
[Owen; #667378]
* Build fixes [Emmanuele, Rico; #667864]
* Code cleanups [Adel; #668087]
* Misc bug fixes [Colin, Florian, Giovanni, Owen, Xavier; #633028, #658817,
#664138, #667881, #668048, #668050]
Contributors:
Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Xavier Claessens,
Guillaume Desmottes, Stefano Facchini, Adel Gadllah, Alex Hultman,
Ryan Lortie, Seif Lotfy, Florian Müllner, Vit Stanislav, Owen Taylor,
Rico Tzschichholz, Colin Walters
Translations:
Ihar Hrachyshka [be], Alexander Shopov [bg], Arash Mousavi [fa],
Jiri Grönroos, Timo Jyrinki [fi], Fran Diéguez [gl], Kjartan Maraas [nb],
Yuri Myasoedov [ru], Matej Urbančič [sl], Nguyễn Thái Ngọc Duy [vi]
3.3.3
=====
* 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,
#664138, #665261, #666020, #666243]
* Build fixes [Owen]
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, Owen Taylor, Colin Walters, Ron Yorsten,
Marina Zhurakhinskaya
Translations:
Petr Kovar [cz], Kris Thomsen [dk], Daniel Mustieles [es],
Ville-Pekka Vainio [fi], Yaron Shahrabani [he], Luca Ferretti [it],
Hideki Yamane [ja], Ž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]
3.2.1 3.2.1
===== =====
* Restore the IM state on startup - if you were available in when you logged * Restore the IM state on startup - if you were available in when you logged

@ -455,7 +455,7 @@ plugin_enable_extension (PluginObject *obj,
NPString uuid, NPString uuid,
gboolean enabled) gboolean enabled)
{ {
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); const gchar *uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str)) if (!uuid_is_valid (uuid_str))
return FALSE; return FALSE;
@ -468,8 +468,6 @@ plugin_enable_extension (PluginObject *obj,
NULL, /* callback */ NULL, /* callback */
NULL /* user_data */); NULL /* user_data */);
g_free (uuid_str);
return TRUE; return TRUE;
} }
@ -478,32 +476,21 @@ plugin_install_extension (PluginObject *obj,
NPString uuid, NPString uuid,
NPString version_tag) NPString version_tag)
{ {
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); const gchar *uuid_str = uuid.UTF8Characters;
gchar *version_tag_str;
if (!uuid_is_valid (uuid_str)) if (!uuid_is_valid (uuid_str))
{ return FALSE;
g_free (uuid_str);
return FALSE;
}
version_tag_str = g_strndup (version_tag.UTF8Characters,
version_tag.UTF8Length);
g_dbus_proxy_call (obj->proxy, g_dbus_proxy_call (obj->proxy,
"InstallRemoteExtension", "InstallRemoteExtension",
g_variant_new ("(ss)", g_variant_new ("(ss)",
uuid_str, uuid_str,
version_tag_str), version_tag.UTF8Characters),
G_DBUS_CALL_FLAGS_NONE, G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */ -1, /* timeout */
NULL, /* cancellable */ NULL, /* cancellable */
NULL, /* callback */ NULL, /* callback */
NULL /* user_data */); NULL /* user_data */);
g_free (uuid_str);
g_free (version_tag_str);
return TRUE; return TRUE;
} }
@ -514,14 +501,11 @@ plugin_uninstall_extension (PluginObject *obj,
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
gchar *uuid_str; const gchar *uuid_str;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str)) if (!uuid_is_valid (uuid_str))
{ return FALSE;
g_free (uuid_str);
return FALSE;
}
res = g_dbus_proxy_call_sync (obj->proxy, res = g_dbus_proxy_call_sync (obj->proxy,
"UninstallExtension", "UninstallExtension",
@ -532,8 +516,6 @@ plugin_uninstall_extension (PluginObject *obj,
NULL, /* cancellable */ NULL, /* cancellable */
&error); &error);
g_free (uuid_str);
if (!res) if (!res)
{ {
g_warning ("Failed to uninstall extension: %s", error->message); g_warning ("Failed to uninstall extension: %s", error->message);
@ -551,14 +533,11 @@ plugin_get_info (PluginObject *obj,
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
gchar *uuid_str; const gchar *uuid_str;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str)) if (!uuid_is_valid (uuid_str))
{ return FALSE;
g_free (uuid_str);
return FALSE;
}
res = g_dbus_proxy_call_sync (obj->proxy, res = g_dbus_proxy_call_sync (obj->proxy,
"GetExtensionInfo", "GetExtensionInfo",
@ -568,8 +547,6 @@ plugin_get_info (PluginObject *obj,
NULL, /* cancellable */ NULL, /* cancellable */
&error); &error);
g_free (uuid_str);
if (!res) if (!res)
{ {
g_warning ("Failed to retrieve extension metadata: %s", error->message); g_warning ("Failed to retrieve extension metadata: %s", error->message);
@ -587,14 +564,11 @@ plugin_get_errors (PluginObject *obj,
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
gchar *uuid_str; const gchar *uuid_str;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str)) if (!uuid_is_valid (uuid_str))
{ return FALSE;
g_free (uuid_str);
return FALSE;
}
res = g_dbus_proxy_call_sync (obj->proxy, res = g_dbus_proxy_call_sync (obj->proxy,
"GetExtensionErrors", "GetExtensionErrors",
@ -604,8 +578,6 @@ plugin_get_errors (PluginObject *obj,
NULL, /* cancellable */ NULL, /* cancellable */
&error); &error);
g_free (uuid_str);
if (!res) if (!res)
{ {
g_warning ("Failed to retrieve errors: %s", error->message); g_warning ("Failed to retrieve errors: %s", error->message);
@ -661,8 +633,7 @@ plugin_get_shell_version (PluginObject *obj,
STRINGN_TO_NPVARIANT (buffer, length, *result); STRINGN_TO_NPVARIANT (buffer, length, *result);
out: out:
if (res) g_variant_unref (res);
g_variant_unref (res);
return ret; return ret;
} }

@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.3.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.2.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@ -63,14 +63,14 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.7.5 CLUTTER_MIN_VERSION=1.7.5
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.29.18 GJS_MIN_VERSION=1.29.18
MUTTER_MIN_VERSION=3.3.3 MUTTER_MIN_VERSION=3.2.1
FOLKS_MIN_VERSION=0.5.2 FOLKS_MIN_VERSION=0.5.2
GTK_MIN_VERSION=3.3.9 GTK_MIN_VERSION=3.0.0
GIO_MIN_VERSION=2.31.6 GIO_MIN_VERSION=2.31.0
LIBECAL_MIN_VERSION=2.32.0 LIBECAL_MIN_VERSION=2.32.0
LIBEDATASERVER_MIN_VERSION=1.2.0 LIBEDATASERVER_MIN_VERSION=1.2.0
LIBEDATASERVERUI_MIN_VERSION=2.91.6 LIBEDATASERVERUI_MIN_VERSION=2.91.6
TELEPATHY_GLIB_MIN_VERSION=0.15.6 TELEPATHY_GLIB_MIN_VERSION=0.15.5
TELEPATHY_LOGGER_MIN_VERSION=0.2.4 TELEPATHY_LOGGER_MIN_VERSION=0.2.4
POLKIT_MIN_VERSION=0.100 POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11 STARTUP_NOTIFICATION_MIN_VERSION=0.11
@ -82,9 +82,8 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
folks >= $FOLKS_MIN_VERSION folks >= $FOLKS_MIN_VERSION
libmutter >= $MUTTER_MIN_VERSION libmutter >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_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 gdk-x11-3.0 libsoup-2.4
gl
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
@ -118,6 +117,7 @@ CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS 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(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(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0) PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7) PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)

@ -59,8 +59,6 @@ gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
all-local: gschemas.compiled all-local: gschemas.compiled
convertdir = $(datadir)/GConf/gsettings
convert_DATA = gnome-shell-overrides.convert
shadersdir = $(pkgdatadir)/shaders shadersdir = $(pkgdatadir)/shaders
shaders_DATA = \ shaders_DATA = \
@ -71,7 +69,6 @@ EXTRA_DIST = \
gnome-shell.desktop.in.in \ gnome-shell.desktop.in.in \
$(menu_DATA) \ $(menu_DATA) \
$(shaders_DATA) \ $(shaders_DATA) \
$(convert_DATA) \
org.gnome.shell.gschema.xml.in org.gnome.shell.gschema.xml.in
CLEANFILES = \ CLEANFILES = \

@ -1,5 +0,0 @@
[org.gnome.shell.overrides]
attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs
button-layout = /desktop/gnome/shell/windows/button_layout
edge-tiling = /desktop/gnome/shell/windows/edge_tiling
workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary

@ -60,7 +60,6 @@ StScrollBar StBin#trough {
StScrollBar StButton#vhandle StScrollBar StButton#vhandle
{ {
background-image: url("scroll-vhandle.svg"); background-image: url("scroll-vhandle.svg");
background-size: contain;
background-color: #252525; background-color: #252525;
border: 1px solid #080808; border: 1px solid #080808;
border-radius: 8px; border-radius: 8px;
@ -69,7 +68,6 @@ StScrollBar StButton#vhandle
StScrollBar StButton#hhandle StScrollBar StButton#hhandle
{ {
background-image: url("scroll-hhandle.svg"); background-image: url("scroll-hhandle.svg");
background-size: contain;
background-color: #252525; background-color: #252525;
border: 1px solid #080808; border: 1px solid #080808;
border-radius: 8px; border-radius: 8px;
@ -226,20 +224,16 @@ StTooltip StLabel {
.toggle-switch-us { .toggle-switch-us {
background-image: url("toggle-off-us.svg"); background-image: url("toggle-off-us.svg");
background-size: contain;
} }
.toggle-switch-us:checked { .toggle-switch-us:checked {
background-image: url("toggle-on-us.svg"); background-image: url("toggle-on-us.svg");
background-size: contain;
} }
.toggle-switch-intl { .toggle-switch-intl {
background-image: url("toggle-off-intl.svg"); background-image: url("toggle-off-intl.svg");
background-size: contain;
} }
.toggle-switch-intl:checked { .toggle-switch-intl:checked {
background-image: url("toggle-on-intl.svg"); background-image: url("toggle-on-intl.svg");
background-size: contain;
} }
.nm-menu-item-icons { .nm-menu-item-icons {
@ -362,7 +356,6 @@ StTooltip StLabel {
.panel-button:focus { .panel-button:focus {
border-image: url("panel-button-border.svg") 10 10 0 2; border-image: url("panel-button-border.svg") 10 10 0 2;
background-image: url("panel-button-highlight-wide.svg"); background-image: url("panel-button-highlight-wide.svg");
background-size: contain;
color: white; color: white;
text-shadow: black 0px 2px 2px; text-shadow: black 0px 2px 2px;
} }
@ -371,7 +364,6 @@ StTooltip StLabel {
.panel-status-button:checked, .panel-status-button:checked,
.panel-status-button:focus { .panel-status-button:focus {
background-image: url("panel-button-highlight-narrow.svg"); background-image: url("panel-button-highlight-narrow.svg");
background-size: contain;
} }
.panel-button:active > .system-status-icon, .panel-button:active > .system-status-icon,
@ -475,17 +467,16 @@ StTooltip StLabel {
} }
.window-caption { .window-caption {
background: rgba(0,0,0,0.5); background: rgba(0,0,0,0.8);
border-radius: 8px; border: 1px solid rgba(128,128,128,0.40);
border-radius: 10px;
font-size: 9pt; font-size: 9pt;
font-weight: bold; padding: 2px 8px;
padding: 6px 12px; -shell-caption-spacing: 4px;
-shell-caption-spacing: 12px;
} }
.window-close { .window-close {
background-image: url("close-window.svg"); background-image: url("close-window.svg");
background-size: 34px;
height: 34px; height: 34px;
width: 34px; width: 34px;
-shell-close-overlap: 20px; -shell-close-overlap: 20px;
@ -520,7 +511,6 @@ StTooltip StLabel {
.placeholder { .placeholder {
background-image: url("dash-placeholder.svg"); background-image: url("dash-placeholder.svg");
background-size: contain;
height: 24px; height: 24px;
} }
@ -655,17 +645,6 @@ StTooltip StLabel {
font-size: 11pt; 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 */ /* Apps */
.icon-grid { .icon-grid {
@ -707,13 +686,11 @@ StTooltip StLabel {
.app-filter:selected { .app-filter:selected {
color: #ffffff; color: #ffffff;
background-image: url("filter-selected-ltr.svg"); background-image: url("filter-selected-ltr.svg");
background-size: contain;
background-position: 190px 10px; background-position: 190px 10px;
} }
.app-filter:selected:rtl { .app-filter:selected:rtl {
background-image: url("filter-selected-rtl.svg"); background-image: url("filter-selected-rtl.svg");
background-size: contain;
background-position: 10px 10px; background-position: 10px 10px;
} }
@ -740,8 +717,7 @@ StTooltip StLabel {
border-radius: 4px; border-radius: 4px;
padding: 3px; padding: 3px;
border: 1px rgba(0,0,0,0); border: 1px rgba(0,0,0,0);
font-size: 8pt; font-size: 7.5pt;
font-weight: bold;
color: white; color: white;
transition-duration: 100; transition-duration: 100;
text-align: center; text-align: center;
@ -795,7 +771,6 @@ StTooltip StLabel {
.app-well-app.running > .overview-icon { .app-well-app.running > .overview-icon {
text-shadow: black 0px 2px 2px; text-shadow: black 0px 2px 2px;
background-image: url("running-indicator.svg"); background-image: url("running-indicator.svg");
background-size: contain;
} }
.contact:selected, .contact:selected,
@ -1292,8 +1267,7 @@ StTooltip StLabel {
} }
.notification-icon-button > StIcon { .notification-icon-button > StIcon {
icon-size: 16px; icon-size: 36px;
padding: 8px;
} }
.hotplug-transient-box { .hotplug-transient-box {
@ -1457,7 +1431,6 @@ StTooltip StLabel {
.summary-source-button:selected .summary-source { .summary-source-button:selected .summary-source {
background-image: url("panel-button-highlight-narrow.svg"); background-image: url("panel-button-highlight-narrow.svg");
background-size: contain;
border-image: url("source-button-border.svg") 10 10 0 1; border-image: url("source-button-border.svg") 10 10 0 1;
} }
@ -1468,7 +1441,6 @@ StTooltip StLabel {
.summary-source-button:expanded:selected { .summary-source-button:expanded:selected {
background-image: url("panel-button-highlight-wide.svg"); background-image: url("panel-button-highlight-wide.svg");
background-size: contain;
border-image: url("source-button-border.svg") 10 10 0 1; border-image: url("source-button-border.svg") 10 10 0 1;
} }
@ -1582,7 +1554,6 @@ StTooltip StLabel {
width: 52px; width: 52px;
height: 52px; height: 52px;
background-image: url("corner-ripple-ltr.png"); background-image: url("corner-ripple-ltr.png");
background-size: contain;
} }
.ripple-box:rtl { .ripple-box:rtl {
@ -1624,7 +1595,6 @@ StTooltip StLabel {
border: 0px; border: 0px;
background: rgba(255,255,255,0.5); background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-up.svg"); background-image: url("ws-switch-arrow-up.svg");
background-size: contain;
border-radius: 8px; border-radius: 8px;
} }
@ -1633,7 +1603,6 @@ StTooltip StLabel {
border: 0px; border: 0px;
background: rgba(255,255,255,0.5); background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-down.svg"); background-image: url("ws-switch-arrow-down.svg");
background-size: contain;
border-radius: 8px; border-radius: 8px;
} }

@ -18,10 +18,11 @@ DOC_MODULE=shell
# The top-level SGML file. You can change this if you want to. # The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code # Directories containing the source code, relative to $(srcdir).
# gtk-doc will search all .c and .h files beneath these paths # gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros. # for inline comments documenting functions and macros.
DOC_SOURCE_DIR=$(top_srcdir)/src # e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
DOC_SOURCE_DIR=../../../src
# Extra options to pass to gtkdoc-scangobj. Not normally needed. # Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS= SCANGOBJ_OPTIONS=
@ -57,16 +58,7 @@ EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names # Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES= \ IGNORE_HFILES=calendar-server gvc hotplug-sniffer st tray
calendar-server \
gvc \
hotplug-sniffer \
st \
tray \
gactionmuxer.h \
gactionobservable.h \
gactionobserver.h \
shell-recorder-src.h
# Images to copy into HTML directory. # Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
@ -87,7 +79,7 @@ expand_content_files=
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS) GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell.la
# This includes the standard gtk-doc make rules, copied by gtkdocize. # This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make include $(top_srcdir)/gtk-doc.make

@ -18,10 +18,11 @@ DOC_MODULE=st
# The top-level SGML file. You can change this if you want to. # The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code # Directories containing the source code, relative to $(srcdir).
# gtk-doc will search all .c and .h files beneath these paths # gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros. # for inline comments documenting functions and macros.
DOC_SOURCE_DIR=$(top_srcdir)/src/st # e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
DOC_SOURCE_DIR=../../../src/st
# Extra options to pass to gtkdoc-scangobj. Not normally needed. # Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS= SCANGOBJ_OPTIONS=

@ -72,7 +72,6 @@ nobase_dist_js_DATA = \
ui/tweener.js \ ui/tweener.js \
ui/userMenu.js \ ui/userMenu.js \
ui/viewSelector.js \ ui/viewSelector.js \
ui/wanda.js \
ui/windowAttentionHandler.js \ ui/windowAttentionHandler.js \
ui/windowManager.js \ ui/windowManager.js \
ui/workspace.js \ ui/workspace.js \

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

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

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

@ -33,6 +33,7 @@ const St = imports.gi.St;
const GdmGreeter = imports.gi.GdmGreeter; const GdmGreeter = imports.gi.GdmGreeter;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const DBus = imports.dbus;
const Fprint = imports.gdm.fingerprint; const Fprint = imports.gdm.fingerprint;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -140,9 +141,11 @@ function _smoothlyResizeActor(actor, width, height) {
return hold; return hold;
} }
const UserListItem = new Lang.Class({ function UserListItem(user, reason) {
Name: 'UserListItem', this._init(user, reason);
}
UserListItem.prototype = {
_init: function(user) { _init: function(user) {
this.user = user; this.user = user;
this._userChangedId = this.user.connect('changed', this._userChangedId = this.user.connect('changed',
@ -205,8 +208,7 @@ const UserListItem = new Lang.Class({
// We use background-image instead of, say, St.TextureCache // We use background-image instead of, say, St.TextureCache
// so the theme writers can add a rounded frame around the image // so the theme writers can add a rounded frame around the image
// and so theme writers can pick the icon size. // and so theme writers can pick the icon size.
this._iconBin.set_style('background-image: url("' + iconFile + '");' + this._iconBin.set_style('background-image: url("' + iconFile + '");');
'background-size: contain;');
} else { } else {
this._iconBin.hide(); this._iconBin.hide();
} }
@ -272,12 +274,15 @@ const UserListItem = new Lang.Class({
}); });
return hold; return hold;
} }
});
};
Signals.addSignalMethods(UserListItem.prototype); Signals.addSignalMethods(UserListItem.prototype);
const UserList = new Lang.Class({ function UserList() {
Name: 'UserList', this._init.apply(this, arguments);
}
UserList.prototype = {
_init: function() { _init: function() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'}); this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor.set_policy(Gtk.PolicyType.NEVER, this.actor.set_policy(Gtk.PolicyType.NEVER,
@ -533,12 +538,14 @@ const UserList = new Lang.Class({
item.actor.destroy(); item.actor.destroy();
delete this._items[userName]; delete this._items[userName];
} }
}); };
Signals.addSignalMethods(UserList.prototype); Signals.addSignalMethods(UserList.prototype);
const SessionListItem = new Lang.Class({ function SessionListItem(id, name) {
Name: 'SessionListItem', this._init(id, name);
}
SessionListItem.prototype = {
_init: function(id, name) { _init: function(id, name) {
this.id = id; this.id = id;
@ -593,12 +600,14 @@ const SessionListItem = new Lang.Class({
_onClicked: function() { _onClicked: function() {
this.emit('activate'); this.emit('activate');
} }
}); };
Signals.addSignalMethods(SessionListItem.prototype); Signals.addSignalMethods(SessionListItem.prototype);
const SessionList = new Lang.Class({ function SessionList() {
Name: 'SessionList', this._init();
}
SessionList.prototype = {
_init: function() { _init: function() {
this.actor = new St.Bin(); this.actor = new St.Bin();
@ -729,15 +738,24 @@ const SessionList = new Lang.Class({
})); }));
} }
} }
}); };
Signals.addSignalMethods(SessionList.prototype); Signals.addSignalMethods(SessionList.prototype);
const LoginDialog = new Lang.Class({ function LoginDialog() {
Name: 'LoginDialog', if (_loginDialog == null) {
Extends: ModalDialog.ModalDialog, this._init();
_loginDialog = this;
}
return _loginDialog;
}
LoginDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function() { _init: function() {
this.parent({ shellReactive: true, styleClass: 'login-dialog' }); ModalDialog.ModalDialog.prototype._init.call(this, { shellReactive: true,
styleClass: 'login-dialog' });
this.connect('destroy', this.connect('destroy',
Lang.bind(this, this._onDestroy)); Lang.bind(this, this._onDestroy));
this.connect('opened', this.connect('opened',
@ -890,7 +908,7 @@ const LoginDialog = new Lang.Class({
if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY)) if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
return; return;
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, Lang.bind(this, this._fprintManager.GetDefaultDeviceRemote(DBus.CALL_FLAG_START, Lang.bind(this,
function(device, error) { function(device, error) {
if (!error && device) if (!error && device)
this._haveFingerprintReader = true; this._haveFingerprintReader = true;
@ -1381,8 +1399,8 @@ const LoginDialog = new Lang.Class({
}, },
close: function() { close: function() {
this.parent(); ModalDialog.ModalDialog.prototype.close.call(this);
Main.ctrlAltTabManager.removeGroup(this._group); Main.ctrlAltTabManager.removeGroup(this._group);
} }
}); };

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

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

@ -38,7 +38,7 @@ function recursivelyDeleteDir(dir) {
let child = dir.get_child(info.get_name()); let child = dir.get_child(info.get_name());
if (type == Gio.FileType.REGULAR) if (type == Gio.FileType.REGULAR)
deleteGFile(child); deleteGFile(child);
else if (type == Gio.FileType.DIRECTORY) else if (type == Gio.TypeType.DIRECTORY)
recursivelyDeleteDir(child); recursivelyDeleteDir(child);
} }

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

@ -54,9 +54,11 @@ function _getProvidersTable() {
return _providersTable = providers; return _providersTable = providers;
} }
const ModemGsm = new Lang.Class({ function ModemGsm() {
Name: 'ModemGsm', this._init.apply(this, arguments);
}
ModemGsm.prototype = {
_init: function(path) { _init: function(path) {
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path); this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
@ -154,12 +156,14 @@ const ModemGsm = new Lang.Class({
return name3 || name2 || null; return name3 || name2 || null;
} }
}); }
Signals.addSignalMethods(ModemGsm.prototype); Signals.addSignalMethods(ModemGsm.prototype);
const ModemCdma = new Lang.Class({ function ModemCdma() {
Name: 'ModemCdma', this._init.apply(this, arguments);
}
ModemCdma.prototype = {
_init: function(path) { _init: function(path) {
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path); this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
@ -227,5 +231,5 @@ const ModemCdma = new Lang.Class({
return null; return null;
} }
}); };
Signals.addSignalMethods(ModemCdma.prototype); Signals.addSignalMethods(ModemCdma.prototype);

@ -232,53 +232,3 @@ function fixupPCIDescription(desc) {
return out.join(' '); 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;
}

@ -43,9 +43,11 @@ function primaryModifier(mask) {
return primary; return primary;
} }
const AltTabPopup = new Lang.Class({ function AltTabPopup() {
Name: 'AltTabPopup', this._init();
}
AltTabPopup.prototype = {
_init : function() { _init : function() {
this.actor = new Shell.GenericContainer({ name: 'altTabPopup', this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
reactive: true, reactive: true,
@ -538,11 +540,13 @@ const AltTabPopup = new Lang.Class({
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; }) onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
}); });
} }
}); };
const SwitcherList = new Lang.Class({ function SwitcherList(squareItems) {
Name: 'SwitcherList', this._init(squareItems);
}
SwitcherList.prototype = {
_init : function(squareItems) { _init : function(squareItems) {
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' }); this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -847,13 +851,15 @@ const SwitcherList = new Lang.Class({
// Clip the area for scrolling // 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); this._clipBin.set_clip(0, -topPadding, (this.actor.allocation.x2 - this.actor.allocation.x1) - leftPadding - rightPadding, this.actor.height + bottomPadding);
} }
}); };
Signals.addSignalMethods(SwitcherList.prototype); Signals.addSignalMethods(SwitcherList.prototype);
const AppIcon = new Lang.Class({ function AppIcon(app) {
Name: 'AppIcon', this._init(app);
}
AppIcon.prototype = {
_init: function(app) { _init: function(app) {
this.app = app; this.app = app;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app', this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
@ -871,14 +877,17 @@ const AppIcon = new Lang.Class({
this._iconBin.set_size(size, size); this._iconBin.set_size(size, size);
this._iconBin.child = this.icon; this._iconBin.child = this.icon;
} }
}); };
const AppSwitcher = new Lang.Class({ function AppSwitcher() {
Name: 'AppSwitcher', this._init.apply(this, arguments);
Extends: SwitcherList, }
AppSwitcher.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(localApps, otherApps, altTabPopup) { _init : function(localApps, otherApps, altTabPopup) {
this.parent(true); SwitcherList.prototype._init.call(this, true);
// Construct the AppIcons, add to the popup // Construct the AppIcons, add to the popup
let activeWorkspace = global.screen.get_active_workspace(); let activeWorkspace = global.screen.get_active_workspace();
@ -957,7 +966,7 @@ const AppSwitcher = new Lang.Class({
_allocate: function (actor, box, flags) { _allocate: function (actor, box, flags) {
// Allocate the main list items // 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 arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
let arrowWidth = arrowHeight * 2; let arrowWidth = arrowHeight * 2;
@ -1012,7 +1021,7 @@ const AppSwitcher = new Lang.Class({
this._arrows[this._curApp].remove_style_pseudo_class('highlighted'); this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
} }
this.parent(n, justOutline); SwitcherList.prototype.highlight.call(this, n, justOutline);
this._curApp = n; this._curApp = n;
if (this._curApp != -1) { if (this._curApp != -1) {
@ -1036,14 +1045,17 @@ const AppSwitcher = new Lang.Class({
if (appIcon.cachedWindows.length == 1) if (appIcon.cachedWindows.length == 1)
arrow.hide(); arrow.hide();
} }
}); };
const ThumbnailList = new Lang.Class({ function ThumbnailList(windows) {
Name: 'ThumbnailList', this._init(windows);
Extends: SwitcherList, }
ThumbnailList.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(windows) { _init : function(windows) {
this.parent(false); SwitcherList.prototype._init.call(this);
let activeWorkspace = global.screen.get_active_workspace(); let activeWorkspace = global.screen.get_active_workspace();
@ -1121,7 +1133,7 @@ const ThumbnailList = new Lang.Class({
// Make sure we only do this once // Make sure we only do this once
this._thumbnailBins = new Array(); this._thumbnailBins = new Array();
} }
}); };
function _drawArrow(area, side) { function _drawArrow(area, side) {
let themeNode = area.get_theme_node(); let themeNode = area.get_theme_node();

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

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

@ -64,9 +64,11 @@ function ConsoleKitManager() {
return self; return self;
} }
const AutomountManager = new Lang.Class({ function AutomountManager() {
Name: 'AutomountManager', this._init();
}
AutomountManager.prototype = {
_init: function() { _init: function() {
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = []; this._volumeQueue = [];
@ -266,4 +268,4 @@ const AutomountManager = new Lang.Class({
return false; return false;
}); });
} }
}); }

@ -75,9 +75,11 @@ function HotplugSniffer() {
'/org/gnome/Shell/HotplugSniffer'); '/org/gnome/Shell/HotplugSniffer');
} }
const ContentTypeDiscoverer = new Lang.Class({ function ContentTypeDiscoverer(callback) {
Name: 'ContentTypeDiscoverer', this._init(callback);
}
ContentTypeDiscoverer.prototype = {
_init: function(callback) { _init: function(callback) {
this._callback = callback; this._callback = callback;
}, },
@ -134,11 +136,13 @@ const ContentTypeDiscoverer = new Lang.Class({
this._callback(mount, apps, contentTypes); this._callback(mount, apps, contentTypes);
} }
}); }
const AutorunManager = new Lang.Class({ function AutorunManager() {
Name: 'AutorunManager', this._init();
}
AutorunManager.prototype = {
_init: function() { _init: function() {
this._volumeMonitor = Gio.VolumeMonitor.get(); this._volumeMonitor = Gio.VolumeMonitor.get();
@ -255,14 +259,17 @@ const AutorunManager = new Lang.Class({
+ ': ' + e.toString()); + ': ' + e.toString());
} }
}, },
}); }
const AutorunResidentSource = new Lang.Class({ function AutorunResidentSource() {
Name: 'AutorunResidentSource', this._init();
Extends: MessageTray.Source, }
AutorunResidentSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function() { _init: function() {
this.parent(_("Removable Devices")); MessageTray.Source.prototype._init.call(this, _("Removable Devices"));
this._mounts = []; this._mounts = [];
@ -317,14 +324,19 @@ const AutorunResidentSource = new Lang.Class({
icon_type: St.IconType.FULLCOLOR, icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE }); icon_size: this.ICON_SIZE });
} }
}); }
const AutorunResidentNotification = new Lang.Class({ function AutorunResidentNotification(source) {
Name: 'AutorunResidentNotification', this._init(source);
Extends: MessageTray.Notification, }
AutorunResidentNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source) { _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 // set the notification as resident
this.setResident(true); this.setResident(true);
@ -398,11 +410,13 @@ const AutorunResidentNotification = new Lang.Class({
return item; return item;
}, },
}); }
const AutorunTransientDispatcher = new Lang.Class({ function AutorunTransientDispatcher() {
Name: 'AutorunTransientDispatcher', this._init();
}
AutorunTransientDispatcher.prototype = {
_init: function() { _init: function() {
this._sources = []; this._sources = [];
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
@ -493,14 +507,17 @@ const AutorunTransientDispatcher = new Lang.Class({
// destroy the notification source // destroy the notification source
source.destroy(); source.destroy();
} }
}); }
const AutorunTransientSource = new Lang.Class({ function AutorunTransientSource(mount, apps) {
Name: 'AutorunTransientSource', this._init(mount, apps);
Extends: MessageTray.Source, }
AutorunTransientSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(mount, apps) { _init: function(mount, apps) {
this.parent(mount.get_name()); MessageTray.Source.prototype._init.call(this, mount.get_name());
this.mount = mount; this.mount = mount;
this.apps = apps; this.apps = apps;
@ -517,14 +534,19 @@ const AutorunTransientSource = new Lang.Class({
return new St.Icon({ gicon: this.mount.get_icon(), return new St.Icon({ gicon: this.mount.get_icon(),
icon_size: this.ICON_SIZE }); icon_size: this.ICON_SIZE });
} }
}); }
const AutorunTransientNotification = new Lang.Class({ function AutorunTransientNotification(source) {
Name: 'AutorunTransientNotification', this._init(source);
Extends: MessageTray.Notification, }
AutorunTransientNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source) { _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', this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
vertical: true }); vertical: true });
@ -557,7 +579,7 @@ const AutorunTransientNotification = new Lang.Class({
let label = new St.Bin({ y_align: St.Align.MIDDLE, let label = new St.Bin({ y_align: St.Align.MIDDLE,
child: new St.Label child: new St.Label
({ text: _("Open with %s").format(app.get_name()) }) ({ text: _("Open with %s").format(app.get_display_name()) })
}); });
box.add(label); box.add(label);
@ -599,5 +621,5 @@ const AutorunTransientNotification = new Lang.Class({
return button; return button;
} }
}); }

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

@ -155,24 +155,28 @@ function _getEventDayAbbreviation(dayNumber) {
// Abstraction for an appointment/event in a calendar // Abstraction for an appointment/event in a calendar
const CalendarEvent = new Lang.Class({ function CalendarEvent(date, end, summary, allDay) {
Name: 'CalendarEvent', this._init(date, end, summary, allDay);
}
CalendarEvent.prototype = {
_init: function(date, end, summary, allDay) { _init: function(date, end, summary, allDay) {
this.date = date; this.date = date;
this.end = end; this.end = end;
this.summary = summary; this.summary = summary;
this.allDay = allDay; this.allDay = allDay;
} }
}); };
// Interface for appointments/events - e.g. the contents of a calendar // Interface for appointments/events - e.g. the contents of a calendar
// //
// First, an implementation with no events // First, an implementation with no events
const EmptyEventSource = new Lang.Class({ function EmptyEventSource() {
Name: 'EmptyEventSource', this._init();
}
EmptyEventSource.prototype = {
_init: function() { _init: function() {
}, },
@ -187,7 +191,7 @@ const EmptyEventSource = new Lang.Class({
hasEvents: function(day) { hasEvents: function(day) {
return false; return false;
} }
}); };
Signals.addSignalMethods(EmptyEventSource.prototype); Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer"> const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
@ -215,6 +219,11 @@ function CalendarServer() {
return self; return self;
} }
// an implementation that reads data from a session bus service
function DBusEventSource() {
this._init();
}
function _datesEqual(a, b) { function _datesEqual(a, b) {
if (a < b) if (a < b)
return false; return false;
@ -233,10 +242,8 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
return true; return true;
} }
// an implementation that reads data from a session bus service
const DBusEventSource = new Lang.Class({
Name: 'DBusEventSource',
DBusEventSource.prototype = {
_init: function() { _init: function() {
this._resetCache(); this._resetCache();
@ -337,15 +344,17 @@ const DBusEventSource = new Lang.Class({
return true; return true;
} }
}); };
Signals.addSignalMethods(DBusEventSource.prototype); Signals.addSignalMethods(DBusEventSource.prototype);
// Calendar: // Calendar:
// @eventSource: is an object implementing the EventSource API, e.g. the // @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal. // requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
const Calendar = new Lang.Class({ function Calendar(eventSource) {
Name: 'Calendar', this._init(eventSource);
}
Calendar.prototype = {
_init: function(eventSource) { _init: function(eventSource) {
if (eventSource) { if (eventSource) {
this._eventSource = eventSource; this._eventSource = eventSource;
@ -611,13 +620,15 @@ const Calendar = new Lang.Class({
if (this._eventSource) if (this._eventSource)
this._eventSource.requestRange(beginDate, iter, forceReload); this._eventSource.requestRange(beginDate, iter, forceReload);
} }
}); };
Signals.addSignalMethods(Calendar.prototype); Signals.addSignalMethods(Calendar.prototype);
const EventsList = new Lang.Class({ function EventsList(eventSource) {
Name: 'EventsList', this._init(eventSource);
}
EventsList.prototype = {
_init: function(eventSource) { _init: function(eventSource) {
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'}); this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
this._date = new Date(); this._date = new Date();
@ -748,4 +759,4 @@ const EventsList = new Lang.Class({
this._showOtherDay(this._date); this._showOtherDay(this._date);
} }
} }
}); };

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

@ -22,9 +22,11 @@ const SortGroup = {
BOTTOM: 2 BOTTOM: 2
}; };
const CtrlAltTabManager = new Lang.Class({ function CtrlAltTabManager() {
Name: 'CtrlAltTabManager', this._init();
}
CtrlAltTabManager.prototype = {
_init: function() { _init: function() {
this._items = []; this._items = [];
this._focusManager = St.FocusManager.get_for_stage(global.stage); this._focusManager = St.FocusManager.get_for_stage(global.stage);
@ -132,15 +134,17 @@ const CtrlAltTabManager = new Lang.Class({
})); }));
} }
} }
}); };
function mod(a, b) { function mod(a, b) {
return (a + b) % b; return (a + b) % b;
} }
const CtrlAltTabPopup = new Lang.Class({ function CtrlAltTabPopup() {
Name: 'CtrlAltTabPopup', this._init();
}
CtrlAltTabPopup.prototype = {
_init : function() { _init : function() {
this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup', this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
reactive: true }); reactive: true });
@ -299,14 +303,17 @@ const CtrlAltTabPopup = new Lang.Class({
this._selection = num; this._selection = num;
this._switcher.highlight(num); this._switcher.highlight(num);
} }
}); };
const CtrlAltTabSwitcher = new Lang.Class({ function CtrlAltTabSwitcher(items) {
Name: 'CtrlAltTabSwitcher', this._init(items);
Extends: AltTab.SwitcherList, }
CtrlAltTabSwitcher.prototype = {
__proto__ : AltTab.SwitcherList.prototype,
_init : function(items) { _init : function(items) {
this.parent(true); AltTab.SwitcherList.prototype._init.call(this, true);
for (let i = 0; i < items.length; i++) for (let i = 0; i < items.length; i++)
this._addIcon(items[i]); this._addIcon(items[i]);
@ -329,4 +336,4 @@ const CtrlAltTabSwitcher = new Lang.Class({
this.addItem(box, text); this.addItem(box, text);
} }
}); };

@ -6,7 +6,6 @@ const Lang = imports.lang;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const Mainloop = imports.mainloop;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites; const AppFavorites = imports.ui.appFavorites;
@ -17,15 +16,14 @@ const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace; const Workspace = imports.ui.workspace;
const DASH_ANIMATION_TIME = 0.2; 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 // A container like StBin, but taking the child's scale into account
// when requesting a size // when requesting a size
const DashItemContainer = new Lang.Class({ function DashItemContainer() {
Name: 'DashItemContainer', this._init();
}
DashItemContainer.prototype = {
_init: function() { _init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' }); this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
this.actor.connect('get-preferred-width', this.actor.connect('get-preferred-width',
@ -36,8 +34,6 @@ const DashItemContainer = new Lang.Class({
Lang.bind(this, this._allocate)); Lang.bind(this, this._allocate));
this.actor._delegate = this; this.actor._delegate = this;
this._label = null;
this.child = null; this.child = null;
this._childScale = 1; this._childScale = 1;
this._childOpacity = 255; this._childOpacity = 255;
@ -90,60 +86,6 @@ const DashItemContainer = new Lang.Class({
alloc.natural_size = natWidth * this.child.scale_y; 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) { setChild: function(actor) {
if (this.child == actor) if (this.child == actor)
return; return;
@ -215,14 +157,17 @@ const DashItemContainer = new Lang.Class({
get childOpacity() { get childOpacity() {
return this._childOpacity; return this._childOpacity;
} }
}); };
const RemoveFavoriteIcon = new Lang.Class({ function RemoveFavoriteIcon() {
Name: 'RemoveFavoriteIcon', this._init();
Extends: DashItemContainer, }
RemoveFavoriteIcon.prototype = {
__proto__: DashItemContainer.prototype,
_init: function() { _init: function() {
this.parent(); DashItemContainer.prototype._init.call(this);
this._iconBin = new St.Bin({ style_class: 'remove-favorite' }); this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
this._iconActor = null; this._iconActor = null;
@ -274,21 +219,28 @@ const RemoveFavoriteIcon = new Lang.Class({
return true; return true;
} }
}); };
const DragPlaceholderItem = new Lang.Class({
Name: 'DragPlaceholderItem', function DragPlaceholderItem() {
Extends: DashItemContainer, this._init();
}
DragPlaceholderItem.prototype = {
__proto__: DashItemContainer.prototype,
_init: function() { _init: function() {
this.parent(); DashItemContainer.prototype._init.call(this);
this.setChild(new St.Bin({ style_class: 'placeholder' })); this.setChild(new St.Bin({ style_class: 'placeholder' }));
} }
}); };
const Dash = new Lang.Class({
Name: 'Dash',
function Dash() {
this._init();
}
Dash.prototype = {
_init : function() { _init : function() {
this._maxHeight = -1; this._maxHeight = -1;
this.iconSize = 64; this.iconSize = 64;
@ -298,9 +250,6 @@ const Dash = new Lang.Class({
this._dragPlaceholderPos = -1; this._dragPlaceholderPos = -1;
this._animatingPlaceholdersCount = 0; this._animatingPlaceholdersCount = 0;
this._favRemoveTarget = null; this._favRemoveTarget = null;
this._showLabelTimeoutId = 0;
this._resetHoverTimeoutId = 0;
this._labelShowing = false;
this._box = new St.BoxLayout({ name: 'dash', this._box = new St.BoxLayout({ name: 'dash',
vertical: true, vertical: true,
@ -434,48 +383,14 @@ const Dash = new Lang.Class({
Lang.bind(this, function() { Lang.bind(this, function() {
display.actor.opacity = 255; display.actor.opacity = 255;
})); }));
display.actor.set_tooltip_text(app.get_name());
let item = new DashItemContainer(); let item = new DashItemContainer();
item.setChild(display.actor); item.setChild(display.actor);
item.setLabelText(app.get_name());
display.icon.setIconSize(this.iconSize); display.icon.setIconSize(this.iconSize);
display.actor.connect('notify::hover',
Lang.bind(this, function() {
this._onHover(item, display)
}));
return item;
},
_onHover: function (item, display) { return item;
if (display.actor.get_hover() && !display.isMenuUp) {
if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
Lang.bind(this, function() {
this._labelShowing = true;
item.showLabel();
return false;
}));
if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0;
}
}
} else {
if (this._showLabelTimeoutId > 0)
Mainloop.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0;
item.hideLabel();
if (this._labelShowing) {
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
Lang.bind(this, function() {
this._labelShowing = false;
return false;
}));
}
}
}, },
_adjustIconSize: function() { _adjustIconSize: function() {
@ -847,6 +762,6 @@ const Dash = new Lang.Class({
return true; return true;
} }
}); };
Signals.addSignalMethods(Dash.prototype); Signals.addSignalMethods(Dash.prototype);

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

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

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

@ -142,9 +142,11 @@ function findAppFromInhibitor(inhibitor) {
return app; return app;
} }
const ListItem = new Lang.Class({ function ListItem(app, reason) {
Name: 'ListItem', this._init(app, reason);
}
ListItem.prototype = {
_init: function(app, reason) { _init: function(app, reason) {
this._app = app; this._app = app;
this._reason = reason; this._reason = reason;
@ -190,7 +192,7 @@ const ListItem = new Lang.Class({
this.emit('activate'); this.emit('activate');
this._app.activate(); this._app.activate();
} }
}); };
Signals.addSignalMethods(ListItem.prototype); Signals.addSignalMethods(ListItem.prototype);
// The logout timer only shows updates every 10 seconds // The logout timer only shows updates every 10 seconds
@ -228,19 +230,27 @@ function _setLabelText(label, text) {
} }
} }
function EndSessionDialog() {
if (_endSessionDialog == null) {
this._init();
_endSessionDialog = this;
}
return _endSessionDialog;
}
function init() { function init() {
// This always returns the same singleton object // This always returns the same singleton object
// By instantiating it initially, we register the // By instantiating it initially, we register the
// bus object, etc. // bus object, etc.
_endSessionDialog = new EndSessionDialog(); let dialog = new EndSessionDialog();
} }
const EndSessionDialog = new Lang.Class({ EndSessionDialog.prototype = {
Name: 'EndSessionDialog', __proto__: ModalDialog.ModalDialog.prototype,
Extends: ModalDialog.ModalDialog,
_init: function() { _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()); this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
@ -333,8 +343,7 @@ const EndSessionDialog = new Lang.Class({
this._iconBin.child = null; this._iconBin.child = null;
if (iconFile) { if (iconFile) {
this._iconBin.show(); this._iconBin.show();
this._iconBin.set_style('background-image: url("' + iconFile + '");' + this._iconBin.set_style('background-image: url("' + iconFile + '");');
'background-size: contain;');
} else { } else {
this._iconBin.hide(); this._iconBin.hide();
} }
@ -432,7 +441,7 @@ const EndSessionDialog = new Lang.Class({
}, },
close: function() { close: function() {
this.parent(); ModalDialog.ModalDialog.prototype.close.call(this);
this._dbusImpl.emit_signal('Closed', null); this._dbusImpl.emit_signal('Closed', null);
}, },
@ -534,4 +543,4 @@ const EndSessionDialog = new Lang.Class({
this.disconnect(signalId); this.disconnect(signalId);
})); }));
} }
}); };

@ -202,7 +202,7 @@ function gotExtensionZipFile(session, message, uuid) {
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions); global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
} }
loadExtension(dir, ExtensionType.PER_USER, true); loadExtension(dir, true, ExtensionType.PER_USER);
}); });
} }
@ -502,12 +502,15 @@ function loadExtensions() {
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER); _loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
} }
const InstallExtensionDialog = new Lang.Class({ function InstallExtensionDialog(uuid, version_tag, name) {
Name: 'InstallExtensionDialog', this._init(uuid, version_tag, name);
Extends: ModalDialog.ModalDialog, }
InstallExtensionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(uuid, version_tag, name) { _init: function(uuid, version_tag, name) {
this.parent({ styleClass: 'extension-dialog' }); ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'extension-dialog' });
this._uuid = uuid; this._uuid = uuid;
this._version_tag = version_tag; this._version_tag = version_tag;
@ -567,4 +570,4 @@ const InstallExtensionDialog = new Lang.Class({
this.close(global.get_current_time()); this.close(global.get_current_time());
} }
}); };

@ -10,9 +10,11 @@ const Params = imports.misc.params;
const ICON_SIZE = 48; const ICON_SIZE = 48;
const BaseIcon = new Lang.Class({ function BaseIcon(label, createIcon) {
Name: 'BaseIcon', this._init(label, createIcon);
}
BaseIcon.prototype = {
_init : function(label, params) { _init : function(label, params) {
params = Params.parse(params, { createIcon: null, params = Params.parse(params, { createIcon: null,
setSizeManually: false, setSizeManually: false,
@ -35,8 +37,7 @@ const BaseIcon = new Lang.Class({
this.actor.set_child(box); this.actor.set_child(box);
this.iconSize = ICON_SIZE; this.iconSize = ICON_SIZE;
this._iconBin = new St.Bin({ x_align: St.Align.MIDDLE, this._iconBin = new St.Bin();
y_align: St.Align.MIDDLE });
box.add_actor(this._iconBin); box.add_actor(this._iconBin);
@ -126,12 +127,12 @@ const BaseIcon = new Lang.Class({
this.iconSize = size; this.iconSize = size;
this.icon = this.createIcon(this.iconSize); this.icon = this.createIcon(this.iconSize);
this._iconBin.child = this.icon;
// The icon returned by createIcon() might actually be smaller than // The icon returned by createIcon() might actually be smaller than
// the requested icon size (for instance StTextureCache does this // the requested icon size (for instance StTextureCache does this
// for fallback icons), so set the size explicitly. // 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() { _onStyleChanged: function() {
@ -146,18 +147,15 @@ const BaseIcon = new Lang.Class({
size = found ? len : ICON_SIZE; size = found ? len : ICON_SIZE;
} }
// don't create icons unnecessarily
if (size == this.iconSize &&
this._iconBin.child)
return;
this._createIconTexture(size); this._createIconTexture(size);
} }
}); };
const IconGrid = new Lang.Class({ function IconGrid(params) {
Name: 'IconGrid', this._init(params);
}
IconGrid.prototype = {
_init: function(params) { _init: function(params) {
params = Params.parse(params, { rowLimit: null, params = Params.parse(params, { rowLimit: null,
columnLimit: null, columnLimit: null,
@ -326,4 +324,4 @@ const IconGrid = new Lang.Class({
visibleItemsCount: function() { visibleItemsCount: function() {
return this._grid.get_children().length - this._grid.get_n_skip_paint(); return this._grid.get_children().length - this._grid.get_n_skip_paint();
} }
}); };

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

@ -17,9 +17,11 @@ const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const STARTUP_ANIMATION_TIME = 0.2; const STARTUP_ANIMATION_TIME = 0.2;
const KEYBOARD_ANIMATION_TIME = 0.5; const KEYBOARD_ANIMATION_TIME = 0.5;
const LayoutManager = new Lang.Class({ function LayoutManager() {
Name: 'LayoutManager', this._init.apply(this, arguments);
}
LayoutManager.prototype = {
_init: function () { _init: function () {
this._rtl = (St.Widget.get_default_direction() == St.TextDirection.RTL); this._rtl = (St.Widget.get_default_direction() == St.TextDirection.RTL);
this.monitors = []; this.monitors = [];
@ -372,7 +374,7 @@ const LayoutManager = new Lang.Class({
findMonitorForActor: function(actor) { findMonitorForActor: function(actor) {
return this._chrome.findMonitorForActor(actor); return this._chrome.findMonitorForActor(actor);
} }
}); };
Signals.addSignalMethods(LayoutManager.prototype); Signals.addSignalMethods(LayoutManager.prototype);
@ -380,9 +382,11 @@ Signals.addSignalMethods(LayoutManager.prototype);
// //
// This class manages a "hot corner" that can toggle switching to // This class manages a "hot corner" that can toggle switching to
// overview. // overview.
const HotCorner = new Lang.Class({ function HotCorner() {
Name: 'HotCorner', this._init();
}
HotCorner.prototype = {
_init : function() { _init : function() {
// We use this flag to mark the case where the user has entered the // 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 // 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)); Lang.bind(this, this._onCornerLeft));
// Cache the three ripples instead of dynamically creating and destroying them. // 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._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false }); this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false }); this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
Main.uiGroup.add_actor(this._ripple1); Main.uiGroup.add_actor(this._ripple1);
Main.uiGroup.add_actor(this._ripple2); Main.uiGroup.add_actor(this._ripple2);
@ -544,7 +548,7 @@ const HotCorner = new Lang.Class({
return true; return true;
return false; return false;
} }
}); };
// This manages the shell "chrome"; the UI that's visible in the // This manages the shell "chrome"; the UI that's visible in the
@ -557,9 +561,11 @@ const defaultParams = {
affectsInputRegion: true affectsInputRegion: true
}; };
const Chrome = new Lang.Class({ function Chrome() {
Name: 'Chrome', this._init.apply(this, arguments);
}
Chrome.prototype = {
_init: function(layoutManager) { _init: function(layoutManager) {
this._layoutManager = layoutManager; this._layoutManager = layoutManager;
@ -975,4 +981,4 @@ const Chrome = new Lang.Class({
return false; return false;
} }
}); };

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

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

@ -55,9 +55,11 @@ function _getAutoCompleteGlobalKeywords() {
return keywords.concat(windowProperties).concat(headerProperties); return keywords.concat(windowProperties).concat(headerProperties);
} }
const AutoComplete = new Lang.Class({ function AutoComplete(entry) {
Name: 'AutoComplete', this._init(entry);
}
AutoComplete.prototype = {
_init: function(entry) { _init: function(entry) {
this._entry = entry; this._entry = entry;
this._entry.connect('key-press-event', Lang.bind(this, this._entryKeyPressEvent)); this._entry.connect('key-press-event', Lang.bind(this, this._entryKeyPressEvent));
@ -116,13 +118,15 @@ const AutoComplete = new Lang.Class({
this._entry.clutter_text.insert_text(additionalCompletionText, cursorPos); this._entry.clutter_text.insert_text(additionalCompletionText, cursorPos);
} }
}); };
Signals.addSignalMethods(AutoComplete.prototype); Signals.addSignalMethods(AutoComplete.prototype);
const Notebook = new Lang.Class({ function Notebook() {
Name: 'Notebook', this._init();
}
Notebook.prototype = {
_init: function() { _init: function() {
this.actor = new St.BoxLayout({ vertical: true }); this.actor = new St.BoxLayout({ vertical: true });
@ -246,7 +250,7 @@ const Notebook = new Lang.Class({
this.selectIndex(prevIndex); this.selectIndex(prevIndex);
} }
}); };
Signals.addSignalMethods(Notebook.prototype); Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) { function objectToString(o) {
@ -258,9 +262,12 @@ function objectToString(o) {
} }
} }
const ObjLink = new Lang.Class({ function ObjLink(o, title) {
Name: 'ObjLink', this._init(o, title);
Extends: Link.Link, }
ObjLink.prototype = {
__proto__: Link.Link,
_init: function(o, title) { _init: function(o, title) {
let text; let text;
@ -270,8 +277,7 @@ const ObjLink = new Lang.Class({
text = objectToString(o); text = objectToString(o);
text = GLib.markup_escape_text(text, -1); text = GLib.markup_escape_text(text, -1);
this._obj = o; this._obj = o;
Link.Link.prototype._init.call(this, { label: text });
this.parent({ label: text });
this.actor.get_child().single_line_mode = true; this.actor.get_child().single_line_mode = true;
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this.actor.connect('clicked', Lang.bind(this, this._onClicked));
}, },
@ -279,11 +285,13 @@ const ObjLink = new Lang.Class({
_onClicked: function (link) { _onClicked: function (link) {
Main.lookingGlass.inspectObject(this._obj, this.actor); Main.lookingGlass.inspectObject(this._obj, this.actor);
} }
}); };
const Result = new Lang.Class({ function Result(command, o, index) {
Name: 'Result', this._init(command, o, index);
}
Result.prototype = {
_init : function(command, o, index) { _init : function(command, o, index) {
this.index = index; this.index = index;
this.o = o; this.o = o;
@ -305,11 +313,13 @@ const Result = new Lang.Class({
padBin.add_actor(line); padBin.add_actor(line);
this.actor.add(padBin); this.actor.add(padBin);
} }
}); };
const WindowList = new Lang.Class({ function WindowList() {
Name: 'WindowList', this._init();
}
WindowList.prototype = {
_init : function () { _init : function () {
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' }); this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
@ -350,12 +360,14 @@ const WindowList = new Lang.Class({
} }
} }
} }
}); };
Signals.addSignalMethods(WindowList.prototype); Signals.addSignalMethods(WindowList.prototype);
const ObjInspector = new Lang.Class({ function ObjInspector() {
Name: 'ObjInspector', this._init();
}
ObjInspector.prototype = {
_init : function () { _init : function () {
this._obj = null; this._obj = null;
this._previousObj = null; this._previousObj = null;
@ -455,7 +467,7 @@ const ObjInspector = new Lang.Class({
_onBack: function() { _onBack: function() {
this.selectObject(this._previousObj, true); this.selectObject(this._previousObj, true);
} }
}); };
function addBorderPaintHook(actor) { function addBorderPaintHook(actor) {
let signalId = actor.connect_after('paint', let signalId = actor.connect_after('paint',
@ -481,9 +493,11 @@ function addBorderPaintHook(actor) {
return signalId; return signalId;
} }
const Inspector = new Lang.Class({ function Inspector() {
Name: 'Inspector', this._init();
}
Inspector.prototype = {
_init: function() { _init: function() {
let container = new Shell.GenericContainer({ width: 0, let container = new Shell.GenericContainer({ width: 0,
height: 0 }); height: 0 });
@ -622,13 +636,15 @@ const Inspector = new Lang.Class({
this._borderPaintId = addBorderPaintHook(this._target); this._borderPaintId = addBorderPaintHook(this._target);
} }
} }
}); };
Signals.addSignalMethods(Inspector.prototype); Signals.addSignalMethods(Inspector.prototype);
const ErrorLog = new Lang.Class({ function ErrorLog() {
Name: 'ErrorLog', this._init();
}
ErrorLog.prototype = {
_init: function() { _init: function() {
this.actor = new St.BoxLayout(); this.actor = new St.BoxLayout();
this.text = new St.Label(); this.text = new St.Label();
@ -663,11 +679,13 @@ const ErrorLog = new Lang.Class({
} }
this.text.text = text; this.text.text = text;
} }
}); };
const Memory = new Lang.Class({ function Memory() {
Name: 'Memory', this._init();
}
Memory.prototype = {
_init: function() { _init: function() {
this.actor = new St.BoxLayout({ vertical: true }); this.actor = new St.BoxLayout({ vertical: true });
this._glibc_uordblks = new St.Label(); this._glibc_uordblks = new St.Label();
@ -712,11 +730,13 @@ const Memory = new Lang.Class({
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure; this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago; this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
} }
}); };
const Extensions = new Lang.Class({ function Extensions() {
Name: 'Extensions', this._init();
}
Extensions.prototype = {
_init: function() { _init: function() {
this.actor = new St.BoxLayout({ vertical: true, this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' }); name: 'lookingGlassExtensions' });
@ -846,11 +866,13 @@ const Extensions = new Lang.Class({
return box; return box;
} }
}); };
const LookingGlass = new Lang.Class({ function LookingGlass() {
Name: 'LookingGlass', this._init();
}
LookingGlass.prototype = {
_init : function() { _init : function() {
this._borderPaintTarget = null; this._borderPaintTarget = null;
this._borderPaintId = 0; this._borderPaintId = 0;
@ -867,8 +889,7 @@ const LookingGlass = new Lang.Class({
this.actor = new St.BoxLayout({ name: 'LookingGlassDialog', this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
style_class: 'lg-dialog', style_class: 'lg-dialog',
vertical: true, vertical: true,
visible: false, visible: false });
reactive: true });
this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent)); this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent));
this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
@ -1207,5 +1228,5 @@ const LookingGlass = new Lang.Class({
}) })
}); });
} }
}); };
Signals.addSignalMethods(LookingGlass.prototype); Signals.addSignalMethods(LookingGlass.prototype);

@ -36,15 +36,17 @@ const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
let magDBusService = null; let magDBusService = null;
const Magnifier = new Lang.Class({ function Magnifier() {
Name: 'Magnifier', this._init();
}
Magnifier.prototype = {
_init: function() { _init: function() {
// Magnifier is a manager of ZoomRegions. // Magnifier is a manager of ZoomRegions.
this._zoomRegions = []; this._zoomRegions = [];
// Create small clutter tree for the magnified mouse. // 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(); this._mouseSprite = new Clutter.Texture();
xfixesCursor.update_texture_image(this._mouseSprite); xfixesCursor.update_texture_image(this._mouseSprite);
this._cursorRoot = new Clutter.Group(); this._cursorRoot = new Clutter.Group();
@ -541,12 +543,14 @@ const Magnifier = new Lang.Class({
); );
} }
} }
}); };
Signals.addSignalMethods(Magnifier.prototype); Signals.addSignalMethods(Magnifier.prototype);
const ZoomRegion = new Lang.Class({ function ZoomRegion(magnifier, mouseSourceActor) {
Name: 'ZoomRegion', this._init(magnifier, mouseSourceActor);
}
ZoomRegion.prototype = {
_init: function(magnifier, mouseSourceActor) { _init: function(magnifier, mouseSourceActor) {
this._magnifier = magnifier; this._magnifier = magnifier;
@ -1146,11 +1150,13 @@ const ZoomRegion = new Lang.Class({
yMagMouse - groupHeight / 2); yMagMouse - groupHeight / 2);
} }
} }
}); };
const Crosshairs = new Lang.Class({ function Crosshairs() {
Name: 'Crosshairs', this._init();
}
Crosshairs.prototype = {
_init: function() { _init: function() {
// Set the group containing the crosshairs to three times the desktop // Set the group containing the crosshairs to three times the desktop
@ -1406,4 +1412,4 @@ const Crosshairs = new Lang.Class({
this._vertTopHair.set_position((groupWidth - thickness) / 2, top); this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom); this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
} }
}); };

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Lang = imports.lang; const GLib = imports.gi.GLib;
const Main = imports.ui.main; const Main = imports.ui.main;
const MAG_SERVICE_NAME = 'org.gnome.Magnifier'; const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
@ -96,9 +96,11 @@ const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc. // '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
let _zoomRegionInstanceCount = 0; let _zoomRegionInstanceCount = 0;
const ShellMagnifier = new Lang.Class({ function ShellMagnifier() {
Name: 'ShellMagnifier', this._init();
}
ShellMagnifier.prototype = {
_init: function() { _init: function() {
this._zoomers = {}; this._zoomers = {};
@ -324,7 +326,7 @@ const ShellMagnifier = new Lang.Class({
// Drop the leading '#'. // Drop the leading '#'.
return parseInt(colorString.slice(1), 16); return parseInt(colorString.slice(1), 16);
} }
}); };
/** /**
* ShellMagnifierZoomRegion: * ShellMagnifierZoomRegion:
@ -332,9 +334,11 @@ const ShellMagnifier = new Lang.Class({
* @zoomerObjectPath: String that is the path to a DBus ZoomRegion. * @zoomerObjectPath: String that is the path to a DBus ZoomRegion.
* @zoomRegion: The actual zoom region associated with the object path. * @zoomRegion: The actual zoom region associated with the object path.
*/ */
const ShellMagnifierZoomRegion = new Lang.Class({ function ShellMagnifierZoomRegion(zoomerObjectPath, zoomRegion) {
Name: 'ShellMagnifierZoomRegion', this._init(zoomerObjectPath, zoomRegion);
}
ShellMagnifierZoomRegion.prototype = {
_init: function(zoomerObjectPath, zoomRegion) { _init: function(zoomerObjectPath, zoomRegion) {
this._zoomRegion = zoomRegion; this._zoomRegion = zoomRegion;
@ -419,4 +423,4 @@ const ShellMagnifierZoomRegion = new Lang.Class({
destroy: function() { destroy: function() {
this._dbusImpl.unexport(); this._dbusImpl.unexport();
} }
}); };

@ -132,11 +132,15 @@ function _initUserSession() {
ExtensionSystem.init(); ExtensionSystem.init();
ExtensionSystem.loadExtensions(); 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(); 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(); overview.toggle();
}); });
@ -332,7 +336,6 @@ function _windowRemoved(workspace, window) {
workspace._lastRemovedWindow = null; workspace._lastRemovedWindow = null;
_queueCheckWorkspaces(); _queueCheckWorkspaces();
} }
return false;
}); });
} }

@ -83,9 +83,11 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1); return GLib.markup_escape_text(text, -1);
} }
const URLHighlighter = new Lang.Class({ function URLHighlighter(text, lineWrap, allowMarkup) {
Name: 'URLHighlighter', this._init(text, lineWrap, allowMarkup);
}
URLHighlighter.prototype = {
_init: function(text, lineWrap, allowMarkup) { _init: function(text, lineWrap, allowMarkup) {
if (!text) if (!text)
text = ''; text = '';
@ -209,11 +211,13 @@ const URLHighlighter = new Lang.Class({
} }
return -1; return -1;
} }
}); };
const FocusGrabber = new Lang.Class({ function FocusGrabber() {
Name: 'FocusGrabber', this._init();
}
FocusGrabber.prototype = {
_init: function() { _init: function() {
this.actor = null; this.actor = null;
@ -347,7 +351,7 @@ const FocusGrabber = new Lang.Class({
this._togglingFocusGrabMode = false; this._togglingFocusGrabMode = false;
} }
} }
}); }
Signals.addSignalMethods(FocusGrabber.prototype); Signals.addSignalMethods(FocusGrabber.prototype);
// Notification: // Notification:
@ -404,9 +408,11 @@ Signals.addSignalMethods(FocusGrabber.prototype);
// the content and the action area of the notification will be cleared. // the content and the action area of the notification will be cleared.
// The content area is also always cleared if 'customContent' is false // 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. // because it might contain the @banner that didn't fit in the banner mode.
const Notification = new Lang.Class({ function Notification(source, title, banner, params) {
Name: 'Notification', this._init(source, title, banner, params);
}
Notification.prototype = {
IMAGE_SIZE: 125, IMAGE_SIZE: 125,
_init: function(source, title, banner, params) { _init: function(source, title, banner, params) {
@ -947,12 +953,14 @@ const Notification = new Lang.Class({
this.actor.destroy(); this.actor.destroy();
this.actor._delegate = null; this.actor._delegate = null;
} }
}); };
Signals.addSignalMethods(Notification.prototype); Signals.addSignalMethods(Notification.prototype);
const Source = new Lang.Class({ function Source(title) {
Name: 'MessageTraySource', this._init(title);
}
Source.prototype = {
ICON_SIZE: 24, ICON_SIZE: 24,
_init: function(title) { _init: function(title) {
@ -1134,12 +1142,14 @@ const Source = new Lang.Class({
_lastNotificationRemoved: function() { _lastNotificationRemoved: function() {
this.destroy(); this.destroy();
} }
}); };
Signals.addSignalMethods(Source.prototype); Signals.addSignalMethods(Source.prototype);
const SummaryItem = new Lang.Class({ function SummaryItem(source) {
Name: 'SummaryItem', this._init(source);
}
SummaryItem.prototype = {
_init: function(source) { _init: function(source) {
this.source = source; this.source = source;
this.source.connect('notification-added', Lang.bind(this, this._notificationAddedToSource)); this.source.connect('notification-added', Lang.bind(this, this._notificationAddedToSource));
@ -1330,12 +1340,14 @@ const SummaryItem = new Lang.Class({
if (this.notificationStack.get_children().length > 0) if (this.notificationStack.get_children().length > 0)
this.notificationStack.get_children()[0]._delegate.setIconVisible(true); this.notificationStack.get_children()[0]._delegate.setIconVisible(true);
} }
}); };
Signals.addSignalMethods(SummaryItem.prototype); Signals.addSignalMethods(SummaryItem.prototype);
const MessageTray = new Lang.Class({ function MessageTray() {
Name: 'MessageTray', this._init();
}
MessageTray.prototype = {
_init: function() { _init: function() {
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) { this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
this._onStatusChanged(proxy.status); this._onStatusChanged(proxy.status);
@ -1430,16 +1442,8 @@ const MessageTray = new Lang.Class({
this._notificationRemoved = false; this._notificationRemoved = false;
this._reNotifyAfterHideNotification = null; this._reNotifyAfterHideNotification = null;
this._corner = new Clutter.Rectangle({ width: 1,
height: 1,
opacity: 0,
reactive: true });
this._corner.connect('enter-event', Lang.bind(this, this._onCornerEnter));
Main.layoutManager.trayBox.add_actor(this._corner);
Main.layoutManager.trackChrome(this._corner);
Main.layoutManager.trayBox.add_actor(this.actor); Main.layoutManager.trayBox.add_actor(this.actor);
this.actor.y = this.actor.height; this.actor.y = -1;
Main.layoutManager.trackChrome(this.actor); Main.layoutManager.trackChrome(this.actor);
Main.layoutManager.trackChrome(this._notificationBin); Main.layoutManager.trackChrome(this._notificationBin);
@ -1478,24 +1482,12 @@ const MessageTray = new Lang.Class({
this._chatSummaryItemsCount = 0; this._chatSummaryItemsCount = 0;
}, },
_onCornerEnter: function(actor, event) {
this._pointerInSummary = true;
this._updateState();
},
_setSizePosition: function() { _setSizePosition: function() {
let monitor = Main.layoutManager.bottomMonitor; let monitor = Main.layoutManager.bottomMonitor;
this._notificationBin.x = 0; this._notificationBin.x = 0;
this._notificationBin.width = monitor.width; this._notificationBin.width = monitor.width;
this._summaryBin.x = 0; this._summaryBin.x = 0;
this._summaryBin.width = monitor.width; this._summaryBin.width = monitor.width;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
this._corner.x = 0;
else
this._corner.x = Main.layoutManager.trayBox.width - 1;
this._corner.y = Main.layoutManager.trayBox.height - 1;
}, },
contains: function(source) { contains: function(source) {
@ -2096,7 +2088,7 @@ const MessageTray = new Lang.Class({
_hideTray: function() { _hideTray: function() {
this._tween(this.actor, '_trayState', State.HIDDEN, this._tween(this.actor, '_trayState', State.HIDDEN,
{ y: this.actor.height, { y: -1,
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
@ -2434,14 +2426,17 @@ const MessageTray = new Lang.Class({
if (this._clickedSummaryItem) if (this._clickedSummaryItem)
this._updateState(); this._updateState();
} }
}); };
const SystemNotificationSource = new Lang.Class({ function SystemNotificationSource() {
Name: 'SystemNotificationSource', this._init();
Extends: Source, }
SystemNotificationSource.prototype = {
__proto__: Source.prototype,
_init: function() { _init: function() {
this.parent(_("System Information")); Source.prototype._init.call(this, _("System Information"));
this._setSummaryIcon(this.createNotificationIcon()); this._setSummaryIcon(this.createNotificationIcon());
}, },
@ -2455,4 +2450,4 @@ const SystemNotificationSource = new Lang.Class({
open: function() { open: function() {
this.destroy(); this.destroy();
} }
}); };

@ -29,9 +29,11 @@ const State = {
FADED_OUT: 4 FADED_OUT: 4
}; };
const ModalDialog = new Lang.Class({ function ModalDialog() {
Name: 'ModalDialog', this._init();
}
ModalDialog.prototype = {
_init: function(params) { _init: function(params) {
params = Params.parse(params, { shellReactive: false, params = Params.parse(params, { shellReactive: false,
styleClass: null }); styleClass: null });
@ -301,5 +303,5 @@ const ModalDialog = new Lang.Class({
}) })
}); });
} }
}); };
Signals.addSignalMethods(ModalDialog.prototype); Signals.addSignalMethods(ModalDialog.prototype);

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

@ -87,14 +87,16 @@ const rewriteRules = {
] ]
}; };
const NotificationDaemon = new Lang.Class({ function NotificationDaemon() {
Name: 'NotificationDaemon', this._init();
}
NotificationDaemon.prototype = {
_init: function() { _init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications'); this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
this._sources = []; this._sources = {};
this._senderToPid = {}; this._senderToPid = {};
this._notifications = {}; this._notifications = {};
this._busProxy = new Bus(); this._busProxy = new Bus();
@ -152,30 +154,14 @@ const NotificationDaemon = new Lang.Class({
} }
}, },
_lookupSource: function(title, pid, trayIcon) {
for (let i = 0; i < this._sources.length; i++) {
let source = this._sources[i];
if (source.pid == pid &&
(source.initialTitle == title || source.trayIcon || trayIcon))
return source;
}
return null;
},
// Returns the source associated with ndata.notification if it is set. // Returns the source associated with ndata.notification if it is set.
// Otherwise, returns the source associated with the title and pid if // Otherwise, returns the source associated with the pid if one is
// such source is stored in this._sources and the notification is not // stored in this._sources and the notification is not transient.
// transient. If the existing or requested source is associated with // Otherwise, creates a new source as long as pid is provided.
// a tray icon and passed in pid matches a pid of an existing source,
// the title match is ignored to enable representing a tray icon and
// notifications from the same application with a single source.
//
// If no existing source is found, a new source is created as long as
// pid is provided.
// //
// Either a pid or ndata.notification is needed to retrieve or // Either a pid or ndata.notification is needed to retrieve or
// create a source. // create a source.
_getSource: function(title, pid, ndata, sender, trayIcon) { _getSource: function(title, pid, ndata, sender) {
if (!pid && !(ndata && ndata.notification)) if (!pid && !(ndata && ndata.notification))
return null; return null;
@ -192,24 +178,20 @@ const NotificationDaemon = new Lang.Class({
// with a transient one from the same sender, so we // with a transient one from the same sender, so we
// always create a new source object for new transient notifications // always create a new source object for new transient notifications
// and never add it to this._sources . // and never add it to this._sources .
if (!isForTransientNotification) { if (!isForTransientNotification && this._sources[pid]) {
let source = this._lookupSource(title, pid, trayIcon); let source = this._sources[pid];
if (source) { source.setTitle(title);
source.setTitle(title); return source;
return source;
}
} }
let source = new Source(title, pid, sender, trayIcon); let source = new Source(title, pid, sender);
source.setTransient(isForTransientNotification); source.setTransient(isForTransientNotification);
if (!isForTransientNotification) { if (!isForTransientNotification) {
this._sources.push(source); this._sources[pid] = source;
source.connect('destroy', Lang.bind(this, source.connect('destroy', Lang.bind(this,
function() { function() {
let index = this._sources.indexOf(source); delete this._sources[pid];
if (index >= 0)
this._sources.splice(index, 1);
})); }));
} }
@ -288,7 +270,7 @@ const NotificationDaemon = new Lang.Class({
let sender = invocation.get_sender(); let sender = invocation.get_sender();
let pid = this._senderToPid[sender]; let pid = this._senderToPid[sender];
let source = this._getSource(appName, pid, ndata, sender, null); let source = this._getSource(appName, pid, ndata, sender);
if (source) { if (source) {
this._notifyForSource(source, ndata); this._notifyForSource(source, ndata);
@ -314,7 +296,7 @@ const NotificationDaemon = new Lang.Class({
} }
let [pid] = result; let [pid] = result;
source = this._getSource(appName, pid, ndata, sender, null); source = this._getSource(appName, pid, ndata, sender);
// We only store sender-pid entries for persistent sources. // We only store sender-pid entries for persistent sources.
// Removing the entries once the source is destroyed // Removing the entries once the source is destroyed
@ -463,8 +445,8 @@ const NotificationDaemon = new Lang.Class({
if (!tracker.focus_app) if (!tracker.focus_app)
return; return;
for (let i = 0; i < this._sources.length; i++) { for (let id in this._sources) {
let source = this._sources[i]; let source = this._sources[id];
if (source.app == tracker.focus_app) { if (source.app == tracker.focus_app) {
source.destroyNonResidentNotifications(); source.destroyNonResidentNotifications();
return; return;
@ -483,26 +465,28 @@ const NotificationDaemon = new Lang.Class({
}, },
_onTrayIconAdded: function(o, icon) { _onTrayIconAdded: function(o, icon) {
let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null, icon); let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null);
source.setTrayIcon(icon);
}, },
_onTrayIconRemoved: function(o, icon) { _onTrayIconRemoved: function(o, icon) {
let source = this._lookupSource(null, icon.pid, true); let source = this._sources[icon.pid];
if (source) if (source)
source.destroy(); source.destroy();
} }
}); };
const Source = new Lang.Class({ function Source(title, pid, sender) {
Name: 'NotificationDaemonSource', this._init(title, pid, sender);
Extends: MessageTray.Source, }
_init: function(title, pid, sender, trayIcon) { Source.prototype = {
this.parent(title); __proto__: MessageTray.Source.prototype,
this.initialTitle = title; _init: function(title, pid, sender) {
MessageTray.Source.prototype._init.call(this, title);
this.pid = pid; this._pid = pid;
if (sender) if (sender)
this._nameWatcherId = Gio.DBus.session.watch_name(sender, this._nameWatcherId = Gio.DBus.session.watch_name(sender,
Gio.BusNameWatcherFlags.NONE, Gio.BusNameWatcherFlags.NONE,
@ -516,12 +500,7 @@ const Source = new Lang.Class({
this.title = this.app.get_name(); this.title = this.app.get_name();
else else
this.useNotificationIcon = true; this.useNotificationIcon = true;
this._trayIcon = null;
this.trayIcon = trayIcon;
if (this.trayIcon) {
this._setSummaryIcon(this.trayIcon);
this.useNotificationIcon = false;
}
}, },
_onNameVanished: function() { _onNameVanished: function() {
@ -548,7 +527,7 @@ const Source = new Lang.Class({
}, },
handleSummaryClick: function() { handleSummaryClick: function() {
if (!this.trayIcon) if (!this._trayIcon)
return false; return false;
let event = Clutter.get_current_event(); let event = Clutter.get_current_event();
@ -569,11 +548,11 @@ const Source = new Lang.Class({
let id = global.connect('notify::stage-input-mode', Lang.bind(this, let id = global.connect('notify::stage-input-mode', Lang.bind(this,
function () { function () {
global.disconnect(id); global.disconnect(id);
this.trayIcon.click(event); this._trayIcon.click(event);
})); }));
Main.overview.hide(); Main.overview.hide();
} else { } else {
this.trayIcon.click(event); this._trayIcon.click(event);
} }
return true; return true;
}, },
@ -582,25 +561,31 @@ const Source = new Lang.Class({
if (this.app) if (this.app)
return; return;
this.app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid); this.app = Shell.WindowTracker.get_default().get_app_from_pid(this._pid);
if (!this.app) if (!this.app)
return; return;
// Only override the icon if we were previously using // Only override the icon if we were previously using
// notification-based icons (ie, not a trayicon) or if it was unset before // notification-based icons (ie, not a trayicon) or if it was unset before
if (!this.trayIcon) { if (!this._trayIcon) {
this.useNotificationIcon = false; this.useNotificationIcon = false;
this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE)); this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE));
} }
}, },
setTrayIcon: function(icon) {
this._setSummaryIcon(icon);
this.useNotificationIcon = false;
this._trayIcon = icon;
},
open: function(notification) { open: function(notification) {
this.destroyNonResidentNotifications(); this.destroyNonResidentNotifications();
this.openApp(); this.openApp();
}, },
_lastNotificationRemoved: function() { _lastNotificationRemoved: function() {
if (!this.trayIcon) if (!this._trayIcon)
this.destroy(); this.destroy();
}, },
@ -621,6 +606,6 @@ const Source = new Lang.Class({
this._nameWatcherId = 0; this._nameWatcherId = 0;
} }
this.parent(); MessageTray.Source.prototype.destroy.call(this);
} }
}); };

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

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

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

@ -22,9 +22,11 @@ const Util = imports.misc.util;
* @iconFactory: A JavaScript callback which will create an icon texture given a size parameter * @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
* @launch: A JavaScript callback to launch the entry * @launch: A JavaScript callback to launch the entry
*/ */
const PlaceInfo = new Lang.Class({ function PlaceInfo(id, name, iconFactory, launch) {
Name: 'PlaceInfo', this._init(id, name, iconFactory, launch);
}
PlaceInfo.prototype = {
_init: function(id, name, iconFactory, launch) { _init: function(id, name, iconFactory, launch) {
this.id = id; this.id = id;
this.name = name; this.name = name;
@ -53,7 +55,7 @@ const PlaceInfo = new Lang.Class({
isRemovable: function() { isRemovable: function() {
return false; return false;
} }
}); };
// Helper function to translate launch parameters into a GAppLaunchContext // Helper function to translate launch parameters into a GAppLaunchContext
function _makeLaunchContext(params) function _makeLaunchContext(params)
@ -70,9 +72,12 @@ function _makeLaunchContext(params)
return launchContext; return launchContext;
} }
const PlaceDeviceInfo = new Lang.Class({ function PlaceDeviceInfo(mount) {
Name: 'PlaceDeviceInfo', this._init(mount);
Extends: PlaceInfo, }
PlaceDeviceInfo.prototype = {
__proto__: PlaceInfo.prototype,
_init: function(mount) { _init: function(mount) {
this._mount = mount; this._mount = mount;
@ -118,11 +123,13 @@ const PlaceDeviceInfo = new Lang.Class({
_("Retry")); _("Retry"));
} }
} }
}); };
const PlacesManager = new Lang.Class({ function PlacesManager() {
Name: 'PlacesManager', this._init();
}
PlacesManager.prototype = {
_init: function() { _init: function() {
this._defaultPlaces = []; this._defaultPlaces = [];
this._mounts = []; this._mounts = [];
@ -155,12 +162,9 @@ const PlacesManager = new Lang.Class({
this._connect = new PlaceInfo('special:connect', _("Connect to..."), this._connect = new PlaceInfo('special:connect', _("Connect to..."),
function (size) { function (size) {
// do NOT use St.Icon here, it crashes the shell return new St.Icon({ icon_name: 'applications-internet',
// see wanda.js for details icon_type: St.IconType.FULLCOLOR,
return St.TextureCache.get_default().load_icon_name('applications-internet', icon_size: size });
null,
St.IconType.FULLCOLOR,
size);
}, },
function (params) { function (params) {
// BUG: nautilus-connect-server doesn't have a desktop file, so we can't // BUG: nautilus-connect-server doesn't have a desktop file, so we can't
@ -356,15 +360,19 @@ const PlacesManager = new Lang.Class({
_removeById: function(sourceArray, id) { _removeById: function(sourceArray, id) {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1); sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
} }
}); };
Signals.addSignalMethods(PlacesManager.prototype); Signals.addSignalMethods(PlacesManager.prototype);
const PlaceSearchProvider = new Lang.Class({
Name: 'PlaceSearchProvider', function PlaceSearchProvider() {
Extends: Search.SearchProvider, this._init();
}
PlaceSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() { _init: function() {
this.parent(_("PLACES & DEVICES")); Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
}, },
getResultMeta: function(resultId) { getResultMeta: function(resultId) {
@ -426,4 +434,4 @@ const PlaceSearchProvider = new Lang.Class({
let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); }); let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
return this._searchPlaces(places, terms); return this._searchPlaces(places, terms);
} }
}); };

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

@ -2,9 +2,7 @@
const Cairo = imports.cairo; const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
@ -28,9 +26,11 @@ function _ensureStyle(actor) {
actor.ensure_style(); actor.ensure_style();
} }
const PopupBaseMenuItem = new Lang.Class({ function PopupBaseMenuItem(params) {
Name: 'PopupBaseMenuItem', this._init(params);
}
PopupBaseMenuItem.prototype = {
_init: function (params) { _init: function (params) {
params = Params.parse (params, { reactive: true, params = Params.parse (params, { reactive: true,
activate: true, activate: true,
@ -377,27 +377,33 @@ const PopupBaseMenuItem = new Lang.Class({
x -= availWidth + this._spacing; x -= availWidth + this._spacing;
} }
} }
}); };
Signals.addSignalMethods(PopupBaseMenuItem.prototype); Signals.addSignalMethods(PopupBaseMenuItem.prototype);
const PopupMenuItem = new Lang.Class({ function PopupMenuItem() {
Name: 'PopupMenuItem', this._init.apply(this, arguments);
Extends: PopupBaseMenuItem, }
PopupMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function (text, params) { _init: function (text, params) {
this.parent(params); PopupBaseMenuItem.prototype._init.call(this, params);
this.label = new St.Label({ text: text }); this.label = new St.Label({ text: text });
this.addActor(this.label); this.addActor(this.label);
} }
}); };
const PopupSeparatorMenuItem = new Lang.Class({ function PopupSeparatorMenuItem() {
Name: 'PopupSeparatorMenuItem', this._init();
Extends: PopupBaseMenuItem, }
PopupSeparatorMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function () { _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._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
this.addActor(this._drawingArea, { span: -1, expand: true }); this.addActor(this._drawingArea, { span: -1, expand: true });
@ -423,19 +429,22 @@ const PopupSeparatorMenuItem = new Lang.Class({
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight); cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
cr.fill(); cr.fill();
} }
}); };
const PopupAlternatingMenuItemState = { const PopupAlternatingMenuItemState = {
DEFAULT: 0, DEFAULT: 0,
ALTERNATIVE: 1 ALTERNATIVE: 1
} }
const PopupAlternatingMenuItem = new Lang.Class({ function PopupAlternatingMenuItem() {
Name: 'PopupAlternatingMenuItem', this._init.apply(this, arguments);
Extends: PopupBaseMenuItem, }
PopupAlternatingMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(text, alternateText, params) { _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.actor.add_style_class_name('popup-alternating-menu-item');
this._text = text; this._text = text;
@ -521,14 +530,17 @@ const PopupAlternatingMenuItem = new Lang.Class({
this._updateLabel(); this._updateLabel();
} }
}); };
const PopupSliderMenuItem = new Lang.Class({ function PopupSliderMenuItem() {
Name: 'PopupSliderMenuItem', this._init.apply(this, arguments);
Extends: PopupBaseMenuItem, }
PopupSliderMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(value) { _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)); this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
@ -704,11 +716,13 @@ const PopupSliderMenuItem = new Lang.Class({
} }
return false; return false;
} }
}); };
const Switch = new Lang.Class({ function Switch() {
Name: 'Switch', this._init.apply(this, arguments);
}
Switch.prototype = {
_init: function(state) { _init: function(state) {
this.actor = new St.Bin({ style_class: 'toggle-switch' }); this.actor = new St.Bin({ style_class: 'toggle-switch' });
// Translators: this MUST be either "toggle-switch-us" // Translators: this MUST be either "toggle-switch-us"
@ -731,14 +745,17 @@ const Switch = new Lang.Class({
toggle: function() { toggle: function() {
this.setToggleState(!this.state); this.setToggleState(!this.state);
} }
}); };
const PopupSwitchMenuItem = new Lang.Class({ function PopupSwitchMenuItem() {
Name: 'PopupSwitchMenuItem', this._init.apply(this, arguments);
Extends: PopupBaseMenuItem, }
PopupSwitchMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function(text, active, params) { _init: function(text, active, params) {
this.parent(params); PopupBaseMenuItem.prototype._init.call(this, params);
this.label = new St.Label({ text: text }); this.label = new St.Label({ text: text });
this._switch = new Switch(active); this._switch = new Switch(active);
@ -773,7 +790,7 @@ const PopupSwitchMenuItem = new Lang.Class({
this.toggle(); this.toggle();
} }
this.parent(event); PopupBaseMenuItem.prototype.activate.call(this, event);
}, },
toggle: function() { toggle: function() {
@ -788,14 +805,17 @@ const PopupSwitchMenuItem = new Lang.Class({
setToggleState: function(state) { setToggleState: function(state) {
this._switch.setToggleState(state); this._switch.setToggleState(state);
} }
}); };
const PopupImageMenuItem = new Lang.Class({ function PopupImageMenuItem() {
Name: 'PopupImageMenuItem', this._init.apply(this, arguments);
Extends: PopupBaseMenuItem, }
PopupImageMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function (text, iconName, params) { _init: function (text, iconName, params) {
this.parent(params); PopupBaseMenuItem.prototype._init.call(this, params);
this.label = new St.Label({ text: text }); this.label = new St.Label({ text: text });
this.addActor(this.label); this.addActor(this.label);
@ -808,12 +828,13 @@ const PopupImageMenuItem = new Lang.Class({
setIcon: function(name) { setIcon: function(name) {
this._icon.icon_name = name; this._icon.icon_name = name;
} }
}); };
const PopupMenuBase = new Lang.Class({ function PopupMenuBase() {
Name: 'PopupMenuBase', throw new TypeError('Trying to instantiate abstract class PopupMenuBase');
Abstract: true, }
PopupMenuBase.prototype = {
_init: function(sourceActor, styleClass) { _init: function(sourceActor, styleClass) {
this.sourceActor = sourceActor; this.sourceActor = sourceActor;
@ -939,12 +960,7 @@ const PopupMenuBase = new Lang.Class({
this.emit('activate', menuItem); this.emit('activate', menuItem);
this.close(true); this.close(true);
})); }));
// the weird name is to avoid a conflict with some random property menuItem.connect('destroy', Lang.bind(this, function(emitter) {
// 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.disconnect(menuItem._activateId); menuItem.disconnect(menuItem._activateId);
menuItem.disconnect(menuItem._activeChangeId); menuItem.disconnect(menuItem._activeChangeId);
menuItem.disconnect(menuItem._sensitiveChangeId); menuItem.disconnect(menuItem._sensitiveChangeId);
@ -1123,15 +1139,18 @@ const PopupMenuBase = new Lang.Class({
this.emit('destroy'); this.emit('destroy');
} }
}); };
Signals.addSignalMethods(PopupMenuBase.prototype); Signals.addSignalMethods(PopupMenuBase.prototype);
const PopupMenu = new Lang.Class({ function PopupMenu() {
Name: 'PopupMenu', this._init.apply(this, arguments);
Extends: PopupMenuBase, }
PopupMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor, arrowAlignment, arrowSide) { _init: function(sourceActor, arrowAlignment, arrowSide) {
this.parent(sourceActor, 'popup-menu-content'); PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content');
this._arrowAlignment = arrowAlignment; this._arrowAlignment = arrowAlignment;
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
@ -1216,14 +1235,17 @@ const PopupMenu = new Lang.Class({
this.isOpen = false; this.isOpen = false;
this.emit('open-state-changed', false); this.emit('open-state-changed', false);
} }
}); };
const PopupSubMenu = new Lang.Class({ function PopupSubMenu() {
Name: 'PopupSubMenu', this._init.apply(this, arguments);
Extends: PopupMenuBase, }
PopupSubMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor, sourceArrow) { _init: function(sourceActor, sourceArrow) {
this.parent(sourceActor); PopupMenuBase.prototype._init.call(this, sourceActor);
this._arrow = sourceArrow; this._arrow = sourceArrow;
this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER; this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER;
@ -1378,7 +1400,7 @@ const PopupSubMenu = new Lang.Class({
return false; return false;
} }
}); };
/** /**
* PopupMenuSection: * PopupMenuSection:
@ -1388,41 +1410,36 @@ const PopupSubMenu = new Lang.Class({
* can add it to another menu), but is completely transparent * can add it to another menu), but is completely transparent
* to the user * to the user
*/ */
const PopupMenuSection = new Lang.Class({ function PopupMenuSection() {
Name: 'PopupMenuSection', this._init.apply(this, arguments);
Extends: PopupMenuBase, }
PopupMenuSection.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function() { _init: function() {
this.parent(); PopupMenuBase.prototype._init.call(this);
this.actor = this.box; this.actor = this.box;
this.actor._delegate = this; this.actor._delegate = this;
this.isOpen = true; this.isOpen = true;
// an array of externally managed separators
this.separators = [];
}, },
// deliberately ignore any attempt to open() or close(), but emit the // deliberately ignore any attempt to open() or close(), but emit the
// corresponding signal so children can still pick it up // corresponding signal so children can still pick it up
open: function(animate) { this.emit('open-state-changed', true); }, open: function(animate) { this.emit('open-state-changed', true); },
close: function() { this.emit('open-state-changed', false); }, close: function() { this.emit('open-state-changed', false); },
}
destroy: function() { function PopupSubMenuMenuItem() {
for (let i = 0; i < this.separators.length; i++) this._init.apply(this, arguments);
this.separators[i].destroy(); }
this.separators = [];
this.parent(); PopupSubMenuMenuItem.prototype = {
} __proto__: PopupBaseMenuItem.prototype,
});
const PopupSubMenuMenuItem = new Lang.Class({
Name: 'PopupSubMenuMenuItem',
Extends: PopupBaseMenuItem,
_init: function(text) { _init: function(text) {
this.parent(); PopupBaseMenuItem.prototype._init.call(this);
this.actor.add_style_class_name('popup-submenu-menu-item'); this.actor.add_style_class_name('popup-submenu-menu-item');
@ -1444,8 +1461,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
destroy: function() { destroy: function() {
this.menu.destroy(); this.menu.destroy();
PopupBaseMenuItem.prototype.destroy.call(this);
this.parent();
}, },
_onKeyPressEvent: function(actor, event) { _onKeyPressEvent: function(actor, event) {
@ -1460,7 +1476,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
return true; return true;
} }
return this.parent(actor, event); return PopupBaseMenuItem.prototype._onKeyPressEvent.call(this, actor, event);
}, },
activate: function(event) { activate: function(event) {
@ -1470,15 +1486,18 @@ const PopupSubMenuMenuItem = new Lang.Class({
_onButtonReleaseEvent: function(actor) { _onButtonReleaseEvent: function(actor) {
this.menu.toggle(); this.menu.toggle();
} }
}); };
const PopupComboMenu = new Lang.Class({ function PopupComboMenu() {
Name: 'PopupComboMenu', this._init.apply(this, arguments);
Extends: PopupMenuBase, }
PopupComboMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor) { _init: function(sourceActor) {
this.parent(sourceActor, 'popup-combo-menu'); PopupMenuBase.prototype._init.call(this,
sourceActor, 'popup-combo-menu');
this.actor = this.box; this.actor = this.box;
this.actor._delegate = this; this.actor._delegate = this;
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
@ -1583,14 +1602,17 @@ const PopupComboMenu = new Lang.Class({
getItemVisible: function(position) { getItemVisible: function(position) {
return this._getMenuItems()[position].actor.visible; return this._getMenuItems()[position].actor.visible;
} }
}); };
const PopupComboBoxMenuItem = new Lang.Class({ function PopupComboBoxMenuItem() {
Name: 'PopupComboBoxMenuItem', this._init.apply(this, arguments);
Extends: PopupBaseMenuItem, }
PopupComboBoxMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
_init: function (params) { _init: function (params) {
this.parent(params); PopupBaseMenuItem.prototype._init.call(this, params);
this._itemBox = new Shell.Stack(); this._itemBox = new Shell.Stack();
this.addActor(this._itemBox); this.addActor(this._itemBox);
@ -1708,276 +1730,16 @@ const PopupComboBoxMenuItem = new Lang.Class({
this.setActiveItem(position); this.setActiveItem(position);
this.emit('active-item-changed', 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 labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null);
let label = labelValue ? labelValue.deep_unpack() : '';
// remove all underscores that are not followed by another underscore
label = label.replace(/_([^_])/, '$1');
let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
if (section_link) {
let item = new PopupMenuSection();
if (label) {
let title = new PopupMenuItem(label, { reactive: false,
style_class: 'popup-subtitle-menu-item' });
item._titleMenuItem = title;
title._ignored = true;
item.addMenuItem(title);
}
this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
return [item, true, ''];
}
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();
k0 = 0;
// skip ignored items at the beginning
while (k0 < currentItems.length && currentItems[k0]._ignored)
k0++;
// find the right menu item matching the model item
for (j0 = 0; j0 < position; j0++, k0++) {
if (currentItems[k0]._ignored)
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]._ignored)
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) {
let separator = new PopupSeparatorMenuItem();
item.separators.push(separator);
separator._ignored = true;
target.addMenuItem(separator, k+1);
k++;
}
target.addMenuItem(item, k);
if (addSeparator) {
let separator = new PopupSeparatorMenuItem();
item.separators.push(separator);
separator._ignored = true;
target.addMenuItem(separator, 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) {
if (target._titleMenuItem)
target.actor.visible = target.numMenuItems != 1;
else
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. /* Basic implementation of a menu manager.
* Call addMenu to add menus * Call addMenu to add menus
*/ */
const PopupMenuManager = new Lang.Class({ function PopupMenuManager(owner) {
Name: 'PopupMenuManager', this._init(owner);
}
PopupMenuManager.prototype = {
_init: function(owner) { _init: function(owner) {
this._owner = owner; this._owner = owner;
this.grabbed = false; this.grabbed = false;
@ -2249,4 +2011,4 @@ const PopupMenuManager = new Lang.Class({
if (this._activeMenu != null) if (this._activeMenu != null)
this._activeMenu.close(true); this._activeMenu.close(true);
} }
}); };

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

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

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

@ -66,9 +66,11 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
</signal> </signal>
</interface>; </interface>;
const GnomeShell = new Lang.Class({ function GnomeShell() {
Name: 'GnomeShellDBus', this._init();
}
GnomeShell.prototype = {
_init: function() { _init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
@ -122,13 +124,8 @@ const GnomeShell = new Lang.Class({
* indicating whether the operation was successful or not. * indicating whether the operation was successful or not.
* *
*/ */
ScreenshotAreaAsync : function (params, invocation) { ScreenshotAreaAsync : function (x, y, width, height, filename, callback) {
let [x, y, width, height, filename, callback] = params; global.screenshot_area (x, y, width, height, filename, function (obj, result) { callback(result); });
global.screenshot_area (x, y, width, height, filename,
function (obj, result) {
let retval = GLib.Variant.new('(b)', [result]);
invocation.return_value(retval);
});
}, },
/** /**
@ -154,17 +151,12 @@ const GnomeShell = new Lang.Class({
* indicating whether the operation was successful or not. * indicating whether the operation was successful or not.
* *
*/ */
ScreenshotAsync : function (params, invocation) { ScreenshotAsync : function (filename, callback) {
let [filename] = params; global.screenshot(filename, function (obj, result) { callback(result); });
global.screenshot(filename,
function (obj, result) {
let retval = GLib.Variant.new('(b)', [result]);
invocation.return_value(retval);
});
}, },
ListExtensions: function() { ListExtensions: function() {
let out = {}; let out;
for (let uuid in ExtensionSystem.extensionMeta) { for (let uuid in ExtensionSystem.extensionMeta) {
let dbusObj = this.GetExtensionInfo(uuid); let dbusObj = this.GetExtensionInfo(uuid);
out[uuid] = dbusObj; out[uuid] = dbusObj;
@ -174,19 +166,19 @@ const GnomeShell = new Lang.Class({
GetExtensionInfo: function(uuid) { GetExtensionInfo: function(uuid) {
let meta = ExtensionSystem.extensionMeta[uuid] || {}; let meta = ExtensionSystem.extensionMeta[uuid] || {};
let out = {}; let out;
for (let key in meta) { for (let key in meta) {
let val = meta[key]; let val = meta[key];
let type; let type;
switch (typeof val) { switch (typeof val) {
case 'object':
throw Error('Extension had a nested object in the metadata. This is not supported');
case 'string': case 'string':
type = 's'; type = 's';
break; break;
case 'number': case 'number':
type = 'd'; type = 'd';
break; break;
default:
continue;
} }
out[key] = GLib.Variant.new(type, val); out[key] = GLib.Variant.new(type, val);
} }
@ -238,4 +230,4 @@ const GnomeShell = new Lang.Class({
this._dbusImpl.emit_signal('ExtensionStatusChanged', this._dbusImpl.emit_signal('ExtensionStatusChanged',
GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error])); GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
} }
}); };

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

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

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const GDesktopEnums = imports.gi.GDesktopEnums; const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
@ -39,12 +40,15 @@ const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
const HIGH_CONTRAST_THEME = 'HighContrast'; const HIGH_CONTRAST_THEME = 'HighContrast';
const ATIndicator = new Lang.Class({ function ATIndicator() {
Name: 'ATIndicator', this._init.apply(this, arguments);
Extends: PanelMenu.SystemStatusButton, }
ATIndicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() { _init: function() {
this.parent('preferences-desktop-accessibility', null); PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-accessibility', null);
let highContrast = this._buildHCItem(); let highContrast = this._buildHCItem();
this.menu.addMenuItem(highContrast); this.menu.addMenuItem(highContrast);
@ -168,4 +172,5 @@ const ATIndicator = new Lang.Class({
}); });
return widget; return widget;
} }
}); };
Signals.addSignalMethods(ATIndicator.prototype);

@ -23,13 +23,17 @@ const ConnectionState = {
CONNECTING: 3 CONNECTING: 3
} }
const Indicator = new Lang.Class({ function Indicator() {
Name: 'BTIndicator', this._init.apply(this, arguments);
Extends: PanelMenu.SystemStatusButton, }
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() { _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._applet = new GnomeBluetoothApplet.Applet();
this._killswitch = new PopupMenu.PopupSwitchMenuItem(_("Bluetooth"), false); this._killswitch = new PopupMenu.PopupSwitchMenuItem(_("Bluetooth"), false);
@ -331,14 +335,17 @@ const Indicator = new Lang.Class({
_cancelRequest: function() { _cancelRequest: function() {
this._source.destroy(); this._source.destroy();
} }
}); }
const Source = new Lang.Class({ function Source() {
Name: 'BluetoothSource', this._init.apply(this, arguments);
Extends: MessageTray.Source, }
Source.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function() { _init: function() {
this.parent(_("Bluetooth")); MessageTray.Source.prototype._init.call(this, _("Bluetooth"));
this._setSummaryIcon(this.createNotificationIcon()); this._setSummaryIcon(this.createNotificationIcon());
}, },
@ -352,7 +359,7 @@ const Source = new Lang.Class({
} }
})); }));
this.parent(notification); MessageTray.Source.prototype.notify.call(this, notification);
}, },
createNotificationIcon: function() { createNotificationIcon: function() {
@ -360,17 +367,21 @@ const Source = new Lang.Class({
icon_type: St.IconType.SYMBOLIC, icon_type: St.IconType.SYMBOLIC,
icon_size: this.ICON_SIZE }); icon_size: this.ICON_SIZE });
} }
}); }
const AuthNotification = new Lang.Class({ function AuthNotification() {
Name: 'AuthNotification', this._init.apply(this, arguments);
Extends: MessageTray.Notification, }
AuthNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, applet, device_path, name, long_name, uuid) { _init: function(source, applet, device_path, name, long_name, uuid) {
this.parent(source, MessageTray.Notification.prototype._init.call(this,
_("Bluetooth"), source,
_("Authorization request from %s").format(name), _("Bluetooth"),
{ customContent: true }); _("Authorization request from %s").format(name),
{ customContent: true });
this.setResident(true); this.setResident(true);
this._applet = applet; this._applet = applet;
@ -396,17 +407,21 @@ const AuthNotification = new Lang.Class({
this.destroy(); this.destroy();
})); }));
} }
}); }
const ConfirmNotification = new Lang.Class({ function ConfirmNotification() {
Name: 'ConfirmNotification', this._init.apply(this, arguments);
Extends: MessageTray.Notification, }
ConfirmNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, applet, device_path, name, long_name, pin) { _init: function(source, applet, device_path, name, long_name, pin) {
this.parent(source, MessageTray.Notification.prototype._init.call(this,
_("Bluetooth"), source,
_("Pairing confirmation for %s").format(name), _("Bluetooth"),
{ customContent: true }); _("Pairing confirmation for %s").format(name),
{ customContent: true });
this.setResident(true); this.setResident(true);
this._applet = applet; this._applet = applet;
@ -425,17 +440,21 @@ const ConfirmNotification = new Lang.Class({
this.destroy(); this.destroy();
})); }));
} }
}); }
const PinNotification = new Lang.Class({ function PinNotification() {
Name: 'PinNotification', this._init.apply(this, arguments);
Extends: MessageTray.Notification, }
PinNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, applet, device_path, name, long_name, numeric) { _init: function(source, applet, device_path, name, long_name, numeric) {
this.parent(source, MessageTray.Notification.prototype._init.call(this,
_("Bluetooth"), source,
_("Pairing request for %s").format(name), _("Bluetooth"),
{ customContent: true }); _("Pairing request for %s").format(name),
{ customContent: true });
this.setResident(true); this.setResident(true);
this._applet = applet; this._applet = applet;
@ -484,7 +503,7 @@ const PinNotification = new Lang.Class({
}, },
grabFocus: function(lockTray) { grabFocus: function(lockTray) {
this.parent(lockTray); MessageTray.Notification.prototype.grabFocus.call(this, lockTray);
global.stage.set_key_focus(this._entry); global.stage.set_key_focus(this._entry);
} }
}); }

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

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

@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
@ -52,13 +53,15 @@ const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface); const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
const Indicator = new Lang.Class({ function Indicator() {
Name: 'PowerIndicator', this._init.apply(this, arguments);
Extends: PanelMenu.SystemStatusButton, }
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() { _init: function() {
this.parent('battery-missing', null); PanelMenu.SystemStatusButton.prototype._init.call(this, 'battery-missing');
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH); this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
this._deviceItems = [ ]; this._deviceItems = [ ];
@ -161,14 +164,17 @@ const Indicator = new Lang.Class({
this._readPrimaryDevice(); this._readPrimaryDevice();
this._readOtherDevices(); this._readOtherDevices();
} }
}); };
const DeviceItem = new Lang.Class({ function DeviceItem() {
Name: 'DeviceItem', this._init.apply(this, arguments);
Extends: PopupMenu.PopupBaseMenuItem, }
DeviceItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(device) { _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; let [device_id, device_type, icon, percentage, state, time] = device;
@ -215,4 +221,4 @@ const DeviceItem = new Lang.Class({
return _("Unknown"); return _("Unknown");
} }
} }
}); }

@ -17,12 +17,15 @@ const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */
const VOLUME_NOTIFY_ID = 1; const VOLUME_NOTIFY_ID = 1;
const Indicator = new Lang.Class({ function Indicator() {
Name: 'VolumeIndicator', this._init.apply(this, arguments);
Extends: PanelMenu.SystemStatusButton, }
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() { _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 = new Gvc.MixerControl({ name: 'GNOME Shell Volume Control' });
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged)); this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
@ -211,4 +214,4 @@ const Indicator = new Lang.Class({
if (property == '_output' && !this._output.is_muted) if (property == '_output' && !this._output.is_muted)
this.setIcon(this._volumeToIcon(this._output.volume)); this.setIcon(this._volumeToIcon(this._output.volume));
} }
}); };

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

@ -33,6 +33,10 @@ const NotificationDirection = {
RECEIVED: 'chat-received' RECEIVED: 'chat-received'
}; };
let contactFeatures = [Tp.ContactFeature.ALIAS,
Tp.ContactFeature.AVATAR_DATA,
Tp.ContactFeature.PRESENCE];
// This is GNOME Shell's implementation of the Telepathy 'Client' // This is GNOME Shell's implementation of the Telepathy 'Client'
// interface. Specifically, the shell is a Telepathy 'Observer', which // interface. Specifically, the shell is a Telepathy 'Observer', which
// lets us see messages even if they belong to another app (eg, // lets us see messages even if they belong to another app (eg,
@ -68,9 +72,11 @@ function makeMessageFromTplEvent(event) {
}; };
} }
const Client = new Lang.Class({ function Client() {
Name: 'Client', this._init();
};
Client.prototype = {
_init : function() { _init : function() {
// channel path -> ChatSource // channel path -> ChatSource
this._chatSources = {}; this._chatSources = {};
@ -79,21 +85,11 @@ const Client = new Lang.Class({
// account path -> AccountNotification // account path -> AccountNotification
this._accountNotifications = {}; this._accountNotifications = {};
// Define features we want
this._accountManager = Tp.AccountManager.dup();
let factory = this._accountManager.get_factory();
factory.add_account_features([Tp.Account.get_feature_quark_connection()]);
factory.add_connection_features([Tp.Connection.get_feature_quark_contact_list()]);
factory.add_channel_features([Tp.Channel.get_feature_quark_contacts()]);
factory.add_contact_features([Tp.ContactFeature.ALIAS,
Tp.ContactFeature.AVATAR_DATA,
Tp.ContactFeature.PRESENCE,
Tp.ContactFeature.SUBSCRIPTION_STATES]);
// Set up a SimpleObserver, which will call _observeChannels whenever a // Set up a SimpleObserver, which will call _observeChannels whenever a
// channel matching its filters is detected. // channel matching its filters is detected.
// The second argument, recover, means _observeChannels will be run // The second argument, recover, means _observeChannels will be run
// for any existing channel as well. // for any existing channel as well.
this._accountManager = Tp.AccountManager.dup();
this._tpClient = new Shell.TpClient({ 'account-manager': this._accountManager, this._tpClient = new Shell.TpClient({ 'account-manager': this._accountManager,
'name': 'GnomeShell', 'name': 'GnomeShell',
'uniquify-name': true }) 'uniquify-name': true })
@ -120,9 +116,16 @@ const Client = new Lang.Class({
throw new Error('Couldn\'t register Telepathy client. Error: \n' + e); throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
} }
// Watch subscription requests and connection errors // Watch subscription requests and connection errors
this._subscriptionSource = null; this._subscriptionSource = null;
this._accountSource = null; this._accountSource = null;
let factory = this._accountManager.get_factory();
factory.add_account_features([Tp.Account.get_feature_quark_connection()]);
factory.add_connection_features([Tp.Connection.get_feature_quark_contact_list()]);
factory.add_contact_features([Tp.ContactFeature.SUBSCRIPTION_STATES,
Tp.ContactFeature.ALIAS,
Tp.ContactFeature.AVATAR_DATA]);
this._accountManager.connect('account-validity-changed', this._accountManager.connect('account-validity-changed',
Lang.bind(this, this._accountValidityChanged)); Lang.bind(this, this._accountValidityChanged));
@ -132,6 +135,22 @@ const Client = new Lang.Class({
_observeChannels: function(observer, account, conn, channels, _observeChannels: function(observer, account, conn, channels,
dispatchOp, requests, context) { dispatchOp, requests, context) {
// If the self_contact doesn't have the ALIAS, make sure
// to fetch it before trying to grab the channels.
let self_contact = conn.get_self_contact();
if (self_contact.has_feature(Tp.ContactFeature.ALIAS)) {
this._finishObserveChannels(account, conn, channels, context);
} else {
Shell.get_self_contact_features(conn,
contactFeatures,
Lang.bind(this, function() {
this._finishObserveChannels(account, conn, channels, context);
}));
context.delay();
}
},
_finishObserveChannels: function(account, conn, channels, context) {
let len = channels.length; let len = channels.length;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
let channel = channels[i]; let channel = channels[i];
@ -142,7 +161,16 @@ const Client = new Lang.Class({
targetHandleType != Tp.HandleType.CONTACT) targetHandleType != Tp.HandleType.CONTACT)
continue; continue;
this._createChatSource(account, conn, channel, channel.get_target_contact()); /* Request a TpContact */
Shell.get_tp_contacts(conn, [targetHandle],
contactFeatures,
Lang.bind(this, function (connection, contacts, failed) {
if (contacts.length < 1)
return;
/* We got the TpContact */
this._createChatSource(account, conn, channel, contacts[0]);
}), null);
} }
context.accept(); context.accept();
@ -171,11 +199,11 @@ const Client = new Lang.Class({
_handleChannels: function(handler, account, conn, channels, _handleChannels: function(handler, account, conn, channels,
requests, user_action_time, context) { requests, user_action_time, context) {
this._handlingChannels(account, conn, channels, true); this._handlingChannels(account, conn, channels);
context.accept(); context.accept();
}, },
_handlingChannels: function(account, conn, channels, notify) { _handlingChannels: function(account, conn, channels) {
let len = channels.length; let len = channels.length;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
let channel = channels[i]; let channel = channels[i];
@ -186,18 +214,7 @@ const Client = new Lang.Class({
continue; continue;
} }
// 'notify' will be true when coming from an actual HandleChannels if (this._tpClient.is_handling_channel(channel)) {
// 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)) {
// We are already handling the channel, display the source // We are already handling the channel, display the source
let source = this._chatSources[channel.get_object_path()]; let source = this._chatSources[channel.get_object_path()];
if (source) if (source)
@ -208,25 +225,41 @@ const Client = new Lang.Class({
_displayRoomInvitation: function(conn, channel, dispatchOp, context) { _displayRoomInvitation: function(conn, channel, dispatchOp, context) {
// We can only approve the rooms if we have been invited to it // We can only approve the rooms if we have been invited to it
let selfContact = channel.group_get_self_contact(); let selfHandle = channel.group_get_self_handle();
if (selfContact == null) { if (selfHandle == 0) {
Shell.decline_dispatch_op(context, 'Not invited to the room'); Shell.decline_dispatch_op(context, 'Not invited to the room');
return; return;
} }
let [invited, inviter, reason, msg] = channel.group_get_local_pending_contact_info(selfContact); let [invited, inviter, reason, msg] = channel.group_get_local_pending_info(selfHandle);
if (!invited) { if (!invited) {
Shell.decline_dispatch_op(context, 'Not invited to the room'); Shell.decline_dispatch_op(context, 'Not invited to the room');
return; return;
} }
// Request a TpContact for the inviter
Shell.get_tp_contacts(conn, [inviter],
contactFeatures,
Lang.bind(this, this._createRoomInviteSource, channel, context, dispatchOp));
context.delay();
},
_createRoomInviteSource: function(connection, contacts, failed, channel, context, dispatchOp) {
if (contacts.length < 1) {
Shell.decline_dispatch_op(context, 'Failed to get inviter');
return;
}
// We got the TpContact
// FIXME: We don't have a 'chat room' icon (bgo #653737) use // FIXME: We don't have a 'chat room' icon (bgo #653737) use
// system-users for now as Empathy does. // system-users for now as Empathy does.
let source = new ApproverSource(dispatchOp, _("Invitation"), let source = new ApproverSource(dispatchOp, _("Invitation"),
Gio.icon_new_for_string('system-users')); Gio.icon_new_for_string('system-users'));
Main.messageTray.add(source); Main.messageTray.add(source);
let notif = new RoomInviteNotification(source, dispatchOp, channel, inviter); let notif = new RoomInviteNotification(source, dispatchOp, channel, contacts[0]);
source.notify(notif); source.notify(notif);
context.accept(); context.accept();
}, },
@ -254,7 +287,7 @@ const Client = new Lang.Class({
Lang.bind(this, function(dispatchOp, result) { Lang.bind(this, function(dispatchOp, result) {
try { try {
dispatchOp.claim_with_finish(result); dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false); this._handlingChannels(account, conn, [channel]);
} catch (err) { } catch (err) {
throw new Error('Failed to Claim channel: ' + err); throw new Error('Failed to Claim channel: ' + err);
}})); }}));
@ -266,6 +299,21 @@ const Client = new Lang.Class({
}, },
_approveCall: function(account, conn, channel, dispatchOp, context) { _approveCall: function(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle();
Shell.get_tp_contacts(conn, [targetHandle],
contactFeatures,
Lang.bind(this, this._createAudioVideoSource, channel, context, dispatchOp));
context.delay();
},
_createAudioVideoSource: function(connection, contacts, failed, channel, context, dispatchOp) {
if (contacts.length < 1) {
Shell.decline_dispatch_op(context, 'Failed to get inviter');
return;
}
let isVideo = false; let isVideo = false;
let props = channel.borrow_immutable_properties(); let props = channel.borrow_immutable_properties();
@ -280,13 +328,27 @@ const Client = new Lang.Class({
Gio.icon_new_for_string('audio-input-microphone')); Gio.icon_new_for_string('audio-input-microphone'));
Main.messageTray.add(source); Main.messageTray.add(source);
let notif = new AudioVideoNotification(source, dispatchOp, channel, let notif = new AudioVideoNotification(source, dispatchOp, channel, contacts[0], isVideo);
channel.get_target_contact(), isVideo);
source.notify(notif); source.notify(notif);
context.accept(); context.accept();
}, },
_approveFileTransfer: function(account, conn, channel, dispatchOp, context) { _approveFileTransfer: function(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle();
Shell.get_tp_contacts(conn, [targetHandle],
contactFeatures,
Lang.bind(this, this._createFileTransferSource, channel, context, dispatchOp));
context.delay();
},
_createFileTransferSource: function(connection, contacts, failed, channel, context, dispatchOp) {
if (contacts.length < 1) {
Shell.decline_dispatch_op(context, 'Failed to get file sender');
return;
}
// Use the icon of the file being transferred // Use the icon of the file being transferred
let gicon = Gio.content_type_get_icon(channel.get_mime_type()); let gicon = Gio.content_type_get_icon(channel.get_mime_type());
@ -294,8 +356,7 @@ const Client = new Lang.Class({
let source = new ApproverSource(dispatchOp, _("File Transfer"), gicon); let source = new ApproverSource(dispatchOp, _("File Transfer"), gicon);
Main.messageTray.add(source); Main.messageTray.add(source);
let notif = new FileTransferNotification(source, dispatchOp, channel, let notif = new FileTransferNotification(source, dispatchOp, channel, contacts[0]);
channel.get_target_contact());
source.notify(notif); source.notify(notif);
context.accept(); context.accept();
}, },
@ -418,14 +479,17 @@ const Client = new Lang.Class({
return this._accountSource; return this._accountSource;
} }
}); };
const ChatSource = new Lang.Class({ function ChatSource(account, conn, channel, contact, client) {
Name: 'ChatSource', this._init(account, conn, channel, contact, client);
Extends: MessageTray.Source, }
ChatSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(account, conn, channel, contact, client) { _init: function(account, conn, channel, contact, client) {
this.parent(contact.get_alias()); MessageTray.Source.prototype._init.call(this, contact.get_alias());
this.isChat = true; this.isChat = true;
@ -443,9 +507,15 @@ const ChatSource = new Lang.Class({
this._notification.setUrgency(MessageTray.Urgency.HIGH); this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notifyTimeoutId = 0; this._notifyTimeoutId = 0;
// We ack messages when the user expands the new notification or views the summary // We ack messages when the message box is collapsed if user has
// notification, in which case the notification is also expanded. // interacted with it before and so read the messages:
this._notification.connect('expanded', Lang.bind(this, this._ackMessages)); // - 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(); this._presence = contact.get_presence_type();
@ -627,7 +697,7 @@ const ChatSource = new Lang.Class({
}, },
notify: function() { notify: function() {
this.parent(this._notification); MessageTray.Source.prototype.notify.call(this, this._notification);
}, },
respond: function(text) { respond: function(text) {
@ -669,12 +739,12 @@ const ChatSource = new Lang.Class({
if (presence == Tp.ConnectionPresenceType.AVAILABLE) { if (presence == Tp.ConnectionPresenceType.AVAILABLE) {
msg = _("%s is online.").format(title); msg = _("%s is online.").format(title);
shouldNotify = (this._presence == Tp.ConnectionPresenceType.OFFLINE); shouldNotify = (this._presence == Tp.ConnectionPresenceType.OFFLINE);
} else if (presence == Tp.ConnectionPresenceType.OFFLINE) { } else if (presence == Tp.ConnectionPresenceType.OFFLINE ||
presence == Tp.ConnectionPresenceType.EXTENDED_AWAY) {
presence = Tp.ConnectionPresenceType.OFFLINE; presence = Tp.ConnectionPresenceType.OFFLINE;
msg = _("%s is offline.").format(title); msg = _("%s is offline.").format(title);
shouldNotify = (this._presence != Tp.ConnectionPresenceType.OFFLINE); shouldNotify = (this._presence != Tp.ConnectionPresenceType.OFFLINE);
} else if (presence == Tp.ConnectionPresenceType.AWAY || } else if (presence == Tp.ConnectionPresenceType.AWAY) {
presence == Tp.ConnectionPresenceType.EXTENDED_AWAY) {
msg = _("%s is away.").format(title); msg = _("%s is away.").format(title);
shouldNotify = false; shouldNotify = false;
} else if (presence == Tp.ConnectionPresenceType.BUSY) { } else if (presence == Tp.ConnectionPresenceType.BUSY) {
@ -709,15 +779,36 @@ const ChatSource = new Lang.Class({
// 'pending-message-removed' for each one. // '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_async(Lang.bind(this, function(src, result) {
this._channel.ack_all_pending_messages_finish(result);})); this._channel.ack_all_pending_messages_finish(result);}));
} },
});
const ChatNotification = new Lang.Class({ _summaryItemClicked: function(source, button) {
Name: 'ChatNotification', if (button != 1)
Extends: MessageTray.Notification, 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) { _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.setResident(true);
this._responseEntry = new St.Entry({ style_class: 'chat-response', this._responseEntry = new St.Entry({ style_class: 'chat-response',
@ -1000,14 +1091,17 @@ const ChatNotification = new Lang.Class({
this.source.setChatState(Tp.ChannelChatState.ACTIVE); this.source.setChatState(Tp.ChannelChatState.ACTIVE);
} }
} }
}); };
const ApproverSource = new Lang.Class({ function ApproverSource(dispatchOp, text, gicon) {
Name: 'ApproverSource', this._init(dispatchOp, text, gicon);
Extends: MessageTray.Source, }
ApproverSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(dispatchOp, text, gicon) { _init: function(dispatchOp, text, gicon) {
this.parent(text); MessageTray.Source.prototype._init.call(this, text);
this._gicon = gicon; this._gicon = gicon;
this._setSummaryIcon(this.createNotificationIcon()); this._setSummaryIcon(this.createNotificationIcon());
@ -1028,7 +1122,7 @@ const ApproverSource = new Lang.Class({
this._invalidId = 0; this._invalidId = 0;
} }
this.parent(); MessageTray.Source.prototype.destroy.call(this);
}, },
createNotificationIcon: function() { createNotificationIcon: function() {
@ -1036,19 +1130,23 @@ const ApproverSource = new Lang.Class({
icon_type: St.IconType.FULLCOLOR, icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE }); icon_size: this.ICON_SIZE });
} }
}); }
const RoomInviteNotification = new Lang.Class({ function RoomInviteNotification(source, dispatchOp, channel, inviter) {
Name: 'RoomInviteNotification', this._init(source, dispatchOp, channel, inviter);
Extends: MessageTray.Notification, }
RoomInviteNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, dispatchOp, channel, inviter) { _init: function(source, dispatchOp, channel, inviter) {
this.parent(source, MessageTray.Notification.prototype._init.call(this,
/* translators: argument is a room name like source,
* room@jabber.org for example. */ /* translators: argument is a room name like
_("Invitation to %s").format(channel.get_identifier()), * room@jabber.org for example. */
null, _("Invitation to %s").format(channel.get_identifier()),
{ customContent: true }); null,
{ customContent: true });
this.setResident(true); this.setResident(true);
/* translators: first argument is the name of a contact and the second /* translators: first argument is the name of a contact and the second
@ -1075,12 +1173,15 @@ const RoomInviteNotification = new Lang.Class({
this.destroy(); this.destroy();
})); }));
} }
}); };
// Audio Video // Audio Video
const AudioVideoNotification = new Lang.Class({ function AudioVideoNotification(source, dispatchOp, channel, contact, isVideo) {
Name: 'AudioVideoNotification', this._init(source, dispatchOp, channel, contact, isVideo);
Extends: MessageTray.Notification, }
AudioVideoNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, dispatchOp, channel, contact, isVideo) { _init: function(source, dispatchOp, channel, contact, isVideo) {
let title = ''; let title = '';
@ -1092,7 +1193,11 @@ const AudioVideoNotification = new Lang.Class({
/* translators: argument is a contact name like Alice for example. */ /* translators: argument is a contact name like Alice for example. */
title = _("Call from %s").format(contact.get_alias()); 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.setResident(true);
this.addButton('reject', _("Reject")); this.addButton('reject', _("Reject"));
@ -1115,25 +1220,28 @@ const AudioVideoNotification = new Lang.Class({
this.destroy(); this.destroy();
})); }));
} }
}); };
// File Transfer // File Transfer
const FileTransferNotification = new Lang.Class({ function FileTransferNotification(source, dispatchOp, channel, contact) {
Name: 'FileTransferNotification', this._init(source, dispatchOp, channel, contact);
Extends: MessageTray.Notification, }
FileTransferNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, dispatchOp, channel, contact) { _init: function(source, dispatchOp, channel, contact) {
this.parent(this, MessageTray.Notification.prototype._init.call(this,
source, source,
/* To translators: The first parameter is /* To translators: The first parameter is
* the contact's alias and the second one is the * the contact's alias and the second one is the
* file name. The string will be something * file name. The string will be something
* like: "Alice is sending you test.ogg" * like: "Alice is sending you test.ogg"
*/ */
_("%s is sending you %s").format(contact.get_alias(), _("%s is sending you %s").format(contact.get_alias(),
channel.get_filename()), channel.get_filename()),
null, null,
{ customContent: true }); { customContent: true });
this.setResident(true); this.setResident(true);
this.addButton('decline', _("Decline")); this.addButton('decline', _("Decline"));
@ -1155,15 +1263,18 @@ const FileTransferNotification = new Lang.Class({
this.destroy(); this.destroy();
})); }));
} }
}); };
// A notification source that can embed multiple notifications // A notification source that can embed multiple notifications
const MultiNotificationSource = new Lang.Class({ function MultiNotificationSource(title, icon) {
Name: 'MultiNotificationSource', this._init(title, icon);
Extends: MessageTray.Source, }
MultiNotificationSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(title, icon) { _init: function(title, icon) {
this.parent(title); MessageTray.Source.prototype._init.call(this, title);
this._icon = icon; this._icon = icon;
this._setSummaryIcon(this.createNotificationIcon()); this._setSummaryIcon(this.createNotificationIcon());
@ -1171,7 +1282,7 @@ const MultiNotificationSource = new Lang.Class({
}, },
notify: function(notification) { notify: function(notification) {
this.parent(notification); MessageTray.Source.prototype.notify.call(this, notification);
this._nbNotifications += 1; this._nbNotifications += 1;
@ -1189,18 +1300,21 @@ const MultiNotificationSource = new Lang.Class({
icon_type: St.IconType.FULLCOLOR, icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE }); icon_size: this.ICON_SIZE });
} }
}); };
// Subscription request // Subscription request
const SubscriptionRequestNotification = new Lang.Class({ function SubscriptionRequestNotification(source, contact) {
Name: 'SubscriptionRequestNotification', this._init(source, contact);
Extends: MessageTray.Notification, }
SubscriptionRequestNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source, contact) { _init: function(source, contact) {
this.parent(this, source, MessageTray.Notification.prototype._init.call(this, source,
/* To translators: The parameter is the contact's alias */ /* To translators: The parameter is the contact's alias */
_("%s would like permission to see when you are online").format(contact.get_alias()), _("%s would like permission to see when you are online").format(contact.get_alias()),
null, { customContent: true }); null, { customContent: true });
this._contact = contact; this._contact = contact;
this._connection = contact.get_connection(); this._connection = contact.get_connection();
@ -1274,7 +1388,7 @@ const SubscriptionRequestNotification = new Lang.Class({
this._invalidatedId = 0; this._invalidatedId = 0;
} }
this.parent(); MessageTray.Notification.prototype.destroy.call(this);
}, },
_subscriptionStatesChangedCb: function(contact, subscribe, publish, msg) { _subscriptionStatesChangedCb: function(contact, subscribe, publish, msg) {
@ -1283,7 +1397,12 @@ const SubscriptionRequestNotification = new Lang.Class({
if (publish != Tp.SubscriptionState.ASK) if (publish != Tp.SubscriptionState.ASK)
this.destroy(); this.destroy();
} }
}); };
function AccountNotification(source, account, connectionError) {
this._init(source, account, connectionError);
}
// Messages from empathy/libempathy/empathy-utils.c // Messages from empathy/libempathy/empathy-utils.c
// create_errors_to_message_hash() // create_errors_to_message_hash()
@ -1338,16 +1457,15 @@ _connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_INSECURE)]
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_LIMIT_EXCEEDED)] _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"); = _("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({ AccountNotification.prototype = {
Name: 'AccountNotification', __proto__: MessageTray.Notification.prototype,
Extends: MessageTray.Notification,
_init: function(source, account, connectionError) { _init: function(source, account, connectionError) {
this.parent(source, MessageTray.Notification.prototype._init.call(this, source,
/* translators: argument is the account name, like /* translators: argument is the account name, like
* name@jabber.org for example. */ * name@jabber.org for example. */
_("Connection to %s failed").format(account.get_display_name()), _("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true }); null, { customContent: true });
this._label = new St.Label(); this._label = new St.Label();
this.addActor(this._label); this.addActor(this._label);
@ -1423,6 +1541,6 @@ const AccountNotification = new Lang.Class({
this._connectionStatusId = 0; this._connectionStatusId = 0;
} }
this.parent(); MessageTray.Notification.prototype.destroy.call(this);
} }
}); };

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

@ -40,12 +40,15 @@ const IMStatus = {
// Copyright (C) 2008,2009 Red Hat, Inc. // Copyright (C) 2008,2009 Red Hat, Inc.
const IMStatusItem = new Lang.Class({ function IMStatusItem(label, iconName) {
Name: 'IMStatusItem', this._init(label, iconName);
Extends: PopupMenu.PopupBaseMenuItem, }
IMStatusItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(label, iconName) { _init: function(label, iconName) {
this.parent(); PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
this.actor.add_style_class_name('status-chooser-status-item'); this.actor.add_style_class_name('status-chooser-status-item');
@ -58,15 +61,19 @@ const IMStatusItem = new Lang.Class({
this.label = new St.Label({ text: label }); this.label = new St.Label({ text: label });
this.addActor(this.label); this.addActor(this.label);
} }
}); };
const IMUserNameItem = new Lang.Class({ function IMUserNameItem() {
Name: 'IMUserNameItem', this._init();
Extends: PopupMenu.PopupBaseMenuItem, }
IMUserNameItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function() { _init: function() {
this.parent({ reactive: false, PopupMenu.PopupBaseMenuItem.prototype._init.call(this,
style_class: 'status-chooser-user-name' }); { reactive: false,
style_class: 'status-chooser-user-name' });
this._wrapper = new Shell.GenericContainer(); this._wrapper = new Shell.GenericContainer();
this._wrapper.connect('get-preferred-width', this._wrapper.connect('get-preferred-width',
@ -95,15 +102,19 @@ const IMUserNameItem = new Lang.Class({
_wrapperAllocate: function(actor, box, flags) { _wrapperAllocate: function(actor, box, flags) {
this.label.allocate(box, flags); this.label.allocate(box, flags);
} }
}); };
const IMStatusChooserItem = new Lang.Class({ function IMStatusChooserItem() {
Name: 'IMStatusChooserItem', this._init();
Extends: PopupMenu.PopupBaseMenuItem, }
IMStatusChooserItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function() { _init: function() {
this.parent({ reactive: false, PopupMenu.PopupBaseMenuItem.prototype._init.call (this,
style_class: 'status-chooser' }); { reactive: false,
style_class: 'status-chooser' });
this._iconBin = new St.Button({ style_class: 'status-chooser-user-icon' }); this._iconBin = new St.Button({ style_class: 'status-chooser-user-icon' });
this.addActor(this._iconBin); this.addActor(this._iconBin);
@ -209,7 +220,7 @@ const IMStatusChooserItem = new Lang.Class({
this._userChangedId = 0; this._userChangedId = 0;
} }
this.parent(); PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this);
}, },
// Override getColumnWidths()/setColumnWidths() to make the item // Override getColumnWidths()/setColumnWidths() to make the item
@ -239,8 +250,7 @@ const IMStatusChooserItem = new Lang.Class({
}, },
_setIconFromFile: function(iconFile) { _setIconFromFile: function(iconFile) {
this._iconBin.set_style('background-image: url("' + iconFile + '");' + this._iconBin.set_style('background-image: url("' + iconFile + '");');
'background-size: contain;');
this._iconBin.child = null; this._iconBin.child = null;
}, },
@ -299,7 +309,9 @@ const IMStatusChooserItem = new Lang.Class({
this._setComboboxPresence(presence); this._setComboboxPresence(presence);
if (!this._sessionPresenceRestored) { if (!this._sessionPresenceRestored) {
this._sessionStatusChanged(this._presence.status); this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
this._sessionStatusChanged(status);
}));
return; return;
} }
@ -412,16 +424,18 @@ const IMStatusChooserItem = new Lang.Class({
this._expectedPresence = newPresence; this._expectedPresence = newPresence;
this._accountMgr.set_all_requested_presences(newPresence, status, msg); this._accountMgr.set_all_requested_presences(newPresence, status, msg);
} }
}); };
const UserMenuButton = new Lang.Class({ function UserMenuButton() {
Name: 'UserMenuButton', this._init();
Extends: PanelMenu.Button, }
UserMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() { _init: function() {
this.parent(0.0); PanelMenu.Button.prototype._init.call(this, 0.0);
let box = new St.BoxLayout({ name: 'panelUserMenu' }); let box = new St.BoxLayout({ name: 'panelUserMenu' });
this.actor.add_actor(box); this.actor.add_actor(box);
@ -457,6 +471,10 @@ const UserMenuButton = new Lang.Class({
this._idleIcon = new St.Icon({ icon_name: 'user-idle', this._idleIcon = new St.Icon({ icon_name: 'user-idle',
style_class: 'popup-menu-icon' }); style_class: 'popup-menu-icon' });
this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
this._updateSwitch(status);
}));
this._accountMgr.connect('most-available-presence-changed', this._accountMgr.connect('most-available-presence-changed',
Lang.bind(this, this._updatePresenceIcon)); Lang.bind(this, this._updatePresenceIcon));
this._accountMgr.prepare_async(null, Lang.bind(this, this._accountMgr.prepare_async(null, Lang.bind(this,
@ -724,4 +742,4 @@ const UserMenuButton = new Lang.Class({
this._session.ShutdownRemote(); this._session.ShutdownRemote();
} }
} }
}); };

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

@ -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;
}
});

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

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

@ -23,8 +23,6 @@ const WINDOW_DND_SIZE = 256;
const SCROLL_SCALE_AMOUNT = 100 / 5; const SCROLL_SCALE_AMOUNT = 100 / 5;
const WINDOW_CLONE_MAXIMUM_SCALE = 0.7;
const LIGHTBOX_FADE_TIME = 0.1; const LIGHTBOX_FADE_TIME = 0.1;
const CLOSE_BUTTON_FADE_TIME = 0.1; const CLOSE_BUTTON_FADE_TIME = 0.1;
@ -58,13 +56,11 @@ function _clamp(value, min, max) {
} }
const ScaledPoint = new Lang.Class({ function ScaledPoint(x, y, scaleX, scaleY) {
Name: 'ScaledPoint', [this.x, this.y, this.scaleX, this.scaleY] = arguments;
}
_init: function(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
},
ScaledPoint.prototype = {
getPosition : function() { getPosition : function() {
return [this.x, this.y]; return [this.x, this.y];
}, },
@ -90,17 +86,18 @@ const ScaledPoint = new Lang.Class({
return [_interpolate(this.scaleX, other.scaleX, step), return [_interpolate(this.scaleX, other.scaleX, step),
_interpolate(this.scaleY, other.scaleY, step)]; _interpolate(this.scaleY, other.scaleY, step)];
} }
}); };
const WindowClone = new Lang.Class({ function WindowClone(realWindow) {
Name: 'WindowClone', this._init(realWindow);
}
_init : function(realWindow, workspace) { WindowClone.prototype = {
_init : function(realWindow) {
this.realWindow = realWindow; this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window; this.metaWindow = realWindow.meta_window;
this.metaWindow._delegate = this; this.metaWindow._delegate = this;
this._workspace = workspace;
let [borderX, borderY] = this._getInvisibleBorderPadding(); let [borderX, borderY] = this._getInvisibleBorderPadding();
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(), this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
@ -386,12 +383,19 @@ const WindowClone = new Lang.Class({
this.emit('drag-begin'); 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) { 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) { 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) { _onDragCancelled : function (draggable, time) {
@ -414,7 +418,7 @@ const WindowClone = new Lang.Class({
this.emit('drag-end'); this.emit('drag-end');
} }
}); };
Signals.addSignalMethods(WindowClone.prototype); Signals.addSignalMethods(WindowClone.prototype);
@ -423,9 +427,11 @@ Signals.addSignalMethods(WindowClone.prototype);
* @parentActor: The actor which will be the parent of all overlay items * @parentActor: The actor which will be the parent of all overlay items
* such as app icon and window caption * such as app icon and window caption
*/ */
const WindowOverlay = new Lang.Class({ function WindowOverlay(windowClone, parentActor) {
Name: 'WindowOverlay', this._init(windowClone, parentActor);
}
WindowOverlay.prototype = {
_init : function(windowClone, parentActor) { _init : function(windowClone, parentActor) {
let metaWindow = windowClone.metaWindow; let metaWindow = windowClone.metaWindow;
@ -490,9 +496,6 @@ const WindowOverlay = new Lang.Class({
}, },
fadeIn: function() { fadeIn: function() {
if (!this._hidden)
return;
this.show(); this.show();
this.title.opacity = 0; this.title.opacity = 0;
this._parentActor.raise_top(); this._parentActor.raise_top();
@ -521,7 +524,7 @@ const WindowOverlay = new Lang.Class({
// get_transformed_position() and get_transformed_size(), // get_transformed_position() and get_transformed_size(),
// as windowClone might be moving. // as windowClone might be moving.
// See Workspace._showWindowOverlay // See Workspace._showWindowOverlay
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, animate) { updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight) {
let button = this.closeButton; let button = this.closeButton;
let title = this.title; let title = this.title;
@ -543,34 +546,15 @@ const WindowOverlay = new Lang.Class({
else else
buttonX = cloneX + (cloneWidth - button._overlap); buttonX = cloneX + (cloneWidth - button._overlap);
if (animate) button.set_position(Math.floor(buttonX), Math.floor(buttonY));
this._animateOverlayActor(button, Math.floor(buttonX), Math.floor(buttonY), button.width);
else
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
if (!title.fullWidth) if (!title.fullWidth)
title.fullWidth = title.width; 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; let titleY = cloneY + cloneHeight + title._spacing;
title.set_position(Math.floor(titleX), Math.floor(titleY));
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'
});
}, },
_closeWindow: function(actor) { _closeWindow: function(actor) {
@ -658,7 +642,7 @@ const WindowOverlay = new Lang.Class({
this._parentActor.queue_relayout(); this._parentActor.queue_relayout();
} }
}); };
Signals.addSignalMethods(WindowOverlay.prototype); Signals.addSignalMethods(WindowOverlay.prototype);
const WindowPositionFlags = { const WindowPositionFlags = {
@ -669,9 +653,11 @@ const WindowPositionFlags = {
/** /**
* @metaWorkspace: a #Meta.Workspace, or null * @metaWorkspace: a #Meta.Workspace, or null
*/ */
const Workspace = new Lang.Class({ function Workspace(metaWorkspace, monitorIndex) {
Name: 'Workspace', this._init(metaWorkspace, monitorIndex);
}
Workspace.prototype = {
_init : function(metaWorkspace, monitorIndex) { _init : function(metaWorkspace, monitorIndex) {
// When dragging a window, we use this slot for reserve space. // When dragging a window, we use this slot for reserve space.
this._reservedSlot = null; this._reservedSlot = null;
@ -966,7 +952,7 @@ const Workspace = new Lang.Class({
let scale = Math.min((width - buttonOuterWidth) / rect.width, let scale = Math.min((width - buttonOuterWidth) / rect.width,
(height - buttonOuterHeight - captionHeight) / rect.height, (height - buttonOuterHeight - captionHeight) / rect.height,
WINDOW_CLONE_MAXIMUM_SCALE); 1.0);
x = Math.floor(x + (width - scale * rect.width) / 2); x = Math.floor(x + (width - scale * rect.width) / 2);
@ -1035,7 +1021,7 @@ const Workspace = new Lang.Class({
let [x, y, scale] = this._computeWindowLayout(metaWindow, slot); let [x, y, scale] = this._computeWindowLayout(metaWindow, slot);
if (overlay && initialPositioning) if (overlay)
overlay.hide(); overlay.hide();
if (animate && isOnCurrentWorkspace) { if (animate && isOnCurrentWorkspace) {
if (!metaWindow.showing_on_its_workspace()) { if (!metaWindow.showing_on_its_workspace()) {
@ -1058,11 +1044,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 { } else {
clone.actor.set_position(x, y); clone.actor.set_position(x, y);
clone.actor.set_scale(scale, scale); clone.actor.set_scale(scale, scale);
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
} }
} }
@ -1084,35 +1079,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) { _showWindowOverlay: function(clone, overlay, fade) {
if (clone.inDrag) if (clone.inDrag)
return; 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) { if (overlay) {
overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
if (fade) if (fade)
overlay.fadeIn(); overlay.fadeIn();
else else
@ -1130,16 +1113,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() { _delayedWindowRepositioning: function() {
if (this._windowIsZooming) if (this._windowIsZooming)
return true; return true;
@ -1157,16 +1130,22 @@ const Workspace = new Lang.Class({
return true; return true;
} }
let actorUnderPointer = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
for (let i = 0; i < this._windows.length; i++) {
if (this._windows[i].actor == actorUnderPointer)
return true;
}
this.positionWindows(WindowPositionFlags.ANIMATE); this.positionWindows(WindowPositionFlags.ANIMATE);
return false; return false;
}, },
showWindowsOverlays: function() {
if (this.leavingOverview)
return;
this._windowOverlaysGroup.show();
this._showAllOverlays();
},
hideWindowsOverlays: function() {
this._windowOverlaysGroup.hide();
},
_doRemoveWindow : function(metaWin) { _doRemoveWindow : function(metaWin) {
let win = metaWin.get_compositor_private(); let win = metaWin.get_compositor_private();
@ -1320,7 +1299,7 @@ const Workspace = new Lang.Class({
this.leavingOverview = true; this.leavingOverview = true;
this._hideAllOverlays(); this.hideWindowsOverlays();
if (this._repositionWindowsId > 0) { if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId); Mainloop.source_remove(this._repositionWindowsId);
@ -1411,7 +1390,7 @@ const Workspace = new Lang.Class({
// Create a clone of a (non-desktop) window and add it to the window list // Create a clone of a (non-desktop) window and add it to the window list
_addWindowClone : function(win) { _addWindowClone : function(win) {
let clone = new WindowClone(win, this); let clone = new WindowClone(win);
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup); let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
clone.connect('selected', clone.connect('selected',
@ -1539,6 +1518,6 @@ const Workspace = new Lang.Class({
return false; return false;
} }
}); };
Signals.addSignalMethods(Workspace.prototype); Signals.addSignalMethods(Workspace.prototype);

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

@ -25,9 +25,11 @@ const SLIDE_ANIMATION_TIME = 0.2;
// placeholder exactly. // placeholder exactly.
const WORKSPACE_CUT_SIZE = 10; const WORKSPACE_CUT_SIZE = 10;
const WindowClone = new Lang.Class({ function WindowClone(realWindow) {
Name: 'WindowClone', this._init(realWindow);
}
WindowClone.prototype = {
_init : function(realWindow) { _init : function(realWindow) {
this.actor = new Clutter.Clone({ source: realWindow.get_texture(), this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
reactive: true }); reactive: true });
@ -51,7 +53,6 @@ const WindowClone = new Lang.Class({
dragActorMaxSize: Workspace.WINDOW_DND_SIZE, dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY }); dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin)); 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._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
this.inDrag = false; this.inDrag = false;
}, },
@ -109,10 +110,6 @@ const WindowClone = new Lang.Class({
this.emit('drag-begin'); this.emit('drag-begin');
}, },
_onDragCancelled : function (draggable, time) {
this.emit('drag-cancelled');
},
_onDragEnd : function (draggable, time, snapback) { _onDragEnd : function (draggable, time, snapback) {
this.inDrag = false; this.inDrag = false;
@ -129,7 +126,7 @@ const WindowClone = new Lang.Class({
this.emit('drag-end'); this.emit('drag-end');
} }
}); };
Signals.addSignalMethods(WindowClone.prototype); Signals.addSignalMethods(WindowClone.prototype);
@ -147,15 +144,15 @@ const ThumbnailState = {
/** /**
* @metaWorkspace: a #Meta.Workspace * @metaWorkspace: a #Meta.Workspace
*/ */
const WorkspaceThumbnail = new Lang.Class({ function WorkspaceThumbnail(metaWorkspace) {
Name: 'WorkspaceThumbnail', this._init(metaWorkspace);
}
WorkspaceThumbnail.prototype = {
_init : function(metaWorkspace) { _init : function(metaWorkspace) {
this.metaWorkspace = metaWorkspace; this.metaWorkspace = metaWorkspace;
this.monitorIndex = Main.layoutManager.primaryIndex; this.monitorIndex = Main.layoutManager.primaryIndex;
this._removed = false;
this.actor = new St.Group({ reactive: true, this.actor = new St.Group({ reactive: true,
clip_to_allocation: true, clip_to_allocation: true,
style_class: 'workspace-thumbnail' }); style_class: 'workspace-thumbnail' });
@ -181,21 +178,17 @@ const WorkspaceThumbnail = new Lang.Class({
let monitor = Main.layoutManager.primaryMonitor; let monitor = Main.layoutManager.primaryMonitor;
this.setPorthole(monitor.x, monitor.y, monitor.width, monitor.height); this.setPorthole(monitor.x, monitor.y, monitor.width, monitor.height);
let windows = global.get_window_actors().filter(this._isWorkspaceWindow, this); let windows = global.get_window_actors().filter(this._isMyWindow, this);
// Create clones for windows that should be visible in the Overview // Create clones for windows that should be visible in the Overview
this._windows = []; this._windows = [];
this._allWindows = [];
this._minimizedChangedIds = [];
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let minimizedChangedId = windows[i].meta_window._minimizedChangedId =
windows[i].meta_window.connect('notify::minimized', windows[i].meta_window.connect('notify::minimized',
Lang.bind(this, Lang.bind(this,
this._updateMinimized)); this._updateMinimized));
this._allWindows.push(windows[i].meta_window);
this._minimizedChangedIds.push(minimizedChangedId);
if (this._isMyWindow(windows[i]) && this._isOverviewWindow(windows[i])) { if (this._isOverviewWindow(windows[i])) {
this._addWindowClone(windows[i]); this._addWindowClone(windows[i]);
} }
} }
@ -280,11 +273,17 @@ const WorkspaceThumbnail = new Lang.Class({
let clone = this._windows[index]; let clone = this._windows[index];
this._windows.splice(index, 1); this._windows.splice(index, 1);
if (win && this._isOverviewWindow(win)) {
if (metaWin._minimizedChangedId) {
metaWin.disconnect(metaWin._minimizedChangedId);
delete metaWin._minimizedChangedId;
}
}
clone.destroy(); clone.destroy();
}, },
_doAddWindow : function(metaWin) { _doAddWindow : function(metaWin) {
if (this._removed) if (this.leavingOverview)
return; return;
let win = metaWin.get_compositor_private(); let win = metaWin.get_compositor_private();
@ -294,7 +293,7 @@ const WorkspaceThumbnail = new Lang.Class({
// the compositor finds out about them... // the compositor finds out about them...
Mainloop.idle_add(Lang.bind(this, Mainloop.idle_add(Lang.bind(this,
function () { function () {
if (!this._removed && if (this.actor &&
metaWin.get_compositor_private() && metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace) metaWin.get_workspace() == this.metaWorkspace)
this._doAddWindow(metaWin); this._doAddWindow(metaWin);
@ -303,19 +302,16 @@ const WorkspaceThumbnail = new Lang.Class({
return; 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 // We might have the window in our list already if it was on all workspaces and
// now was moved to this workspace // now was moved to this workspace
if (this._lookupIndex (metaWin) != -1) if (this._lookupIndex (metaWin) != -1)
return; return;
if (!metaWin._minimizedChangedId)
metaWin._minimizedChangedId = metaWin.connect('notify::minimized',
Lang.bind(this,
this._updateMinimized));
if (!this._isMyWindow(win) || !this._isOverviewWindow(win)) if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
return; return;
@ -327,13 +323,6 @@ const WorkspaceThumbnail = new Lang.Class({
}, },
_windowRemoved : function(metaWorkspace, metaWin) { _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); this._doRemoveWindow(metaWin);
}, },
@ -360,36 +349,27 @@ const WorkspaceThumbnail = new Lang.Class({
this.actor.destroy(); this.actor.destroy();
}, },
workspaceRemoved : function() { _onDestroy: function(actor) {
if (this._removed)
return;
this._removed = true;
this.metaWorkspace.disconnect(this._windowAddedId); this.metaWorkspace.disconnect(this._windowAddedId);
this.metaWorkspace.disconnect(this._windowRemovedId); this.metaWorkspace.disconnect(this._windowRemovedId);
global.screen.disconnect(this._windowEnteredMonitorId); global.screen.disconnect(this._windowEnteredMonitorId);
global.screen.disconnect(this._windowLeftMonitorId); global.screen.disconnect(this._windowLeftMonitorId);
for (let i = 0; i < this._allWindows.length; i++) for (let i = 0; i < this._windows.length; i++) {
this._allWindows[i].disconnect(this._minimizedChangedIds[i]); let metaWin = this._windows[i].metaWindow;
}, if (metaWin._minimizedChangedId) {
metaWin.disconnect(metaWin._minimizedChangedId);
_onDestroy: function(actor) { delete metaWin._minimizedChangedId;
this.workspaceRemoved(); }
}
this._windows = []; this._windows = [];
this.actor = null; 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 // Tests if @win belongs to this workspace and monitor
_isMyWindow : function (win) { _isMyWindow : function (win) {
return this._isWorkspaceWindow(win) && return Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index()) &&
(!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex); (!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex);
}, },
@ -410,10 +390,6 @@ const WorkspaceThumbnail = new Lang.Class({
Lang.bind(this, function(clone) { Lang.bind(this, function(clone) {
Main.overview.beginWindowDrag(); Main.overview.beginWindowDrag();
})); }));
clone.connect('drag-cancelled',
Lang.bind(this, function(clone) {
Main.overview.cancelledWindowDrag();
}));
clone.connect('drag-end', clone.connect('drag-end',
Lang.bind(this, function(clone) { Lang.bind(this, function(clone) {
Main.overview.endWindowDrag(); Main.overview.endWindowDrag();
@ -493,14 +469,16 @@ const WorkspaceThumbnail = new Lang.Class({
return false; return false;
} }
}); };
Signals.addSignalMethods(WorkspaceThumbnail.prototype); Signals.addSignalMethods(WorkspaceThumbnail.prototype);
const ThumbnailsBox = new Lang.Class({ function ThumbnailsBox() {
Name: 'ThumbnailsBox', this._init();
}
ThumbnailsBox.prototype = {
_init: function() { _init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'workspace-thumbnails', this.actor = new Shell.GenericContainer({ style_class: 'workspace-thumbnails',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT }); request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
@ -547,59 +525,6 @@ const ThumbnailsBox = new Lang.Class({
this._stateCounts[ThumbnailState[key]] = 0; this._stateCounts[ThumbnailState[key]] = 0;
this._thumbnails = []; this._thumbnails = [];
Main.overview.connect('item-drag-begin',
Lang.bind(this, this._onDragBegin));
Main.overview.connect('item-drag-end',
Lang.bind(this, this._onDragEnd));
Main.overview.connect('item-drag-cancelled',
Lang.bind(this, this._onDragCancelled));
Main.overview.connect('window-drag-begin',
Lang.bind(this, this._onDragBegin));
Main.overview.connect('window-drag-end',
Lang.bind(this, this._onDragEnd));
Main.overview.connect('window-drag-cancelled',
Lang.bind(this, this._onDragCancelled));
},
_onDragBegin: function() {
this._dragCancelled = false;
this._dragMonitor = {
dragMotion: Lang.bind(this, this._onDragMotion)
};
DND.addDragMonitor(this._dragMonitor);
},
_onDragEnd: function() {
if (this._dragCancelled)
return;
this._endDrag();
},
_onDragCancelled: function() {
this._dragCancelled = true;
this._endDrag();
},
_endDrag: function() {
this._clearDragPlaceholder();
DND.removeDragMonitor(this._dragMonitor);
},
_onDragMotion: function(dragEvent) {
if (!this.actor.contains(dragEvent.targetActor))
this._onLeave();
return DND.DragMotionResult.CONTINUE;
},
_onLeave: function() {
this._clearDragPlaceholder();
},
_clearDragPlaceholder: function() {
this._dropPlaceholderPos = -1;
this.actor.queue_relayout();
}, },
// Draggable target interface // Draggable target interface
@ -672,7 +597,7 @@ const ThumbnailsBox = new Lang.Class({
// ... and bam, a workspace, good as new. // ... and bam, a workspace, good as new.
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
true, time); true, time);
else if (source.shellWorkspaceLaunch) else (source.shellWorkspaceLaunch)
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex, source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time }); timestamp: time });
@ -751,10 +676,8 @@ const ThumbnailsBox = new Lang.Class({
if (thumbnail.state > ThumbnailState.NORMAL) if (thumbnail.state > ThumbnailState.NORMAL)
continue; continue;
if (currentPos >= start && currentPos < start + count) { if (currentPos >= start && currentPos < start + count)
thumbnail.workspaceRemoved();
this._setThumbnailState(thumbnail, ThumbnailState.REMOVING); this._setThumbnailState(thumbnail, ThumbnailState.REMOVING);
}
currentPos++; currentPos++;
} }
@ -1105,4 +1028,4 @@ const ThumbnailsBox = new Lang.Class({
onCompleteScope: this onCompleteScope: this
}); });
} }
}); };

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

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

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

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

706
po/be.po

File diff suppressed because it is too large Load Diff

664
po/bg.po

File diff suppressed because it is too large Load Diff

647
po/cs.po

File diff suppressed because it is too large Load Diff

757
po/da.po

File diff suppressed because it is too large Load Diff

1405
po/el.po

File diff suppressed because it is too large Load Diff

658
po/es.po

File diff suppressed because it is too large Load Diff

778
po/fa.po

File diff suppressed because it is too large Load Diff

827
po/fi.po

File diff suppressed because it is too large Load Diff

756
po/gl.po

File diff suppressed because it is too large Load Diff

735
po/he.po

File diff suppressed because it is too large Load Diff

@ -11,7 +11,7 @@ msgstr ""
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2011-10-04 20:49+0000\n" "POT-Creation-Date: 2011-10-04 20:49+0000\n"
"PO-Revision-Date: 2012-01-04 10:19+0100\n" "PO-Revision-Date: 2011-10-17 10:30+0200\n"
"Last-Translator: Luca Ferretti <lferrett@gnome.org>\n" "Last-Translator: Luca Ferretti <lferrett@gnome.org>\n"
"Language-Team: Italian <tp@lists.linux.it>\n" "Language-Team: Italian <tp@lists.linux.it>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -583,7 +583,7 @@ msgstr[1] "Il sistema verrà spento automaticamente tra %d secondi."
#: ../js/ui/endSessionDialog.js:87 #: ../js/ui/endSessionDialog.js:87
msgid "Powering off the system." msgid "Powering off the system."
msgstr "Spegnimento del sistema." msgstr "pegnimento del sistema."
#: ../js/ui/endSessionDialog.js:98 #: ../js/ui/endSessionDialog.js:98
msgid "Click Restart to quit these applications and restart the system." msgid "Click Restart to quit these applications and restart the system."

864
po/ja.po

File diff suppressed because it is too large Load Diff

920
po/lt.po

File diff suppressed because it is too large Load Diff

1639
po/mk.po

File diff suppressed because it is too large Load Diff

745
po/nb.po

File diff suppressed because it is too large Load Diff

1908
po/nn.po

File diff suppressed because it is too large Load Diff

1630
po/ro.po

File diff suppressed because it is too large Load Diff

817
po/ru.po

File diff suppressed because it is too large Load Diff

720
po/sl.po

File diff suppressed because it is too large Load Diff

747
po/te.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