Compare commits

..

2 Commits

Author SHA1 Message Date
Florian Müllner
7d598b7725 Bump version to 3.7.3.1
Update NEWS.
2012-12-20 17:47:36 +01:00
Florian Müllner
9f890982b2 Revert "NetworkMenu: rework multiple NIC support"
This reverts commit 490206b5b2.

Conflicts:
	configure.ac
	src/gvc
2012-12-20 17:46:31 +01:00
113 changed files with 13294 additions and 19667 deletions

51
NEWS
View File

@@ -1,53 +1,6 @@
3.7.4.1
3.7.3.1
=======
* userMenu: Use show-full-name-in-top-bar setting [Bastien; #689561]
* dateMenu: Add "Open Clocks" entry [Mathieu; #644390]
* screenshot: Immediately show the flash spot [Jasper; #691875]
* Misc. bug fixes [Rico, Jeremy]
Contributors:
Jeremy Bicha, Mathieu Bridon, Bastien Nocera, Jasper St. Pierre,
Rico Tzschichholz
Translations:
Ihar Hrachyshka [be]
3.7.4
=====
* Make menu separators crisp [Giovanni, Allan; #641745]
* power: Update for new D-Bus name [Bastien; #690506]
* Add smooth scrolling support [Jasper; #687573]
* Tweak notification layout [Allan; #688506]
* Ping the active window when using the app menu [Giovanni; #684340]
* Make password entries insensitive after submission [Jasper; #690594, #690895]
* Honor lock-delay GSettings key [Giovanni, Matthias; #690766, #691170]
* Use text/calendar preferred app as the calendar app [Giovanni; #690767]
* lookingGlass: Move to an inspect() function [Jasper; #690726]
* Make OSK animation quicker, snappier [Rui; #688642]
* Allow to close chat notifications with Escape [Jasper; #690897]
* Honor org.gnome.desktop.screensaver.user-switch-enabled [Giovanni; #691042]
* Add a SelectArea() DBus method [Cosimo; #687954]
* Support non-absolute paths when saving screenshots [Cosimo; #688004]
* OSK: Fix extended keys popups [Rui; #674955]
* Don't hide or show the keyboard immediately [Rui; #688646]
* Improve padding in power menu [Giovanni; #689297]
* Add per-window input source switching [Rui; #691414]
* Misc bug fixes and cleanups [Rico, Jasper, Giovanni, Rui, Florian, Dan;
#690608, #690589, #690539, #687081, #690667, #690665, #690666, #685856,
#690858, #690895, #680414, #690965, #691019, #690590, #681376, #690180,
#685513, #689263, #691553, #691720, #691743, #691750]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Allan Day, Rui Matos,
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz,
Dan Winship
Translations:
Matej Urbančič [sl], Kjartan Maraas [nb], Mattias Põldaru [et],
Yaron Shahrabani [he], Aurimas Černius [lt], Khaled Hosny [ar],
Fran Diéguez [gl], Daniel Mustieles [es], Piotr Drąg [pl], Balázs Úr [hu],
Baurzhan Muftakhidinov [kk], Tobias Endrigkeit [de], Dušan Kazik [sk],
Aron Xu [zh_CN], Gheyret Kenji [ug]
* Revert 490206b to not depend on NMGTK-0.9.7, which hasn't been released yet
3.7.3
=====

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.7.4.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.7.3.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@@ -16,6 +16,8 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
# Checks for programs.
AC_PROG_CC
# Needed for per-target cflags, like in gnomeshell-taskpanel
AM_PROG_CC_C_O
# Initialize libtool
LT_PREREQ([2.2.6])
@@ -60,14 +62,15 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.13.4
CLUTTER_MIN_VERSION=1.11.11
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.35.4
MUTTER_MIN_VERSION=3.7.4
GJS_MIN_VERSION=1.33.2
MUTTER_MIN_VERSION=3.7.3
GTK_MIN_VERSION=3.3.9
GIO_MIN_VERSION=2.35.0
LIBECAL_MIN_VERSION=3.5.3
LIBEDATASERVER_MIN_VERSION=3.5.3
LIBEDATASERVERUI_MIN_VERSION=3.5.3
TELEPATHY_GLIB_MIN_VERSION=0.17.5
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
POLKIT_MIN_VERSION=0.100
@@ -75,7 +78,6 @@ STARTUP_NOTIFICATION_MIN_VERSION=0.11
GCR_MIN_VERSION=3.3.90
GNOME_DESKTOP_REQUIRED_VERSION=3.7.1
GNOME_MENUS_REQUIRED_VERSION=3.5.3
NETWORKMANAGER_MIN_VERSION=0.9.6
PULSE_MIN_VERS=2.0
# Collect more than 20 libraries for a prize!
@@ -93,22 +95,37 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
libcanberra libcanberra-gtk3
libcanberra
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
gnome-keyring-1 gcr-3 >= $GCR_MIN_VERSION)
libnm-glib libnm-util gnome-keyring-1
gcr-3 >= $GCR_MIN_VERSION)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
GNOME_KEYBINDINGS_KEYSDIR=`$PKG_CONFIG --variable keysdir gnome-keybindings`
AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS
CFLAGS=$GNOME_SHELL_CFLAGS
LIBS=$GNOME_SHELL_LIBS
AC_CHECK_FUNCS(JS_NewGlobalObject XFixesCreatePointerBarrier)
CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2.2)
AC_MSG_CHECKING([for bluetooth support])
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
@@ -155,19 +172,6 @@ if test "x$use_systemd" = "xyes"; then
AC_DEFINE(WITH_SYSTEMD, 1, [systemd support])
fi
GNOME_KEYBINDINGS_KEYSDIR=`$PKG_CONFIG --variable keysdir gnome-keybindings`
AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS
CFLAGS=$GNOME_SHELL_CFLAGS
LIBS=$GNOME_SHELL_LIBS
AC_CHECK_FUNCS(XFixesCreatePointerBarrier)
CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
AC_SUBST(MUTTER_GIR_DIR)
@@ -193,6 +197,16 @@ fi
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0()
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
AC_SUBST(G_IR_SCANNER)
G_IR_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
AC_SUBST(G_IR_COMPILER)
G_IR_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
AC_SUBST(G_IR_GENERATE)
GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
AC_SUBST(GIRDIR)
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
AC_SUBST(TYPELIBDIR)
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
@@ -208,7 +222,32 @@ if test "$enable_man" != no; then
fi
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
GNOME_COMPILE_WARNINGS([error])
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=error)
changequote(,)dnl
if test "$enable_compile_warnings" != no ; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
if test "$enable_compile_warnings" = error ; then
case " $CFLAGS " in
*[\ \ ]-Werror[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;;
esac
fi
fi
fi
changequote([,])dnl
AC_ARG_ENABLE(jhbuild-wrapper-script,
AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)

View File

@@ -12,7 +12,6 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = \
org.gnome.Shell.Screenshot.xml \
org.gnome.ShellSearchProvider.xml \
org.gnome.ShellSearchProvider2.xml

View File

@@ -1,128 +0,0 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Shell.Screenshot:
@short_description: Screenshot interface
The interface used to capture pictures of the screen contents.
-->
<interface name="org.gnome.Shell.Screenshot">
<!--
Screenshot:
@filename: The filename for the screenshot
@include_cursor: Whether to include the cursor image or not
@flash: Whether to flash the screen or not
@success: whether the screenshot was captured
@filename_used: the file where the screenshot was saved
Takes a screenshot of the whole screen and saves it
in @filename as png image, it returns a boolean
indicating whether the operation was successful or not.
@filename can either be an absolute path or a basename, in
which case the screenshot will be saved in the $XDG_PICTURES_DIR
or the home directory if it doesn't exist. The filename used
to save the screenshot will be returned in @filename_used.
-->
<method name="Screenshot">
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<!--
ScreenshotWindow:
@include_frame: Whether to include the frame or not
@include_cursor: Whether to include the cursor image or not
@flash: Whether to flash the window area or not
@filename: The filename for the screenshot
@success: whether the screenshot was captured
@filename_used: the file where the screenshot was saved
Takes a screenshot of the focused window (optionally omitting the frame)
and saves it in @filename as png image, it returns a boolean
indicating whether the operation was successful or not.
@filename can either be an absolute path or a basename, in
which case the screenshot will be saved in the $XDG_PICTURES_DIR
or the home directory if it doesn't exist. The filename used
to save the screenshot will be returned in @filename_used.
-->
<method name="ScreenshotWindow">
<arg type="b" direction="in" name="include_frame"/>
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<!--
ScreenshotArea:
@x: the X coordinate of the area to capture
@y: the Y coordinate of the area to capture
@width: the width of the area to capture
@height: the height of the area to capture
@flash: whether to flash the area or not
@filename: the filename for the screenshot
@success: whether the screenshot was captured
@filename_used: the file where the screenshot was saved
Takes a screenshot of the passed in area and saves it
in @filename as png image, it returns a boolean
indicating whether the operation was successful or not.
@filename can either be an absolute path or a basename, in
which case the screenshot will be saved in the $XDG_PICTURES_DIR
or the home directory if it doesn't exist. The filename used
to save the screenshot will be returned in @filename_used.
-->
<method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<!--
FlashArea:
@x: the X coordinate of the area to flash
@y: the Y coordinate of the area to flash
@width: the width of the area to flash
@height: the height of the area to flash
Renders a flash spot effect in the specified rectangle of the screen.
-->
<method name="FlashArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
</method>
<!--
SelectArea:
@x: the X coordinate of the selected area
@y: the Y coordinate of the selected area
@width: the width of the selected area
@height: the height of the selected area
Interactively allows the user to select a rectangular area of
the screen, and returns its coordinates.
-->
<method name="SelectArea">
<arg type="i" direction="out" name="x"/>
<arg type="i" direction="out" name="y"/>
<arg type="i" direction="out" name="width"/>
<arg type="i" direction="out" name="height"/>
</method>
</interface>
</node>

View File

@@ -65,6 +65,11 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
menuitem in single-user, single-session situations.
</_description>
</key>
<key name="show-full-name" type="b">
<default>true</default>
<_summary>Show full name in the user menu</_summary>
<_description>Whether the users full name is shown in the user menu or not.</_description>
</key>
<key name="remember-mount-password" type="b">
<default>false</default>
<_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary>

View File

@@ -206,12 +206,11 @@ StScrollBar StButton#vhandle:active {
}
.popup-separator-menu-item {
-gradient-height: 1px;
-gradient-start: rgba(255,255,255,0.0);
-gradient-end: rgba(255,255,255,0.3);
-margin-horizontal: 24px;
height: 1px;
padding: 8px 0px;
-gradient-height: 2px;
-gradient-start: rgba(8,8,8,0);
-gradient-end: #333333;
-margin-horizontal: 1.5em;
height: 1em;
}
.popup-alternating-menu-item:alternate {
@@ -252,10 +251,6 @@ StScrollBar StButton#vhandle:active {
icon-size: 1.09em;
}
.popup-battery-percentage {
padding-left: 24px;
}
/* Switches */
.toggle-switch {
width: 65px;
@@ -292,17 +287,13 @@ StScrollBar StButton#vhandle:active {
.hotplug-notification-item,
.hotplug-resident-eject-button,
.modal-dialog-button {
font-weight: bold;
border: 1px solid #8b8b8b;
background-gradient-direction: vertical;
background-gradient-start: rgba(255, 255, 255, 0.2);
background-gradient-end: rgba(255, 255, 255, 0);
}
.dash-search-button,
.modal-dialog-button {
font-weight: bold;
}
.dash-search-button:hover,
.notification-button:hover,
.notification-icon-button:hover,
@@ -363,7 +354,7 @@ StScrollBar StButton#vhandle:active {
background-gradient-start: rgba(5,5,6,0.1);
background-gradient-end: rgba(254,254,254,0.1);
background-gradient-direction: vertical;
transition-duration: 300ms;
transition-duration: 300;
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
}
@@ -398,7 +389,7 @@ StScrollBar StButton#vhandle:active {
color: rgb(64, 64, 64);
caret-color: rgb(64, 64, 64);
font-weight: bold;
transition-duration: 0ms;
transition-duration: 0;
}
.notification StEntry,
@@ -429,7 +420,7 @@ StScrollBar StButton#vhandle:active {
background-color: black;
font-weight: bold;
height: 1.86em;
transition-duration: 250ms;
transition-duration: 250;
}
#panel.lock-screen {
@@ -512,7 +503,7 @@ StScrollBar StButton#vhandle:active {
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
transition-duration: 100ms;
transition-duration: 100;
}
#panel.unlock-screen .panel-button,
@@ -727,10 +718,6 @@ StScrollBar StButton#vhandle:active {
-vertical-spacing: 32px;
}
.window-picker.external-monitor {
padding: 32px;
}
/* Dash */
#dash {
@@ -755,6 +742,10 @@ StScrollBar StButton#vhandle:active {
height: 24px;
}
#viewSelector {
spacing: 1em;
}
/* Search Box */
#searchEntry {
@@ -779,10 +770,6 @@ StScrollBar StButton#vhandle:active {
spacing: 18px;
}
#searchResultsBin {
max-width: 1000px;
}
#searchResultsContent {
padding-right: 20px;
spacing: 16px;
@@ -930,7 +917,7 @@ StScrollBar StButton#vhandle:active {
border-radius: 4px;
padding: 3px;
border: 1px rgba(0,0,0,0);
transition-duration: 100ms;
transition-duration: 100;
text-align: center;
}
@@ -947,7 +934,7 @@ StScrollBar StButton#vhandle:active {
.grid-search-result:hover .overview-icon {
background-color: rgba(255,255,255,0.1);
text-shadow: black 0px 2px 2px;
transition-duration: 100ms;
transition-duration: 100;
color:white;
}
@@ -963,20 +950,19 @@ StScrollBar StButton#vhandle:active {
color: white;
}
.show-apps:checked > .overview-icon,
.show-apps:active > .overview-icon {
.show-apps:checked > .overview-icon {
background-gradient-start: rgba(255, 255, 255, .05);
background-gradient-end: rgba(255, 255, 255, .15);
background-gradient-direction: vertical;
border-radius: 4px;
box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 1);
transition-duration: 100ms;
transition-duration: 100;
}
.show-apps:checked .show-apps-icon,
.show-apps:focus .show-apps-icon {
color: white;
transition-duration: 100ms;
transition-duration: 100;
}
.app-well-app:focus > .overview-icon,
@@ -1015,7 +1001,7 @@ StScrollBar StButton#vhandle:active {
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
transition-duration: 100ms;
transition-duration: 100;
padding-left: .3em;
padding-right: .3em;
}
@@ -1318,7 +1304,7 @@ StScrollBar StButton#vhandle:active {
#message-tray {
background: #2e3436 url(message-tray-background.png);
background-repeat: repeat;
height: 72px;
transition-duration: 250;
}
#message-tray:keyboard {
@@ -1345,7 +1331,7 @@ StScrollBar StButton#vhandle:active {
border-radius: 10px 10px 0px 0px;
background: rgba(0,0,0,0.9);
padding: 8px 8px 4px 8px;
spacing-rows: 4px;
spacing-rows: 10px;
spacing-columns: 10px;
}
@@ -1425,7 +1411,6 @@ StScrollBar StButton#vhandle:active {
}
.notification-actions {
padding-top: 18px;
spacing: 10px;
}
@@ -1588,7 +1573,7 @@ StScrollBar StButton#vhandle:active {
.summary-source {
border-radius: 4px;
padding: 0 6px 0 6px;
transition-duration: 100ms;
transition-duration: 100;
}
.summary-source-counter {
@@ -2417,7 +2402,6 @@ StScrollBar StButton#vhandle:active {
.screen-shield-notifications-box {
spacing: 18px;
max-width: 34em;
}
.screen-shield-notification-source {

View File

@@ -88,18 +88,11 @@ doc-gen-org.gnome.Shell.SearchProvider2.xml: $(top_srcdir)/data/org.gnome.ShellS
--generate-docbook doc-gen \
$(top_srcdir)/data/org.gnome.ShellSearchProvider2.xml
doc-gen-org.gnome.Shell.Screenshot.xml: $(top_srcdir)/data/org.gnome.Shell.Screenshot.xml
gdbus-codegen \
--interface-prefix org.gnome.Shell.Screenshot. \
--generate-docbook doc-gen \
$(top_srcdir)/data/org.gnome.Shell.Screenshot.xml
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files= \
doc-gen-org.gnome.Shell.SearchProvider.xml \
doc-gen-org.gnome.Shell.SearchProvider2.xml \
doc-gen-org.gnome.Shell.Screenshot.xml
doc-gen-org.gnome.Shell.SearchProvider2.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files

View File

@@ -66,11 +66,4 @@ its dependencies to build from tarballs.</description>
<gnome:userid>fmuellner</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Ray Strode</foaf:name>
<foaf:mbox rdf:resource="mailto:halfline@gmail.com" />
<gnome:userid>halfline</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

View File

@@ -28,7 +28,6 @@ nobase_dist_js_DATA = \
misc/extensionUtils.js \
misc/fileUtils.js \
misc/gnomeSession.js \
misc/hash.js \
misc/history.js \
misc/jsParse.js \
misc/loginManager.js \
@@ -50,6 +49,7 @@ nobase_dist_js_DATA = \
ui/extensionSystem.js \
ui/extensionDownloader.js \
ui/environment.js \
ui/flashspot.js \
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \
@@ -74,7 +74,6 @@ nobase_dist_js_DATA = \
ui/popupMenu.js \
ui/remoteSearch.js \
ui/runDialog.js \
ui/screenshot.js \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \

View File

@@ -128,7 +128,6 @@ const UserListItem = new Lang.Class({
let layout = new St.BoxLayout({ vertical: false });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
child: layout,
reactive: true,
@@ -493,7 +492,6 @@ const SessionListItem = new Lang.Class({
this.id = id;
this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
reactive: true,
x_fill: true,
@@ -534,7 +532,6 @@ const SessionListItem = new Lang.Class({
color.alpha / 255);
cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
cr.fill();
cr.$dispose();
},
_onClicked: function() {
@@ -554,7 +551,6 @@ const SessionList = new Lang.Class({
this.actor.child = this._box;
this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
x_fill: true,
y_fill: true });
@@ -677,7 +673,7 @@ const LoginDialog = new Lang.Class({
this.parent({ shellReactive: true,
styleClass: 'login-dialog',
parentActor: parentActor,
keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN,
keybindingMode: Main.KeybindingMode.LOGIN_SCREEN,
shouldFadeIn: false });
this.connect('destroy',
Lang.bind(this, this._onDestroy));
@@ -790,7 +786,6 @@ const LoginDialog = new Lang.Class({
let notListedLabel = new St.Label({ text: _("Not listed?"),
style_class: 'login-dialog-not-listed-label' });
this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
child: notListedLabel,
reactive: true,

View File

@@ -1,141 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const System = imports.system;
const Params = imports.misc.params;
// This is an implementation of EcmaScript SameValue algorithm,
// which returns true if two values are not observably distinguishable.
// It was taken from http://wiki.ecmascript.org/doku.php?id=harmony:egal
//
// In the future, we may want to use the 'is' operator instead.
function _sameValue(x, y) {
if (x === y) {
// 0 === -0, but they are not identical
return x !== 0 || 1 / x === 1 / y;
}
// NaN !== NaN, but they are identical.
// NaNs are the only non-reflexive value, i.e., if x !== x,
// then x is a NaN.
// isNaN is broken: it converts its argument to number, so
// isNaN("foo") => true
return x !== x && y !== y;
}
const _hashers = {
object: function(o) { return o ? System.addressOf(o) : 'null'; },
function: function(f) { return System.addressOf(f); },
string: function(s) { return s; },
number: function(n) { return String(n); },
undefined: function() { return 'undefined'; },
};
/* Map is meant to be similar in usage to ES6 Map, which is
described at http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets,
without requiring more than ES5 + Gjs extensions.
Known differences from other implementations:
Polyfills around the web usually implement HashMaps for
primitive values and reversed WeakMaps for object keys,
but we want real maps with real O(1) semantics in all cases,
and the easiest way is to have different hashers for different
types.
Known differences from the ES6 specification:
- Map is a Lang.Class, not a ES6 class, so inheritance,
prototype, sealing, etc. work differently.
- items(), keys() and values() don't return iterators,
they return actual arrays, so they incur a full copy everytime
they're called, and they don't see changes if you mutate
the table while iterating
(admittedly, the ES6 spec is a bit unclear on this, and
the reference code would just blow up)
*/
const Map = new Lang.Class({
Name: 'Map',
_init: function(iterable) {
this._pool = { };
if (iterable) {
for (let i = 0; i < iterable.length; i++) {
let [key, value] = iterable[i];
this.set(key, value);
}
}
},
_hashKey: function(key) {
let type = typeof(key);
return type + ':' + _hashers[type](key);
},
_internalGet: function(key) {
let hash = this._hashKey(key);
let node = this._pool[hash];
if (node && _sameValue(node.key, key))
return [true, node.value];
else
return [false, null];
},
get: function(key) {
return this._internalGet(key)[1];
},
has: function(key) {
return this._internalGet(key)[0];
},
set: function(key, value) {
let hash = this._hashKey(key);
let node = this._pool[hash];
if (node) {
node.key = key;
node.value = value;
} else {
this._pool[hash] = { key: key, value: value };
}
},
delete: function(key) {
let hash = this._hashKey(key);
let node = this._pool[hash];
if (node && _sameValue(node.key, key)) {
delete this._pool[hash];
return [node.key, node.value];
} else {
return [null, null];
}
},
keys: function() {
let pool = this._pool;
return Object.getOwnPropertyNames(pool).map(function(hash) {
return pool[hash].key;
});
},
values: function() {
let pool = this._pool;
return Object.getOwnPropertyNames(pool).map(function(hash) {
return pool[hash].value;
});
},
items: function() {
let pool = this._pool;
return Object.getOwnPropertyNames(pool).map(function(hash) {
return [pool[hash].key, pool[hash].value];
});
},
size: function() {
return Object.getOwnPropertyNames(this._pool).length;
},
});

View File

@@ -159,6 +159,86 @@ function killall(processName) {
}
}
// This was ported from network-manager-applet
// Copyright 2007 - 2011 Red Hat, Inc.
// Author: Dan Williams <dcbw@redhat.com>
const _IGNORED_WORDS = [
'Semiconductor',
'Components',
'Corporation',
'Communications',
'Company',
'Corp.',
'Corp',
'Co.',
'Inc.',
'Inc',
'Incorporated',
'Ltd.',
'Limited.',
'Intel',
'chipset',
'adapter',
'[hex]',
'NDIS',
'Module'
];
const _IGNORED_PHRASES = [
'Multiprotocol MAC/baseband processor',
'Wireless LAN Controller',
'Wireless LAN Adapter',
'Wireless Adapter',
'Network Connection',
'Wireless Cardbus Adapter',
'Wireless CardBus Adapter',
'54 Mbps Wireless PC Card',
'Wireless PC Card',
'Wireless PC',
'PC Card with XJACK(r) Antenna',
'Wireless cardbus',
'Wireless LAN PC Card',
'Technology Group Ltd.',
'Communication S.p.A.',
'Business Mobile Networks BV',
'Mobile Broadband Minicard Composite Device',
'Mobile Communications AB',
'(PC-Suite Mode)'
];
function fixupPCIDescription(desc) {
desc = desc.replace(/[_,]/, ' ');
/* Attempt to shorten ID by ignoring certain phrases */
for (let i = 0; i < _IGNORED_PHRASES.length; i++) {
let item = _IGNORED_PHRASES[i];
let pos = desc.indexOf(item);
if (pos != -1) {
let before = desc.substring(0, pos);
let after = desc.substring(pos + item.length, desc.length);
desc = before + after;
}
}
/* Attmept to shorten ID by ignoring certain individual words */
let words = desc.split(' ');
let out = [ ];
for (let i = 0; i < words.length; i++) {
let item = words[i];
// skip empty items (that come out from consecutive spaces)
if (item.length == 0)
continue;
if (_IGNORED_WORDS.indexOf(item) == -1) {
out.push(item);
}
}
return out.join(' ');
}
// lowerBound:
// @array: an array or array-like object, already sorted
// according to @cmp

View File

@@ -153,7 +153,6 @@ const ViewByCategories = new Lang.Class({
y_fill: false,
style_class: 'vfade' });
this._categoryScroll.add_actor(this._categoryBox);
this._categoryScroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.actor.add(this._view.actor, { expand: true, x_fill: true, y_fill: true });
this.actor.add(this._categoryScroll, { expand: false, y_fill: false, y_align: St.Align.START });

View File

@@ -220,8 +220,25 @@ const BoxPointer = new Lang.Class({
this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition();
this._updateFlip();
this._reposition(this._sourceActor, this._arrowAlignment);
if (this._shouldFlip()) {
switch (this._arrowSide) {
case St.Side.TOP:
this._arrowSide = St.Side.BOTTOM;
break;
case St.Side.BOTTOM:
this._arrowSide = St.Side.TOP;
break;
case St.Side.LEFT:
this._arrowSide = St.Side.RIGHT;
break;
case St.Side.RIGHT:
this._arrowSide = St.Side.LEFT;
break;
}
this._reposition(this._sourceActor, this._arrowAlignment);
}
}
},
@@ -388,11 +405,11 @@ const BoxPointer = new Lang.Class({
cr.setLineWidth(borderWidth);
cr.stroke();
}
cr.$dispose();
},
setPosition: function(sourceActor, alignment) {
this._arrowSide = this._userArrowSide;
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.actor.show();
@@ -400,8 +417,7 @@ const BoxPointer = new Lang.Class({
this._sourceActor = sourceActor;
this._arrowAlignment = alignment;
this._reposition();
this._updateFlip();
this._reposition(sourceActor, alignment);
},
setSourceAlignment: function(alignment) {
@@ -413,10 +429,7 @@ const BoxPointer = new Lang.Class({
this.setPosition(this._sourceActor, this._arrowAlignment);
},
_reposition: function() {
let sourceActor = this._sourceActor;
let alignment = this._arrowAlignment;
_reposition: function(sourceActor, alignment) {
// Position correctly relative to the sourceActor
let sourceNode = sourceActor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
@@ -540,7 +553,7 @@ const BoxPointer = new Lang.Class({
_shiftActor : function() {
// Since the position of the BoxPointer depends on the allocated size
// of the BoxPointer and the position of the source actor, trying
// to position the BoxPointer via the x/y properties will result in
// to position the BoxPoiner via the x/y properties will result in
// allocation loops and warnings. Instead we do the positioning via
// the anchor point, which is independent of allocation, and leave
// x == y == 0.
@@ -548,47 +561,37 @@ const BoxPointer = new Lang.Class({
-(this._yPosition + this._yOffset));
},
_calculateArrowSide: function(arrowSide) {
_shouldFlip: function() {
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let [minWidth, minHeight, boxWidth, boxHeight] = this._container.get_preferred_size();
let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
let boxWidth = boxAllocation.x2 - boxAllocation.x1;
let boxHeight = boxAllocation.y2 - boxAllocation.y1;
let monitor = Main.layoutManager.findMonitorForActor(this.actor);
switch (arrowSide) {
switch (this._arrowSide) {
case St.Side.TOP:
if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
if (boxAllocation.y2 > monitor.y + monitor.height &&
boxHeight < sourceAllocation.y1 - monitor.y)
return St.Side.BOTTOM;
return true;
break;
case St.Side.BOTTOM:
if (sourceAllocation.y1 - boxHeight < monitor.y &&
if (boxAllocation.y1 < monitor.y &&
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
return St.Side.TOP;
return true;
break;
case St.Side.LEFT:
if (sourceAllocation.y2 + boxWidth > monitor.x + monitor.width &&
if (boxAllocation.x2 > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - monitor.x)
return St.Side.RIGHT;
return true;
break;
case St.Side.RIGHT:
if (sourceAllocation.y1 - boxWidth < monitor.x &&
if (boxAllocation.x1 < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return St.Side.LEFT;
return true;
break;
}
return arrowSide;
},
_updateFlip: function() {
let arrowSide = this._calculateArrowSide(this._userArrowSide);
if (this._arrowSide != arrowSide) {
this._arrowSide = arrowSide;
this._reposition();
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._container.queue_relayout();
return false;
}));
}
return false;
},
set xOffset(offset) {

View File

@@ -88,9 +88,7 @@ const AutomountManager = new Lang.Class({
if (!this._loginManager.sessionActive)
return;
global.play_theme_sound(0, 'device-added-media',
_("External drive connected"),
null);
global.play_theme_sound(0, 'device-added-media');
},
_onDriveDisconnected: function() {
@@ -99,9 +97,7 @@ const AutomountManager = new Lang.Class({
if (!this._loginManager.sessionActive)
return;
global.play_theme_sound(0, 'device-removed-media',
_("External drive disconnected"),
null);
global.play_theme_sound(0, 'device-removed-media');
},
_onDriveEjectButton: function(monitor, drive) {

View File

@@ -293,6 +293,7 @@ const AutorunResidentSource = new Lang.Class({
_init: function(manager) {
this.parent(_("Removable Devices"), 'media-removable');
this.showInLockScreen = false;
this._mounts = [];
@@ -300,10 +301,6 @@ const AutorunResidentSource = new Lang.Class({
this._notification = new AutorunResidentNotification(this._manager, this);
},
_createPolicy: function() {
return new MessageTray.NotificationPolicy({ showInLockScreen: false });
},
buildRightClickMenu: function() {
return null;
},

View File

@@ -60,14 +60,18 @@ const KeyringDialog = new Lang.Class({
this._controlTable = null;
let buttons = [{ label: '',
action: Lang.bind(this, this._onCancelButton),
key: Clutter.Escape
},
{ label: '',
action: Lang.bind(this, this._onContinueButton),
default: true
}]
this._cancelButton = this.addButton({ label: '',
action: Lang.bind(this, this._onCancelButton),
key: Clutter.Escape });
this._continueButton = this.addButton({ label: '',
action: Lang.bind(this, this._onContinueButton),
default: true },
{ expand: true, x_fill: false, x_align: St.Align.END });
this.setButtons(buttons);
this._cancelButton = buttons[0].button;
this._continueButton = buttons[1].button;
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
@@ -142,14 +146,6 @@ const KeyringDialog = new Lang.Class({
this._messageBox.add(table, { x_fill: true, y_fill: true });
},
_updateSensitivity: function(sensitive) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive;
},
_ensureOpen: function() {
// NOTE: ModalDialog.open() is safe to call if the dialog is
// already open - it just returns true without side-effects
@@ -171,14 +167,12 @@ const KeyringDialog = new Lang.Class({
_onShowPassword: function(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._passwordEntry.grab_key_focus();
},
_onShowConfirm: function(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._continueButton.grab_key_focus();
},
@@ -198,7 +192,6 @@ const KeyringDialog = new Lang.Class({
},
_onContinueButton: function() {
this._updateSensitivity(false);
this.prompt.complete();
},

View File

@@ -159,13 +159,14 @@ const AuthenticationDialog = new Lang.Class({
messageBox.add(this._nullMessageLabel);
this._nullMessageLabel.show();
this._cancelButton = this.addButton({ label: _("Cancel"),
action: Lang.bind(this, this.cancel),
key: Clutter.Escape });
this._okButton = this.addButton({ label: _("Authenticate"),
action: Lang.bind(this, this._onAuthenticateButtonPressed),
default: true },
{ expand: true, x_fill: false, x_align: St.Align.END });
this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this.cancel),
key: Clutter.Escape
},
{ label: _("Authenticate"),
action: Lang.bind(this, this._onAuthenticateButtonPressed),
default: true
}]);
this._doneEmitted = false;
@@ -213,17 +214,8 @@ const AuthenticationDialog = new Lang.Class({
}
},
_updateSensitivity: function(sensitive) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive;
},
_onEntryActivate: function() {
let response = this._passwordEntry.get_text();
this._updateSensitivity(false);
this._session.response(response);
// When the user responds, dismiss already shown info and
// error texts (if any)
@@ -277,7 +269,6 @@ const AuthenticationDialog = new Lang.Class({
this._passwordBox.show();
this._passwordEntry.set_text('');
this._passwordEntry.grab_key_focus();
this._updateSensitivity(true);
this._ensureOpen();
},

View File

@@ -20,8 +20,8 @@ const Recorder = new Lang.Class({
Main.wm.addKeybinding('toggle-recording',
this._bindingSettings,
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._toggleRecorder));
},

View File

@@ -13,7 +13,6 @@ const Tp = imports.gi.TelepathyGLib;
const History = imports.misc.history;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
@@ -416,8 +415,6 @@ const TelepathyClient = new Lang.Class({
_ensureAppSource: function() {
if (this._appSource == null) {
this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
this._appSource.policy = new NotificationDaemon.NotificationApplicationPolicy('empathy');
Main.messageTray.add(this._appSource);
this._appSource.connect('destroy', Lang.bind(this, function () {
this._appSource = null;
@@ -487,10 +484,6 @@ const ChatSource = new Lang.Class({
return rightClickMenu;
},
_createPolicy: function() {
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
},
_updateAlias: function() {
let oldAlias = this.title;
let newAlias = this._contact.get_alias();
@@ -1055,10 +1048,6 @@ const ApproverSource = new Lang.Class({
}));
},
_createPolicy: function() {
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
},
destroy: function() {
if (this._invalidId != 0) {
this._dispatchOp.disconnect(this._invalidId);
@@ -1357,8 +1346,9 @@ const AccountNotification = new Lang.Class({
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'view':
let cmd = 'empathy-accounts --select-account=' +
account.get_path_suffix();
let cmd = '/usr/bin/empathy-accounts'
+ ' --select-account=%s'
.format(account.get_path_suffix());
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
app_info.launch([], global.create_app_launch_context());
break;

View File

@@ -32,7 +32,6 @@ function _onVertSepRepaint (area)
cr.setDash([1, 3], 1); // Hard-code for now
cr.setLineWidth(stippleWidth);
cr.stroke();
cr.$dispose();
};
const DateMenuButton = new Lang.Class({
@@ -84,26 +83,12 @@ const DateMenuButton = new Lang.Class({
}));
vbox.add(this._calendar.actor);
let separator = new PopupMenu.PopupSeparatorMenuItem();
separator.setColumnWidths(1);
vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
this._openCalendarItem.actor.can_focus = false;
vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
this._openClocksItem = new PopupMenu.PopupMenuItem(_("Open Clocks"));
this._openClocksItem.connect('activate', Lang.bind(this, this._onOpenClocksActivate));
this._openClocksItem.actor.can_focus = false;
vbox.add(this._openClocksItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._appInstalledChanged));
this._appInstalledChanged();
item = this.menu.addSettingsAction(_("Date and Time Settings"), 'gnome-datetime-panel.desktop');
if (item) {
let separator = new PopupMenu.PopupSeparatorMenuItem();
separator.setColumnWidths(1);
vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
item.actor.show_on_set_parent = false;
item.actor.can_focus = false;
item.actor.reparent(vbox);
@@ -123,6 +108,16 @@ const DateMenuButton = new Lang.Class({
// Event list
vbox.add(this._eventList.actor, { expand: true });
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
this._openCalendarItem.actor.can_focus = false;
vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
this._calendarSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.office.calendar' });
this._calendarSettings.connect('changed::exec',
Lang.bind(this, this._calendarSettingsChanged));
this._calendarSettingsChanged();
// Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
if (isOpen) {
@@ -156,9 +151,10 @@ const DateMenuButton = new Lang.Class({
this._sessionUpdated();
},
_appInstalledChanged: function() {
let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
this._openClocksItem.actor.visible = app !== null;
_calendarSettingsChanged: function() {
let exec = this._calendarSettings.get_string('exec');
let fullExec = GLib.find_program_in_path(exec);
this._openCalendarItem.actor.visible = fullExec != null;
},
_setEventsVisibility: function(visible) {
@@ -209,14 +205,24 @@ const DateMenuButton = new Lang.Class({
_onOpenCalendarActivate: function() {
this.menu.close();
let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
app.launch([], global.create_app_launch_context());
},
_onOpenClocksActivate: function() {
this.menu.close();
let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
app.activate();
let tool = this._calendarSettings.get_string('exec');
if (tool.length == 0 || tool.substr(0, 9) == 'evolution') {
// TODO: pass the selected day
let app = Shell.AppSystem.get_default().lookup_app('evolution-calendar.desktop');
app.activate();
} else {
let needTerm = this._calendarSettings.get_boolean('needs-term');
if (needTerm) {
let terminalSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.terminal' });
let term = terminalSettings.get_string('exec');
let arg = terminalSettings.get_string('exec-arg');
if (arg != '')
Util.spawn([term, arg, tool]);
else
Util.spawn([term, tool]);
} else {
Util.spawnCommandLine(tool)
}
}
}
});

45
js/ui/flashspot.js Normal file
View File

@@ -0,0 +1,45 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const FLASHSPOT_ANIMATION_TIME = 0.25; // seconds
const Flashspot = new Lang.Class({
Name: 'Flashspot',
Extends: Lightbox.Lightbox,
_init: function(area) {
this.parent(Main.uiGroup, { inhibitEvents: true,
width: area.width,
height: area.height });
this.actor.style_class = 'flashspot';
this.actor.set_position(area.x, area.y);
},
fire: function() {
this.actor.opacity = 0;
Tweener.addTween(this.actor,
{ opacity: 255,
time: FLASHSPOT_ANIMATION_TIME,
transition: 'linear',
onComplete: Lang.bind(this, this._onFireShowComplete)
});
this.actor.show();
},
_onFireShowComplete: function() {
Tweener.addTween(this.actor,
{ opacity: 0,
time: FLASHSPOT_ANIMATION_TIME,
transition: 'linear',
onComplete: Lang.bind(this, function() {
this.destroy();
})
});
}
});

View File

@@ -183,9 +183,6 @@ const GrabHelper = new Lang.Class({
else if (hadFocus || params.grabFocus)
_navigateActor(newFocus);
if ((params.grabFocus || params.modal) && !this._capturedEventId)
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this._grabStack.push(params);
return true;
},
@@ -195,6 +192,8 @@ const GrabHelper = new Lang.Class({
if (firstGrab) {
if (!Main.pushModal(this._owner, this._modalParams))
return false;
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
}
this._modalCount++;
@@ -206,6 +205,11 @@ const GrabHelper = new Lang.Class({
if (this._modalCount > 0)
return;
if (this._capturedEventId > 0) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
Main.popModal(this._owner);
global.sync_pointer();
},
@@ -304,11 +308,6 @@ const GrabHelper = new Lang.Class({
this._releaseFocusGrab();
}
if (!this.grabbed && this._capturedEventId > 0) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
if (hadFocus) {
let poppedGrab = poppedGrabs[0];
_navigateActor(poppedGrab.savedFocus);
@@ -317,13 +316,6 @@ const GrabHelper = new Lang.Class({
_onCapturedEvent: function(actor, event) {
let type = event.type();
if (type == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab({ isUser: true });
return true;
}
let press = type == Clutter.EventType.BUTTON_PRESS;
let release = type == Clutter.EventType.BUTTON_RELEASE;
let button = press || release;
@@ -336,6 +328,12 @@ const GrabHelper = new Lang.Class({
if (!button && this._modalCount == 0)
return false;
if (type == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab({ isUser: true });
return true;
}
if (this._isWithinGrabbedActor(event.get_source()))
return false;

View File

@@ -2,21 +2,18 @@
const Caribou = imports.gi.Caribou;
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const BoxPointer = imports.ui.boxpointer;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard';
const KEYBOARD_TYPE = 'keyboard-type';
@@ -59,7 +56,14 @@ const Key = new Lang.Class({
if (this._key.name == 'Control_L' || this._key.name == 'Alt_L')
this._key.latch = true;
this._key.connect('key-pressed', Lang.bind(this, function ()
{ this.actor.checked = true }));
this._key.connect('key-released', Lang.bind(this, function ()
{ this.actor.checked = false; }));
if (this._extended_keys.length > 0) {
this._grabbed = false;
this._eventCaptureId = 0;
this._key.connect('notify::show-subkeys', Lang.bind(this, this._onShowSubkeysChanged));
this._boxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
{ x_fill: true,
@@ -111,23 +115,52 @@ const Key = new Lang.Class({
this._boxPointer.bin.add_actor(this._extended_keyboard);
},
get subkeys() {
return this._boxPointer;
_onEventCapture: function (actor, event) {
let source = event.get_source();
let type = event.type();
if ((type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE) &&
this._extended_keyboard.contains(source)) {
source.extended_key.press();
source.extended_key.release();
return false;
}
if (type == Clutter.EventType.BUTTON_PRESS) {
this._boxPointer.actor.hide();
this._ungrab();
return true;
}
return false;
},
_ungrab: function () {
global.stage.disconnect(this._eventCaptureId);
this._eventCaptureId = 0;
this._grabbed = false;
Main.popModal(this.actor);
},
_onShowSubkeysChanged: function () {
if (this._key.show_subkeys) {
this.actor.fake_release();
this._boxPointer.actor.raise_top();
this._boxPointer.setPosition(this.actor, 0.5);
this.emit('show-subkeys');
this.actor.fake_release();
this._boxPointer.show(BoxPointer.PopupAnimation.FULL);
this.actor.set_hover(false);
if (!this._grabbed) {
Main.pushModal(this.actor);
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
this._grabbed = true;
}
this._key.release();
} else {
this.emit('hide-subkeys');
if (this._grabbed)
this._ungrab();
this._boxPointer.hide(BoxPointer.PopupAnimation.FULL);
}
}
});
Signals.addSignalMethods(Key.prototype);
const Keyboard = new Lang.Class({
// HACK: we can't set Name, because it collides with Name dbus property
@@ -142,26 +175,16 @@ const Keyboard = new Lang.Class({
this._focusInExtendedKeys = false;
this._timestamp = global.display.get_current_time_roundtrip();
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA });
this._keyboardSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._a11yApplicationsSettings = new Gio.Settings({ schema: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._settingsChanged();
},
this._showIdleId = 0;
this._subkeysBoxPointer = null;
this._capturedEventId = 0;
this._capturedPress = false;
this._keyboardVisible = false;
Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, function(o, visible) {
this._keyboardVisible = visible;
}));
this._keyboardRequested = false;
this._keyboardRestingId = 0;
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
init: function () {
this._redraw();
},
@@ -250,14 +273,10 @@ const Keyboard = new Lang.Class({
return;
let time = global.get_current_time();
if (!(focus instanceof Clutter.Text)) {
if (focus instanceof Clutter.Text)
this.Show(time);
else
this.Hide(time);
return;
}
if (!this._showIdleId)
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE,
Lang.bind(this, function() { this.Show(time); }));
},
_addKeys: function () {
@@ -312,19 +331,6 @@ const Keyboard = new Lang.Class({
return trayButton;
},
_onCapturedEvent: function(actor, event) {
let type = event.type();
let press = type == Clutter.EventType.BUTTON_PRESS;
let release = type == Clutter.EventType.BUTTON_RELEASE;
if (press)
this._capturedPress = true;
else if (release && this._capturedPress)
this._hideSubkeys();
return true;
},
_addRows : function (keys, layout) {
let keyboard_row = new St.BoxLayout();
for (let i = 0; i < keys.length; ++i) {
@@ -347,19 +353,6 @@ const Keyboard = new Lang.Class({
// Add new key for hiding message tray
right_box.add(this._getTrayIcon());
}
button.connect('show-subkeys', Lang.bind(this, function() {
if (this._subkeysBoxPointer)
this._subkeysBoxPointer.hide(BoxPointer.PopupAnimation.FULL);
this._subkeysBoxPointer = button.subkeys;
this._subkeysBoxPointer.show(BoxPointer.PopupAnimation.FULL);
if (!this._capturedEventId)
this._capturedEventId = this.actor.connect('captured-event',
Lang.bind(this, this._onCapturedEvent));
}));
button.connect('hide-subkeys', Lang.bind(this, function() {
this._hideSubkeys();
}));
}
keyboard_row.add(left_box, { expand: true, x_fill: false, x_align: St.Align.START });
keyboard_row.add(right_box, { expand: true, x_fill: false, x_align: St.Align.END });
@@ -469,37 +462,7 @@ const Keyboard = new Lang.Class({
actor._extended_keys || actor.extended_key;
},
_clearKeyboardRestTimer: function() {
if (!this._keyboardRestingId)
return;
GLib.source_remove(this._keyboardRestingId);
this._keyboardRestingId = 0;
},
show: function (monitor) {
this._keyboardRequested = true;
if (this._keyboardVisible) {
if (monitor != Main.layoutManager.keyboardIndex) {
Main.layoutManager.keyboardIndex = monitor;
this._redraw();
}
return;
}
this._clearKeyboardRestTimer();
this._keyboardRestingId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
KEYBOARD_REST_TIME,
Lang.bind(this, function() {
this._clearKeyboardRestTimer();
this._show(monitor);
}));
},
_show: function(monitor) {
if (!this._keyboardRequested)
return;
Main.layoutManager.keyboardIndex = monitor;
this._redraw();
Main.layoutManager.showKeyboard();
@@ -507,41 +470,10 @@ const Keyboard = new Lang.Class({
},
hide: function () {
this._keyboardRequested = false;
if (!this._keyboardVisible)
return;
this._clearKeyboardRestTimer();
this._keyboardRestingId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
KEYBOARD_REST_TIME,
Lang.bind(this, function() {
this._clearKeyboardRestTimer();
this._hide();
}));
},
_hide: function() {
if (this._keyboardRequested)
return;
this._hideSubkeys();
Main.layoutManager.hideKeyboard();
this._createSource();
},
_hideSubkeys: function() {
if (this._subkeysBoxPointer) {
this._subkeysBoxPointer.hide(BoxPointer.PopupAnimation.FULL);
this._subkeysBoxPointer = null;
}
if (this._capturedEventId) {
this.actor.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
this._capturedPress = false;
},
_moveTemporarily: function () {
let currentWindow = global.screen.get_display().focus_window;
let rect = currentWindow.get_outer_rect();
@@ -570,13 +502,6 @@ const Keyboard = new Lang.Class({
return one - two;
},
_clearShowIdle: function() {
if (!this._showIdleId)
return;
GLib.source_remove(this._showIdleId);
this._showIdleId = 0;
},
// D-Bus methods
Show: function(timestamp) {
if (!this._enableKeyboard)
@@ -585,8 +510,6 @@ const Keyboard = new Lang.Class({
if (this._compareTimestamp(timestamp, this._timestamp) < 0)
return;
this._clearShowIdle();
if (timestamp != Clutter.CURRENT_TIME)
this._timestamp = timestamp;
this.show(Main.layoutManager.focusIndex);
@@ -599,8 +522,6 @@ const Keyboard = new Lang.Class({
if (this._compareTimestamp(timestamp, this._timestamp) < 0)
return;
this._clearShowIdle();
if (timestamp != Clutter.CURRENT_TIME)
this._timestamp = timestamp;
this.hide();
@@ -635,7 +556,11 @@ const KeyboardSource = new Lang.Class({
this.keepTrayOnSummaryClick = true;
},
handleSummaryClick: function(button) {
handleSummaryClick: function() {
let event = Clutter.get_current_event();
if (event.type() != Clutter.EventType.BUTTON_RELEASE)
return false;
this.open();
return true;
},

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,6 @@
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const St = imports.gi.St;
const Params = imports.misc.params;
@@ -102,7 +101,6 @@ const Lightbox = new Lang.Class({
},
show: function() {
Tweener.removeTweens(this.actor);
if (this._fadeInTime) {
this.shown = false;
this.actor.opacity = 0;
@@ -112,20 +110,17 @@ const Lightbox = new Lang.Class({
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this.shown = true;
this.emit('shown');
})
});
} else {
this.actor.opacity = 255 * this._fadeFactor;
this.shown = true;
this.emit('shown');
}
this.actor.show();
},
hide: function() {
this.shown = false;
Tweener.removeTweens(this.actor);
if (this._fadeOutTime) {
Tweener.addTween(this.actor,
{ opacity: 0,
@@ -202,4 +197,3 @@ const Lightbox = new Lang.Class({
this.highlight(null);
}
});
Signals.addSignalMethods(Lightbox.prototype);

View File

@@ -39,7 +39,6 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
* in the shell core code too. */
'const stage = global.stage; ' +
/* Special lookingGlass functions */
'const inspect = Lang.bind(Main.lookingGlass, Main.lookingGlass.inspect); ' +
'const it = Main.lookingGlass.getIt(); ' +
'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
@@ -872,7 +871,8 @@ const LookingGlass = new Lang.Class({
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
let inspector = new Inspector(this);
inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
this._pushResult('inspect(' + Math.round(stageX) + ', ' + Math.round(stageY) + ')', target);
this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
target);
}));
inspector.connect('closed', Lang.bind(this, function() {
this.actor.show();
@@ -1057,10 +1057,6 @@ const LookingGlass = new Lang.Class({
this._entry.text = '';
},
inspect: function(x, y) {
return global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
},
getIt: function () {
return this._it;
},
@@ -1133,7 +1129,7 @@ const LookingGlass = new Lang.Class({
if (this._open)
return;
if (!Main.pushModal(this._entry, { keybindingMode: Shell.KeyBindingMode.LOOKING_GLASS }))
if (!Main.pushModal(this._entry, { keybindingMode: Main.KeybindingMode.LOOKING_GLASS }))
return;
this._notebook.selectIndex(0);

View File

@@ -38,6 +38,20 @@ const XdndHandler = imports.ui.xdndHandler;
const Util = imports.misc.util;
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
const KeybindingMode = {
NONE: 0, // block all keybindings
NORMAL: 1 << 0, // window mode
OVERVIEW: 1 << 1,
LOCK_SCREEN: 1 << 2,
UNLOCK_SCREEN: 1 << 3,
LOGIN_SCREEN: 1 << 4,
MESSAGE_TRAY: 1 << 5,
SYSTEM_MODAL: 1 << 6,
LOOKING_GLASS: 1 << 7,
ALL: ~0,
};
let componentManager = null;
let panel = null;
@@ -55,30 +69,31 @@ let shellDBusService = null;
let shellMountOpDBusService = null;
let screenSaverDBus = null;
let modalCount = 0;
let keybindingMode = Shell.KeyBindingMode.NORMAL;
let keybindingMode = KeybindingMode.NORMAL;
let modalActorFocusStack = [];
let uiGroup = null;
let magnifier = null;
let xdndHandler = null;
let keyboard = null;
let layoutManager = null;
let background = null;
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
let _overridesSettings = null;
let background = null;
function _sessionUpdated() {
wm.setCustomKeybindingHandler('panel-main-menu',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
KeybindingMode.NORMAL |
KeybindingMode.OVERVIEW,
sessionMode.hasOverview ? Lang.bind(overview, overview.toggle) : null);
wm.allowKeybinding('overlay-key', Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW);
wm.allowKeybinding('overlay-key', KeybindingMode.NORMAL |
KeybindingMode.OVERVIEW);
wm.setCustomKeybindingHandler('panel-run-dialog',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
KeybindingMode.NORMAL |
KeybindingMode.OVERVIEW,
sessionMode.hasRunDialog ? openRunDialog : null);
if (sessionMode.isGreeter)
screenShield.showDialog();
@@ -111,17 +126,38 @@ function start() {
tracker.connect('startup-sequence-changed', _queueCheckWorkspaces);
// Setup the stage hierarchy early
layoutManager = new Layout.LayoutManager();
// For backward compatibility
uiGroup = layoutManager.uiGroup;
let backgroundActor = global.window_group.background;
background = backgroundActor.settings;
// The stage is always covered so Clutter doesn't need to clear it; however
// the color is used as the default contents for the Mutter root background
// actor so set it anyways.
global.stage.color = DEFAULT_BACKGROUND_COLOR;
global.stage.no_clear_hint = true;
_defaultCssStylesheet = global.datadir + '/theme/gnome-shell.css';
loadTheme();
// Set up stage hierarchy to group all UI actors under one container.
uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
uiGroup.connect('allocate',
function (actor, box, flags) {
let children = uiGroup.get_children();
for (let i = 0; i < children.length; i++)
children[i].allocate_preferred_size(flags);
});
uiGroup.connect('get-preferred-width',
function(actor, forHeight, alloc) {
let width = global.stage.width;
[alloc.min_size, alloc.natural_size] = [width, width];
});
uiGroup.connect('get-preferred-height',
function(actor, forWidth, alloc) {
let height = global.stage.height;
[alloc.min_size, alloc.natural_size] = [height, height];
});
global.window_group.reparent(uiGroup);
global.overlay_group.reparent(uiGroup);
global.stage.add_actor(uiGroup);
layoutManager = new Layout.LayoutManager();
xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
overview = new Overview.Overview();
@@ -139,6 +175,7 @@ function start() {
componentManager = new Components.ComponentManager();
layoutManager.init();
keyboard.init();
overview.init();
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
@@ -175,14 +212,6 @@ function start() {
ExtensionDownloader.init();
ExtensionSystem.init();
// Run the startup animation as soon as the mainloop is idle enough
// This is necessary to have it smooth and without interruptions from
// completed IO tasks
GLib.idle_add(GLib.PRIORITY_LOW, function() {
layoutManager.startupAnimation();
return false;
});
}
let _workspaces = [];
@@ -491,7 +520,7 @@ function isInModalStack(actor) {
* - options: Meta.ModalOptions flags to indicate that the pointer is
* already grabbed
*
* - keybindingMode: used to set the current Shell.KeyBindingMode to filter
* - keybindingMode: used to set the current Main.KeybindingMode to filter
* global keybindings; the default of NONE will filter
* out all keybindings
*
@@ -500,7 +529,7 @@ function isInModalStack(actor) {
function pushModal(actor, params) {
params = Params.parse(params, { timestamp: global.get_current_time(),
options: 0,
keybindingMode: Shell.KeyBindingMode.NONE });
keybindingMode: KeybindingMode.NONE });
if (modalCount == 0) {
if (!global.begin_modal(params.timestamp, params.options)) {
@@ -518,20 +547,19 @@ function pushModal(actor, params) {
if (index >= 0)
popModal(actor);
});
let prevFocus = global.stage.get_key_focus();
let prevFocusDestroyId;
if (prevFocus != null) {
prevFocusDestroyId = prevFocus.connect('destroy', function() {
let curFocus = global.stage.get_key_focus();
let curFocusDestroyId;
if (curFocus != null) {
curFocusDestroyId = curFocus.connect('destroy', function() {
let index = _findModal(actor);
if (index >= 0)
modalActorFocusStack[index].prevFocus = null;
modalActorFocusStack[index].actor = null;
});
}
modalActorFocusStack.push({ actor: actor,
focus: curFocus,
destroyId: actorDestroyId,
prevFocus: prevFocus,
prevFocusDestroyId: prevFocusDestroyId,
focusDestroyId: curFocusDestroyId,
keybindingMode: keybindingMode });
keybindingMode = params.keybindingMode;
@@ -561,7 +589,7 @@ function popModal(actor, timestamp) {
global.stage.set_key_focus(null);
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
keybindingMode = Shell.KeyBindingMode.NORMAL;
keybindingMode = KeybindingMode.NORMAL;
throw new Error('incorrect pop');
}
@@ -572,33 +600,18 @@ function popModal(actor, timestamp) {
record.actor.disconnect(record.destroyId);
if (focusIndex == modalActorFocusStack.length - 1) {
if (record.prevFocus)
record.prevFocus.disconnect(record.prevFocusDestroyId);
if (record.focus)
record.focus.disconnect(record.focusDestroyId);
keybindingMode = record.keybindingMode;
global.stage.set_key_focus(record.prevFocus);
global.stage.set_key_focus(record.focus);
} else {
// If we have:
// global.stage.set_focus(a);
// Main.pushModal(b);
// Main.pushModal(c);
// Main.pushModal(d);
//
// then we have the stack:
// [{ prevFocus: a, actor: b },
// { prevFocus: b, actor: c },
// { prevFocus: c, actor: d }]
//
// When actor c is destroyed/popped, if we only simply remove the
// record, then the focus stack will be [a, c], rather than the correct
// [a, b]. Shift the focus stack up before removing the record to ensure
// that we get the correct result.
let t = modalActorFocusStack[modalActorFocusStack.length - 1];
if (t.prevFocus)
t.prevFocus.disconnect(t.prevFocusDestroyId);
if (t.focus)
t.focus.disconnect(t.focusDestroyId);
// Remove from the middle, shift the focus chain up
for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
modalActorFocusStack[i].prevFocus = modalActorFocusStack[i - 1].prevFocus;
modalActorFocusStack[i].prevFocusDestroyId = modalActorFocusStack[i - 1].prevFocusDestroyId;
modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
modalActorFocusStack[i].keybindingMode = modalActorFocusStack[i - 1].keybindingMode;
}
}
@@ -610,7 +623,7 @@ function popModal(actor, timestamp) {
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
Meta.enable_unredirect_for_screen(global.screen);
keybindingMode = Shell.KeyBindingMode.NORMAL;
keybindingMode = KeybindingMode.NORMAL;
}
function createLookingGlass() {

View File

@@ -18,7 +18,6 @@ const BoxPointer = imports.ui.boxpointer;
const CtrlAltTab = imports.ui.ctrlAltTab;
const GnomeSession = imports.misc.gnomeSession;
const GrabHelper = imports.ui.grabHelper;
const Hash = imports.misc.hash;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const PointerWatcher = imports.ui.pointerWatcher;
@@ -244,36 +243,6 @@ function makeCloseButton() {
return closeButton;
}
function strHasSuffix(string, suffix) {
return string.substr(-suffix.length) == suffix;
}
// NotificationPolicy:
// An object that holds all bits of configurable policy related to a notification
// source, such as whether to play sound or honour the critical bit.
//
// A notification without a policy object will inherit the default one.
const NotificationPolicy = new Lang.Class({
Name: 'NotificationPolicy',
_init: function(params) {
params = Params.parse(params, { enable: true,
enableSound: true,
showBanners: true,
forceExpanded: false,
showInLockScreen: true,
detailsInLockScreen: false
});
Lang.copyProperties(params, this);
},
// Do nothing for the default policy. These methods are only useful for the
// GSettings policy.
store: function() { },
destroy: function() { }
});
Signals.addSignalMethods(NotificationPolicy.prototype);
// Notification:
// @source: the notification's Source
// @title: the title
@@ -345,7 +314,6 @@ const Notification = new Lang.Class({
this.resident = false;
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
this.isTransient = false;
this.isMusic = false;
this.forFeedback = false;
this.expanded = false;
this.focused = false;
@@ -353,8 +321,8 @@ const Notification = new Lang.Class({
this._destroyed = false;
this._useActionIcons = false;
this._customContent = false;
this.bannerBodyText = null;
this.bannerBodyMarkup = false;
this._bannerBodyText = null;
this._bannerBodyMarkup = false;
this._titleFitsInBannerMode = true;
this._titleDirection = Clutter.TextDirection.DEFAULT;
this._spacing = 0;
@@ -461,7 +429,7 @@ const Notification = new Lang.Class({
this._actionArea = null;
this._buttonBox = null;
}
if (params.clear)
if (this._imageBin && params.clear)
this.unsetImage();
if (!this._scrollArea && !this._actionArea && !this._imageBin)
@@ -506,12 +474,12 @@ const Notification = new Lang.Class({
// is done correctly automatically.
this._table.set_text_direction(this._titleDirection);
// Unless the notification has custom content, we save this.bannerBodyText
// Unless the notification has custom content, we save this._bannerBodyText
// to add it to the content of the notification if the notification is
// expandable due to other elements in its content area or due to the banner
// not fitting fully in the single-line mode.
this.bannerBodyText = this._customContent ? null : banner;
this.bannerBodyMarkup = params.bannerMarkup;
this._bannerBodyText = this._customContent ? null : banner;
this._bannerBodyMarkup = params.bannerMarkup;
banner = banner ? banner.replace(/\n/g, ' ') : '';
@@ -519,7 +487,7 @@ const Notification = new Lang.Class({
this._bannerLabel.queue_relayout();
// Add the bannerBody now if we know for sure we'll need it
if (this.bannerBodyText && this.bannerBodyText.indexOf('\n') > -1)
if (this._bannerBodyText && this._bannerBodyText.indexOf('\n') > -1)
this._addBannerBody();
if (params.body)
@@ -543,8 +511,7 @@ const Notification = new Lang.Class({
this._table.add_style_class_name('multi-line-notification');
this._scrollArea = new St.ScrollView({ style_class: 'notification-scrollview',
vscrollbar_policy: this._scrollPolicy,
hscrollbar_policy: Gtk.PolicyType.NEVER,
visible: this.expanded });
hscrollbar_policy: Gtk.PolicyType.NEVER });
this._table.add(this._scrollArea, { row: 1,
col: 2 });
this._updateLastColumnSettings();
@@ -585,10 +552,10 @@ const Notification = new Lang.Class({
},
_addBannerBody: function() {
if (this.bannerBodyText) {
let text = this.bannerBodyText;
this.bannerBodyText = null;
this.addBody(text, this.bannerBodyMarkup);
if (this._bannerBodyText) {
let text = this._bannerBodyText;
this._bannerBodyText = null;
this.addBody(text, this._bannerBodyMarkup);
}
},
@@ -620,7 +587,6 @@ const Notification = new Lang.Class({
this._addBannerBody();
}
this._actionArea = actor;
this._actionArea.visible = this.expanded;
if (!props)
props = {};
@@ -643,15 +609,11 @@ const Notification = new Lang.Class({
},
setImage: function(image) {
this.unsetImage();
if (!image)
return;
this._imageBin = new St.Bin({ opacity: 230,
child: image,
visible: this.expanded });
if (this._imageBin)
this.unsetImage();
this._imageBin = new St.Bin();
this._imageBin.child = image;
this._imageBin.opacity = 230;
this._table.add_style_class_name('multi-line-notification');
this._table.add_style_class_name('notification-with-image');
this._addBannerBody();
@@ -701,10 +663,9 @@ const Notification = new Lang.Class({
let button = new St.Button({ can_focus: true });
button._actionId = id;
let iconName = strHasSuffix(id, '-symbolic') ? id : id + '-symbolic';
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(id)) {
button.add_style_class_name('notification-icon-button');
button.child = new St.Icon({ icon_name: iconName });
button.child = new St.Icon({ icon_name: id });
} else {
button.add_style_class_name('notification-button');
button.label = label;
@@ -880,7 +841,7 @@ const Notification = new Lang.Class({
},
_canExpandContent: function() {
return this.bannerBodyText ||
return this._bannerBodyText ||
(!this._titleFitsInBannerMode && !this._table.has_style_class_name('multi-line-notification'));
},
@@ -893,14 +854,6 @@ const Notification = new Lang.Class({
this.expanded = true;
this.actor.remove_style_class_name('notification-unexpanded');
// Show additional content that we keep hidden in banner mode
if (this._imageBin)
this._imageBin.show();
if (this._actionArea)
this._actionArea.show();
if (this._scrollArea)
this._scrollArea.show();
// The banner is never shown when the title did not fit, so this
// can be an if-else statement.
if (!this._titleFitsInBannerMode) {
@@ -932,23 +885,12 @@ const Notification = new Lang.Class({
if (this._destroyed)
return;
this.expanded = false;
// Hide additional content that we keep hidden in banner mode
if (this._imageBin)
this._imageBin.hide();
if (this._actionArea)
this._actionArea.hide();
if (this._scrollArea)
this._scrollArea.hide();
// Make sure we don't line wrap the title, and ellipsize it instead.
this._titleLabel.clutter_text.line_wrap = false;
this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.END;
// Restore banner opacity in case the notification is shown in the
// banner mode again on update.
this._bannerLabel.opacity = 255;
// Restore height requisition
this.actor.add_style_class_name('notification-unexpanded');
this.emit('collapsed');
@@ -1116,11 +1058,10 @@ const Source = new Lang.Class({
this.isTransient = false;
this.isChat = false;
this.isMuted = false;
this.showInLockScreen = true;
this.keepTrayOnSummaryClick = false;
this.notifications = [];
this.policy = this._createPolicy();
},
get count() {
@@ -1139,10 +1080,6 @@ const Source = new Lang.Class({
this.emit('count-updated');
},
_createPolicy: function() {
return new NotificationPolicy();
},
buildRightClickMenu: function() {
let item;
let rightClickMenu = new St.BoxLayout({ name: 'summary-right-click-menu',
@@ -1232,13 +1169,11 @@ const Source = new Lang.Class({
notify: function(notification) {
notification.acknowledged = false;
this.pushNotification(notification);
if (!this.isMuted && this.policy.showBanners)
this.emit('notify', notification);
if (!this.isMuted)
this.emit('notify', notification);
},
destroy: function(reason) {
this.policy.destroy();
this.emit('destroy', reason);
},
@@ -1280,16 +1215,7 @@ const Source = new Lang.Class({
hasResidentNotification: function() {
return this.notifications.some(function(n) { return n.resident; });
},
getMusicNotification: function() {
for (let i = 0; i < this.notifications.length; i++) {
if (this.notifications[i].isMusic)
return this.notifications[i];
}
return null;
},
}
});
Signals.addSignalMethods(Source.prototype);
@@ -1343,14 +1269,6 @@ const SummaryItem = new Lang.Class({
global.focus_manager.add_group(this.rightClickMenu);
},
destroy: function() {
// remove the actor from the summary item so it doesn't get destroyed
// with us
this._sourceBox.remove_actor(this._sourceIcon);
this.actor.destroy();
},
_onKeyPress: function(actor, event) {
if (event.get_key_symbol() == Clutter.KEY_Up) {
actor.emit('clicked', 1);
@@ -1535,7 +1453,7 @@ const MessageTray = new Lang.Class({
this.idleMonitor = new GnomeDesktop.IdleMonitor();
this._grabHelper = new GrabHelper.GrabHelper(this.actor,
{ keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY });
{ keybindingMode: Main.KeybindingMode.MESSAGE_TRAY });
this._grabHelper.addActor(this._summaryBoxPointer.actor);
this._grabHelper.addActor(this.actor);
if (Main.panel.statusArea.activities)
@@ -1595,6 +1513,7 @@ const MessageTray = new Lang.Class({
function() {
this._overviewVisible = false;
this._escapeTray();
this.actor.remove_style_pseudo_class('overview');
this._updateState();
}));
@@ -1603,19 +1522,19 @@ const MessageTray = new Lang.Class({
Main.wm.addKeybinding('toggle-message-tray',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.MESSAGE_TRAY |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.MESSAGE_TRAY |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this.toggleAndNavigate));
Main.wm.addKeybinding('focus-active-notification',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.MESSAGE_TRAY |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.MESSAGE_TRAY |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._expandActiveNotification));
this._sources = new Hash.Map();
this._summaryItems = [];
this._chatSummaryItemsCount = 0;
let pointerWatcher = PointerWatcher.getPointerWatcher();
@@ -1625,19 +1544,22 @@ const MessageTray = new Lang.Class({
this._trayDwellUserTime = 0;
this._sessionUpdated();
this._noMessages = new St.Label({ text: _("No Messages"),
style_class: 'no-messages-label',
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this.actor.add_actor(this._noMessages);
this._updateNoMessagesLabel();
},
_updateNoMessagesLabel: function() {
this._noMessages.visible = this._sources.size() == 0;
if (this._summaryItems.length == 0 && !this._noMessages) {
this._noMessages = new St.Label({ text: _("No Messages"),
style_class: 'no-messages-label',
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this.actor.add_actor(this._noMessages);
} else if (this._summaryItems.length > 0 && this._noMessages) {
this._noMessages.destroy();
this._noMessages = null;
}
},
_sessionUpdated: function() {
@@ -1706,7 +1628,10 @@ const MessageTray = new Lang.Class({
},
_onNotificationKeyRelease: function(actor, event) {
if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) {
let ignoredModifiers = global.display.get_ignored_modifier_mask();
let modifierState = event.get_state() & ~ignoredModifiers;
if (event.get_key_symbol() == Clutter.KEY_Escape && modifierState == 0) {
this._closeNotification();
return true;
}
@@ -1724,7 +1649,15 @@ const MessageTray = new Lang.Class({
},
contains: function(source) {
return this._sources.has(source);
return this._getIndexOfSummaryItemForSource(source) >= 0;
},
_getIndexOfSummaryItemForSource: function(source) {
for (let i = 0; i < this._summaryItems.length; i++) {
if (this._summaryItems[i].source == source)
return i;
}
return -1;
},
add: function(source) {
@@ -1733,23 +1666,7 @@ const MessageTray = new Lang.Class({
return;
}
// Register that we got a notification for this source
source.policy.store();
source.policy.connect('enable-changed', Lang.bind(this, this._onSourceEnableChanged, source));
source.policy.connect('policy-changed', Lang.bind(this, this._updateState));
this._onSourceEnableChanged(source.policy, source);
},
_addSource: function(source) {
let obj = {
source: source,
summaryItem: new SummaryItem(source),
notifyId: 0,
destroyId: 0,
mutedChangedId: 0
};
let summaryItem = obj.summaryItem;
let summaryItem = new SummaryItem(source);
if (source.isChat) {
this._summary.insert_child_at_index(summaryItem.actor, 0);
@@ -1758,11 +1675,11 @@ const MessageTray = new Lang.Class({
this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount);
}
this._sources.set(source, obj);
this._summaryItems.push(summaryItem);
obj.notifyId = source.connect('notify', Lang.bind(this, this._onNotify));
obj.destroyId = source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
obj.mutedChangedId = source.connect('muted-changed', Lang.bind(this,
source.connect('notify', Lang.bind(this, this._onNotify));
source.connect('muted-changed', Lang.bind(this,
function () {
if (source.isMuted)
this._notificationQueue = this._notificationQueue.filter(function(notification) {
@@ -1781,28 +1698,35 @@ const MessageTray = new Lang.Class({
this._onSummaryItemClicked(summaryItem, 3);
}));
source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
// We need to display the newly-added summary item, but if the
// caller is about to post a notification, we want to show that
// *first* and not show the summary item until after it hides.
// So postpone calling _updateState() a tiny bit.
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateState(); return false; }));
this.emit('source-added', source);
this.emit('summary-item-added', summaryItem);
this._updateNoMessagesLabel();
},
_removeSource: function(source) {
let [, obj] = this._sources.delete(source);
let summaryItem = obj.summaryItem;
getSummaryItems: function() {
return this._summaryItems;
},
_onSourceDestroy: function(source) {
let index = this._getIndexOfSummaryItemForSource(source);
if (index == -1)
return;
let summaryItemToRemove = this._summaryItems[index];
this._summaryItems.splice(index, 1);
if (source.isChat)
this._chatSummaryItemsCount--;
source.disconnect(obj.notifyId);
source.disconnect(obj.destroyId);
source.disconnect(obj.mutedChangedId);
let needUpdate = false;
if (this._notification && this._notification.source == source) {
@@ -1810,12 +1734,12 @@ const MessageTray = new Lang.Class({
this._notificationRemoved = true;
needUpdate = true;
}
if (this._clickedSummaryItem == summaryItem) {
if (this._clickedSummaryItem == summaryItemToRemove) {
this._setClickedSummaryItem(null);
needUpdate = true;
}
summaryItem.destroy();
summaryItemToRemove.actor.destroy();
this._updateNoMessagesLabel();
@@ -1823,26 +1747,6 @@ const MessageTray = new Lang.Class({
this._updateState();
},
getSources: function() {
return this._sources.keys();
},
_onSourceEnableChanged: function(policy, source) {
let wasEnabled = this.contains(source);
let shouldBeEnabled = policy.enable;
if (wasEnabled != shouldBeEnabled) {
if (shouldBeEnabled)
this._addSource(source);
else
this._removeSource(source);
}
},
_onSourceDestroy: function(source) {
this._removeSource(source);
},
_onNotificationDestroy: function(notification) {
if (this._notification == notification && (this._notificationState == State.SHOWN || this._notificationState == State.SHOWING)) {
this._updateNotificationTimeout(0);
@@ -1928,7 +1832,7 @@ const MessageTray = new Lang.Class({
},
_onSummaryItemClicked: function(summaryItem, button) {
if (summaryItem.source.handleSummaryClick(button)) {
if (summaryItem.source.handleSummaryClick()) {
if (summaryItem.source.keepTrayOnSummaryClick)
this._setClickedSummaryItem(null);
else
@@ -2287,9 +2191,7 @@ const MessageTray = new Lang.Class({
this._tween(this.actor, '_trayState', State.HIDDEN,
{ y: 0,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._onTrayHidden,
onCompleteScope: this
transition: 'easeOutQuad'
});
// Note that we might have entered here without a grab,
@@ -2299,11 +2201,6 @@ const MessageTray = new Lang.Class({
this._lightbox.hide();
},
_onTrayHidden: function() {
if (!this._overviewVisible)
this.actor.remove_style_pseudo_class('overview');
},
_hideDesktopClone: function(now) {
this._tween(this._desktopClone, '_desktopCloneState', State.HIDDEN,
{ y: 0,
@@ -2340,7 +2237,7 @@ const MessageTray = new Lang.Class({
this._notificationClickedId = this._notification.connect('done-displaying',
Lang.bind(this, this._escapeTray));
this._notificationUnfocusedId = this._notification.connect('unfocused', Lang.bind(this, function() {
this._notification.connect('unfocused', Lang.bind(this, function() {
this._updateState();
}));
this._notificationBin.child = this._notification.actor;
@@ -2369,10 +2266,8 @@ const MessageTray = new Lang.Class({
_updateShowingNotification: function() {
this._notification.acknowledged = true;
// We auto-expand notifications with CRITICAL urgency, or for which the relevant setting
// is on in the control center.
if (this._notification.urgency == Urgency.CRITICAL ||
this._notification.source.policy.forceExpanded)
// We auto-expand notifications with CRITICAL urgency.
if (this._notification.urgency == Urgency.CRITICAL)
this._expandNotification(true);
// We tween all notifications to full opacity. This ensures that both new notifications and
@@ -2456,18 +2351,11 @@ const MessageTray = new Lang.Class({
this.idleMonitor.disconnect(this._idleMonitorBecameActiveId);
this._idleMonitorBecameActiveId = 0;
}
if (this._notificationExpandedId) {
this._notification.disconnect(this._notificationExpandedId);
this._notificationExpandedId = 0;
}
if (this._notificationClickedId) {
this._notification.disconnect(this._notificationClickedId);
this._notificationClickedId = 0;
}
if (this._notificationUnfocusedId) {
this._notification.disconnect(this._notificationUnfocusedId);
this._notificationUnfocusedId = 0;
}
if (this._notificationRemoved) {
Tweener.removeTweens(this._notificationWidget);
@@ -2489,19 +2377,19 @@ const MessageTray = new Lang.Class({
},
_hideNotificationCompleted: function() {
this._notification.collapseCompleted();
let notification = this._notification;
this._notification = null;
if (notification.isTransient)
notification.destroy(NotificationDestroyedReason.EXPIRED);
this._notificationRemoved = false;
this._notificationWidget.hide();
this._closeButton.hide();
this._pointerInTray = false;
this.actor.hover = false; // Clutter doesn't emit notify::hover when actors move
this._notificationBin.child = null;
this._notificationWidget.hide();
this._notification.collapseCompleted();
this._notification.disconnect(this._notificationClickedId);
this._notificationClickedId = 0;
let notification = this._notification;
this._notification = null;
if (notification.isTransient)
notification.destroy(NotificationDestroyedReason.EXPIRED);
},
_expandActiveNotification: function() {
@@ -2689,20 +2577,6 @@ const MessageTray = new Lang.Class({
_onSummaryBoxPointerUngrabbed: function() {
this._summaryBoxPointerState = State.HIDING;
if (this._summaryBoxPointerContentUpdatedId) {
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
this._summaryBoxPointerContentUpdatedId = 0;
}
if (this._summaryBoxPointerCloseClickedId != 0) {
this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
this._summaryBoxPointerCloseClickedId = 0;
}
if (this._sourceDoneDisplayingId) {
this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
this._sourceDoneDisplayingId = 0;
}
this._unlock();
if (this._summaryBoxPointerItem.source.notifications.length == 0) {
@@ -2725,6 +2599,14 @@ const MessageTray = new Lang.Class({
this._summaryBoxPointerState = State.HIDDEN;
this._summaryBoxPointer.bin.child = null;
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
this._summaryBoxPointerContentUpdatedId = 0;
if (this._summaryBoxPointerCloseClickedId != 0) {
this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
this._summaryBoxPointerCloseClickedId = 0;
}
this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
this._summaryBoxPointerDoneDisplayingId = 0;
let sourceNotificationStackDoneShowing = null;
if (doneShowingNotificationStack) {

View File

@@ -37,7 +37,7 @@ const ModalDialog = new Lang.Class({
params = Params.parse(params, { shellReactive: false,
styleClass: null,
parentActor: Main.uiGroup,
keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
keybindingMode: Main.KeybindingMode.SYSTEM_MODAL,
shouldFadeIn: true });
this.state = State.CLOSED;
@@ -96,7 +96,8 @@ const ModalDialog = new Lang.Class({
y_align: St.Align.START });
this.buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
vertical: false });
visible: false,
vertical: false });
this.dialogLayout.add(this.buttonLayout,
{ expand: true,
x_align: St.Align.MIDDLE,
@@ -119,6 +120,7 @@ const ModalDialog = new Lang.Class({
setButtons: function(buttons) {
this.clearButtons();
this.buttonLayout.visible = (buttons.length > 0);
for (let i = 0; i < buttons.length; i++) {
let buttonInfo = buttons[i];
@@ -157,7 +159,6 @@ const ModalDialog = new Lang.Class({
keys = [];
let button = new St.Button({ style_class: 'modal-dialog-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
label: label });

View File

@@ -103,126 +103,6 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'ibus-ui-gtk': 'keyboard'
};
const NotificationGenericPolicy = new Lang.Class({
Name: 'NotificationGenericPolicy',
Extends: MessageTray.NotificationPolicy,
_init: function() {
// Don't chain to parent, it would try setting
// our properties to the defaults
this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
},
store: function() { },
destroy: function() {
this._masterSettings.run_dispose();
},
_changed: function(settings, key) {
this.emit('policy-changed', key);
},
get enable() {
return true;
},
get enableSound() {
return true;
},
get showBanners() {
return this._masterSettings.get_boolean('show-banners');
},
get forceExpanded() {
return false;
},
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen');
},
get detailsInLockScreen() {
return false;
}
});
const NotificationApplicationPolicy = new Lang.Class({
Name: 'NotificationApplicationPolicy',
Extends: MessageTray.NotificationPolicy,
_init: function(id) {
// Don't chain to parent, it would try setting
// our properties to the defaults
this.id = id;
this._canonicalId = this._canonicalizeId(id)
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
this._settings.connect('changed', Lang.bind(this, this._changed));
},
store: function() {
this._settings.set_string('application-id', this.id + '.desktop');
let apps = this._masterSettings.get_strv('application-children');
if (apps.indexOf(this._canonicalId) < 0) {
apps.push(this._canonicalId);
this._masterSettings.set_strv('application-children', apps);
}
},
destroy: function() {
this._masterSettings.run_dispose();
this._settings.run_dispose();
},
_changed: function(settings, key) {
this.emit('policy-changed', key);
},
_canonicalizeId: function(id) {
// Keys are restricted to lowercase alphanumeric characters and dash,
// and two dashes cannot be in succession
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
},
get enable() {
return this._settings.get_boolean('enable');
},
get enableSound() {
return this._settings.get_boolean('enable-sound-alerts');
},
get showBanners() {
return this._masterSettings.get_boolean('show-banners') &&
this._settings.get_boolean('show-banners');
},
get forceExpanded() {
return this._settings.get_boolean('force-expanded');
},
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen') &&
this._settings.get_boolean('show-in-lock-screen');
},
get detailsInLockScreen() {
return this._settings.get_boolean('details-in-lock-screen');
}
});
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
@@ -247,42 +127,42 @@ const NotificationDaemon = new Lang.Class({
this._trayManager.manage_stage(global.stage, Main.messageTray.actor);
},
_imageForNotificationData: function(hints) {
if (hints['image-data']) {
_iconForNotificationData: function(icon, hints) {
// If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
// and don't show a large image. There are currently many applications that use
// notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
// the 'image-data' hint. These applications don't typically pass in 'app_icon'
// argument to Notify() and actually expect the pixbuf to be shown as an icon.
// So the logic here does the right thing for this case. If both an icon and either
// one of 'image-data' or 'image-path' are specified, we show both an icon and
// a large image.
if (icon) {
if (icon.substr(0, 7) == 'file://')
return new Gio.FileIcon({ file: Gio.File.new_for_uri(icon) });
else if (icon[0] == '/') {
return new Gio.FileIcon({ file: Gio.File.new_for_path(icon) });
} else
return new Gio.ThemedIcon({ name: icon });
} else if (hints['image-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = hints['image-data'];
return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
} else if (hints['image-path']) {
return new Gio.FileIcon({ file: Gio.File.new_for_path(hints['image-path']) });
} else {
let stockIcon;
switch (hints.urgency) {
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'gtk-dialog-info';
break;
case Urgency.CRITICAL:
stockIcon = 'gtk-dialog-error';
break;
}
return new Gio.ThemedIcon({ name: stockIcon });
}
return null;
},
_fallbackIconForNotificationData: function(hints) {
let stockIcon;
switch (hints.urgency) {
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'gtk-dialog-info';
break;
case Urgency.CRITICAL:
stockIcon = 'gtk-dialog-error';
break;
}
return new Gio.ThemedIcon({ name: stockIcon });
},
_iconForNotificationData: function(icon) {
if (icon) {
if (icon.substr(0, 7) == 'file://')
return new Gio.FileIcon({ file: Gio.File.new_for_uri(icon) });
else if (icon[0] == '/')
return new Gio.FileIcon({ file: Gio.File.new_for_path(icon) });
else
return new Gio.ThemedIcon({ name: icon });
}
return null;
},
_lookupSource: function(title, pid, trayIcon) {
@@ -333,7 +213,7 @@ const NotificationDaemon = new Lang.Class({
}
}
let source = new Source(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
let source = new Source(title, pid, sender, trayIcon);
source.setTransient(isForTransientNotification);
if (!isForTransientNotification) {
@@ -475,8 +355,12 @@ const NotificationDaemon = new Lang.Class({
[ndata.id, ndata.icon, ndata.summary, ndata.body,
ndata.actions, ndata.hints, ndata.notification];
let gicon = this._iconForNotificationData(icon, hints);
if (notification == null) {
notification = new MessageTray.Notification(source);
notification = new MessageTray.Notification(source, summary, body,
{ gicon: gicon,
bannerMarkup: true });
ndata.notification = notification;
notification.connect('destroy', Lang.bind(this,
function(n, reason) {
@@ -499,36 +383,29 @@ const NotificationDaemon = new Lang.Class({
function(n, actionId) {
this._emitActionInvoked(ndata.id, actionId);
}));
} else {
notification.update(summary, body, { gicon: gicon,
bannerMarkup: true,
clear: true });
}
// Mark music notifications so they can be shown in the screen shield
notification.isMusic = (ndata.hints['category'] == 'x-gnome.music');
let gicon = this._iconForNotificationData(icon, hints);
let gimage = this._imageForNotificationData(hints);
let image = null;
// If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
// and don't show a large image. There are currently many applications that use
// notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
// the 'image-data' hint. These applications don't typically pass in 'app_icon'
// argument to Notify() and actually expect the pixbuf to be shown as an icon.
// So the logic here does the right thing for this case. If both an icon and either
// one of 'image-data' or 'image-path' are specified, we show both an icon and
// a large image.
if (gicon && gimage)
image = new St.Icon({ gicon: gimage,
icon_size: notification.IMAGE_SIZE });
else if (!gicon && gimage)
gicon = gimage;
else if (!gicon)
gicon = this._fallbackIconForNotificationData(hints);
notification.update(summary, body, { gicon: gicon,
bannerMarkup: true,
clear: true });
notification.setImage(image);
// We only display a large image if an icon is also specified.
if (icon && (hints['image-data'] || hints['image-path'])) {
let image = null;
if (hints['image-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = hints['image-data'];
image = St.TextureCache.get_default().load_from_raw(data, hasAlpha,
width, height, rowStride, notification.IMAGE_SIZE);
} else if (hints['image-path']) {
image = St.TextureCache.get_default().load_uri_async(GLib.filename_to_uri(hints['image-path'], null),
notification.IMAGE_SIZE,
notification.IMAGE_SIZE);
}
notification.setImage(image);
} else {
notification.unsetImage();
}
if (actions.length) {
notification.setUseActionIcons(hints['action-icons'] == true);
@@ -558,7 +435,7 @@ const NotificationDaemon = new Lang.Class({
// of the 'transient' hint with hints['transient'] rather than hints.transient
notification.setTransient(hints['transient'] == true);
let sourceGIcon = source.useNotificationIcon ? gicon : null;
let sourceGIcon = source.useNotificationIcon ? this._iconForNotificationData(icon, hints) : null;
source.processNotification(notification, sourceGIcon);
},
@@ -638,22 +515,12 @@ const Source = new Lang.Class({
Name: 'NotificationDaemonSource',
Extends: MessageTray.Source,
_init: function(title, pid, sender, trayIcon, appId) {
// Need to set the app before chaining up, so
// methods called from the parent constructor can find it
this.trayIcon = trayIcon;
this.pid = pid;
this.app = this._getApp(appId);
_init: function(title, pid, sender, trayIcon) {
this.parent(title);
this.initialTitle = title;
if (this.app)
this.title = this.app.get_name();
else
this.useNotificationIcon = true;
this.pid = pid;
if (sender)
this._nameWatcherId = Gio.DBus.session.watch_name(sender,
Gio.BusNameWatcherFlags.NONE,
@@ -662,19 +529,16 @@ const Source = new Lang.Class({
else
this._nameWatcherId = 0;
if (this.trayIcon) {
// Try again finding the app, using the WM_CLASS from the tray icon
this._setSummaryIcon(this.trayIcon);
this.useNotificationIcon = false;
}
},
this._setApp();
if (this.app)
this.title = this.app.get_name();
else
this.useNotificationIcon = true;
_createPolicy: function() {
if (this.app) {
let id = this.app.get_id().replace(/\.desktop$/,'');
return new NotificationApplicationPolicy(id);
} else {
return new NotificationGenericPolicy();
this.trayIcon = trayIcon;
if (this.trayIcon) {
this._setSummaryIcon(this.trayIcon);
this.useNotificationIcon = false;
}
},
@@ -701,17 +565,19 @@ const Source = new Lang.Class({
this.notify(notification);
},
handleSummaryClick: function(button) {
handleSummaryClick: function() {
if (!this.trayIcon)
return false;
let event = Clutter.get_current_event();
if (event.type() != Clutter.EventType.BUTTON_RELEASE)
return false;
// Left clicks are passed through only where there aren't unacknowledged
// notifications, so it possible to open them in summary mode; right
// clicks are always forwarded, as the right click menu is not useful for
// tray icons
if (button == 1 &&
if (event.get_button() == 1 &&
this.notifications.length > 0)
return false;
@@ -724,7 +590,7 @@ const Source = new Lang.Class({
return true;
},
_getApp: function(appId) {
_getApp: function() {
let app;
app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
@@ -732,13 +598,7 @@ const Source = new Lang.Class({
return app;
if (this.trayIcon) {
app = Shell.AppSystem.get_default().lookup_wmclass(this.trayIcon.wm_class);
if (app != null)
return app;
}
if (appId) {
app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
app = Shell.AppSystem.get_default().lookup_wmclass(this.trayIcon.wmclass);
if (app != null)
return app;
}
@@ -746,11 +606,11 @@ const Source = new Lang.Class({
return null;
},
_setApp: function(appId) {
_setApp: function() {
if (this.app)
return;
this.app = this._getApp(appId);
this.app = this._getApp();
if (!this.app)
return;

View File

@@ -122,8 +122,7 @@ const Overview = new Lang.Class({
// one. Instances of this class share a single CoglTexture behind the
// scenes which allows us to show the background with different
// rendering options without duplicating the texture data.
this._background = new Meta.BackgroundActor({ screen: global.screen,
settings: Main.background });
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
this._background.add_glsl_snippet(Meta.SnippetHook.FRAGMENT,
GLSL_DIM_EFFECT_DECLARATIONS,
GLSL_DIM_EFFECT_CODE,
@@ -577,7 +576,7 @@ const Overview = new Lang.Class({
if (this._shown) {
if (!this._modal) {
if (Main.pushModal(this._overview,
{ keybindingMode: Shell.KeyBindingMode.OVERVIEW }))
{ keybindingMode: Main.KeybindingMode.OVERVIEW }))
this._modal = true;
else
this.hide();

View File

@@ -315,7 +315,7 @@ const AppMenuButton = new Lang.Class({
},
show: function() {
if (this._visible)
if (this._visible || Main.screenShield.locked)
return;
this._visible = true;
@@ -598,11 +598,6 @@ const AppMenuButton = new Lang.Class({
return;
menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
menu.connect('activate', Lang.bind(this, function() {
let win = this._targetApp.get_windows()[0];
win.check_alive(global.get_current_time());
}));
} else {
if (this.menu.isDummyQuitMenu)
return;
@@ -644,7 +639,7 @@ const ActivitiesButton = new Lang.Class({
this.actor.label_actor = this._label;
this.hotCorner = new Layout.HotCorner(Main.layoutManager);
this.hotCorner = new Layout.HotCorner();
container.add_actor(this.hotCorner.actor);
this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
@@ -751,9 +746,12 @@ const ActivitiesButton = new Lang.Class({
const PanelCorner = new Lang.Class({
Name: 'PanelCorner',
_init: function(side) {
_init: function(box, side) {
this._side = side;
this._box = box;
this._box.connect('style-changed', Lang.bind(this, this._boxStyleChanged));
this.actor = new St.DrawingArea({ style_class: 'panel-corner' });
this.actor.connect('style-changed', Lang.bind(this, this._styleChanged));
this.actor.connect('repaint', Lang.bind(this, this._repaint));
@@ -809,12 +807,12 @@ const PanelCorner = new Lang.Class({
return children[index];
},
setStyleParent: function(box) {
_boxStyleChanged: function() {
let side = this._side;
let rtlAwareContainer = box instanceof St.BoxLayout;
let rtlAwareContainer = this._box instanceof St.BoxLayout;
if (rtlAwareContainer &&
box.get_text_direction() == Clutter.TextDirection.RTL) {
this._box.get_text_direction() == Clutter.TextDirection.RTL) {
if (this._side == St.Side.LEFT)
side = St.Side.RIGHT;
else if (this._side == St.Side.RIGHT)
@@ -823,9 +821,9 @@ const PanelCorner = new Lang.Class({
let button;
if (side == St.Side.LEFT)
button = this._findLeftmostButton(box);
button = this._findLeftmostButton(this._box);
else if (side == St.Side.RIGHT)
button = this._findRightmostButton(box);
button = this._findRightmostButton(this._box);
if (button) {
if (this._button && this._buttonStyleChangedSignalId) {
@@ -852,7 +850,7 @@ const PanelCorner = new Lang.Class({
// The corner doesn't support theme transitions, so override
// the .panel-button default
button.style = 'transition-duration: 0ms';
button.style = 'transition-duration: 0';
}
},
@@ -865,8 +863,8 @@ const PanelCorner = new Lang.Class({
let backgroundColor = node.get_color('-panel-corner-background-color');
let borderColor = node.get_color('-panel-corner-border-color');
let overlap = borderColor.alpha != 0;
let offsetY = overlap ? 0 : borderWidth;
let noOverlap = borderColor.alpha == 0;
let offsetY = noOverlap ? borderWidth : 0;
let cr = this.actor.get_context();
cr.setOperator(Cairo.Operator.SOURCE);
@@ -890,18 +888,17 @@ const PanelCorner = new Lang.Class({
Clutter.cairo_set_source_color(cr, over);
cr.fill();
if (overlap) {
let offset = borderWidth;
Clutter.cairo_set_source_color(cr, backgroundColor);
if (noOverlap)
return;
cr.save();
cr.translate(xOffsetDirection * offset, - offset);
cr.appendPath(savedPath);
cr.fill();
cr.restore();
}
let offset = borderWidth;
Clutter.cairo_set_source_color(cr, backgroundColor);
cr.$dispose();
cr.save();
cr.translate(xOffsetDirection * offset, - offset);
cr.appendPath(savedPath);
cr.fill();
cr.restore();
},
_styleChanged: function() {
@@ -961,10 +958,17 @@ const Panel = new Lang.Class({
this._rightBox = new St.BoxLayout({ name: 'panelRight' });
this.actor.add_actor(this._rightBox);
this._leftCorner = new PanelCorner(St.Side.LEFT);
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
this._leftCorner = new PanelCorner(this._rightBox, St.Side.LEFT);
else
this._leftCorner = new PanelCorner(this._leftBox, St.Side.LEFT);
this.actor.add_actor(this._leftCorner.actor);
this._rightCorner = new PanelCorner(St.Side.RIGHT);
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
this._rightCorner = new PanelCorner(this._leftBox, St.Side.RIGHT);
else
this._rightCorner = new PanelCorner(this._rightBox, St.Side.RIGHT);
this.actor.add_actor(this._rightCorner.actor);
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@@ -1137,13 +1141,17 @@ const Panel = new Lang.Class({
this._sessionStyle = Main.sessionMode.panelStyle;
if (this._sessionStyle)
this._addStyleClassName(this._sessionStyle);
},
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
this._leftCorner.setStyleParent(this._rightBox);
this._rightCorner.setStyleParent(this._leftBox);
} else {
this._leftCorner.setStyleParent(this._leftBox);
this._rightCorner.setStyleParent(this._rightBox);
_initBox: function(elements, box) {
for (let i = 0; i < elements.length; i++) {
let role = elements[i];
let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
if (!constructor) {
// panel icon is not supported (can happen for
// bluetooth or network)
continue;
}
}
},

View File

@@ -244,21 +244,18 @@ const SystemStatusButton = new Lang.Class({
this.setIcon(iconName);
},
get icons() {
return this._box.get_children();
},
addIcon: function(gicon) {
let icon = new St.Icon({ gicon: gicon,
style_class: 'system-status-icon' });
this._box.add_actor(icon);
this.emit('icons-changed');
return icon;
},
setIcon: function(iconName) {
// Need to first add a NULL GIcon and then set icon_name, to ensure
// compatibility with -symbolic fallbacks
if (!this.mainIcon)
this.mainIcon = this.addIcon(null);
this.mainIcon.icon_name = iconName;

View File

@@ -41,10 +41,10 @@ const PointerWatcher = new Lang.Class({
Name: 'PointerWatcher',
_init: function() {
this._idleMonitor = new GnomeDesktop.IdleMonitor();
this._idleMonitor.connect('became-active', Lang.bind(this, this._onIdleMonitorBecameActive));
this._idleMonitor.add_watch(IDLE_TIME, Lang.bind(this, this._onIdleMonitorBecameIdle));
this._idle = this._idleMonitor.get_idletime() > IDLE_TIME;
let idleMonitor = new GnomeDesktop.IdleMonitor();
idleMonitor.connect('became-active', Lang.bind(this, this._onIdleMonitorBecameActive));
idleMonitor.add_watch(IDLE_TIME, Lang.bind(this, this._onIdleMonitorBecameIdle));
this._idle = idleMonitor.get_idletime() > IDLE_TIME;
this._watches = [];
this.pointerX = null;
this.pointerY = null;

View File

@@ -207,7 +207,6 @@ const PopupBaseMenuItem = new Lang.Class({
color.alpha / 255);
cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
cr.fill();
cr.$dispose();
},
// This returns column widths in logical order (i.e. from the dot
@@ -605,7 +604,6 @@ const PopupSliderMenuItem = new Lang.Class({
color.alpha / 255);
cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI);
cr.fill();
cr.$dispose();
},
_startDragging: function(actor, event) {
@@ -638,34 +636,20 @@ const PopupSliderMenuItem = new Lang.Class({
return true;
},
scroll: function(event) {
_onScrollEvent: function (actor, event) {
let direction = event.get_scroll_direction();
let delta;
if (event.is_pointer_emulated())
return;
if (direction == Clutter.ScrollDirection.DOWN) {
delta = -SLIDER_SCROLL_STEP;
} else if (direction == Clutter.ScrollDirection.UP) {
delta = +SLIDER_SCROLL_STEP;
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
let [dx, dy] = event.get_scroll_delta();
// Even though the slider is horizontal, use dy to match
// the UP/DOWN above.
delta = -dy / 10;
this._value = Math.max(0, this._value - SLIDER_SCROLL_STEP);
}
else if (direction == Clutter.ScrollDirection.UP) {
this._value = Math.min(1, this._value + SLIDER_SCROLL_STEP);
}
this._value = Math.min(Math.max(0, this._value + delta), 1);
this._slider.queue_repaint();
this.emit('value-changed', this._value);
},
_onScrollEvent: function(actor, event) {
this.scroll(event);
},
_motionEvent: function(actor, event) {
let absX, absY;
[absX, absY] = event.get_coords();
@@ -889,7 +873,7 @@ const PopupMenuBase = new Lang.Class({
addSettingsAction: function(title, desktopFile) {
let menuItem = this.addAction(title, function() {
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
let app = Shell.AppSystem.get_default().lookup_setting(desktopFile);
if (!app) {
log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');

View File

@@ -1,11 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const FileUtils = imports.misc.fileUtils;
const Search = imports.ui.search;
@@ -137,12 +135,8 @@ function remoteProvidersLoaded(loadState) {
idxB = sortOrder.indexOf(appIdB);
// if no provider is found in the order, use alphabetical order
if ((idxA == -1) && (idxB == -1)) {
let nameA = providerA.appInfo.get_name();
let nameB = providerB.appInfo.get_name();
return GLib.utf8_collate(nameA, nameB);
}
if ((idxA == -1) && (idxB == -1))
return GLib.utf8_collate(providerA.title, providerB.title);
if (numSorted > 1) {
// if providerA is the last, it goes after everything
@@ -193,18 +187,18 @@ const RemoteSearchProvider = new Lang.Class({
},
createIcon: function(size, meta) {
let gicon;
if (meta['gicon']) {
gicon = Gio.icon_new_for_string(meta['gicon']);
return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
icon_size: size });
} else if (meta['icon-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = meta['icon-data'];
gicon = Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
let textureCache = St.TextureCache.get_default();
return textureCache.load_from_raw(data, hasAlpha,
width, height, rowStride, size);
}
return new St.Icon({ gicon: gicon,
icon_size: size });
return null;
},
_getResultsFinished: function(results, error) {
@@ -221,7 +215,7 @@ const RemoteSearchProvider = new Lang.Class({
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString()));
log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
this.searchSystem.pushResults(this, []);
}
},
@@ -234,7 +228,7 @@ const RemoteSearchProvider = new Lang.Class({
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString()));
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
this.searchSystem.pushResults(this, []);
}
},
@@ -265,7 +259,7 @@ const RemoteSearchProvider = new Lang.Class({
Lang.bind(this, this._getResultMetasFinished, callback),
this._cancellable);
} catch(e) {
log('Error calling GetResultMetas for provider %s: %s'.format(this.id, e.toString()));
log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
callback([]);
}
},

View File

@@ -8,13 +8,11 @@ const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const TweenerEquations = imports.tweener.equations;
const GnomeSession = imports.misc.gnomeSession;
const Hash = imports.misc.hash;
const Layout = imports.ui.layout;
const LoginManager = imports.misc.loginManager;
const Lightbox = imports.ui.lightbox;
@@ -27,7 +25,6 @@ const Util = imports.misc.util;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
const LOCK_DELAY_KEY = 'lock-delay';
const CURTAIN_SLIDE_TIME = 0.3;
// fraction of screen height the arrow must reach before completing
@@ -52,16 +49,36 @@ const SUMMARY_ICON_SIZE = 48;
const STANDARD_FADE_TIME = 10;
const SHORT_FADE_TIME = 0.3;
const GLSL_EFFECT_DECLARATIONS = ' \
uniform float desaturation; \n \
function sample(offx, offy) {
return 'texel += texture2D (sampler, tex_coord.st + pixel_step * ' +
'vec2 (' + offx + ',' + offy + '));\n'
}
const GLSL_BLUR_EFFECT_DECLARATIONS = ' \
uniform vec2 pixel_step;\n \
uniform float desaturation;\n \
vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
vec4 texel;\n \
texel = texture2D (sampler, tex_coord.st);\n'
+ sample(-1.0, -1.0)
+ sample( 0.0, -1.0)
+ sample(+1.0, -1.0)
+ sample(-1.0, 0.0)
+ sample(+1.0, 0.0)
+ sample(-1.0, +1.0)
+ sample( 0.0, +1.0)
+ sample(+1.0, +1.0) + ' \
texel /= 9.0;\n \
return texel;\n \
}\n \
vec3 desaturate (const vec3 color)\n \
{\n \
const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n \
vec3 gray = vec3 (dot (gray_conv, color));\n \
return vec3 (mix (color.rgb, gray, desaturation));\n \
}';
const GLSL_EFFECT_CODE = ' \
cogl_color_out.rgb = desaturate(cogl_color_out.rgb);\n';
const GLSL_BLUR_EFFECT_CODE = ' \
cogl_texel = apply_blur(cogl_sampler, cogl_tex_coord.st);\n \
cogl_texel.rgb = desaturate(cogl_texel.rgb);\n';
const Clock = new Lang.Class({
@@ -109,48 +126,49 @@ const NotificationsBox = new Lang.Class({
name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-box' });
this._musicBin = new St.Bin({ style_class: 'screen-shield-notifications-box',
visible: false });
this._residentNotificationBox = new St.BoxLayout({ vertical: true,
style_class: 'screen-shield-notifications-box' });
let scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START });
this._notificationBox = new St.BoxLayout({ vertical: true,
style_class: 'screen-shield-notifications-box' });
scrollView.add_actor(this._notificationBox);
this._persistentNotificationBox = new St.BoxLayout({ vertical: true,
style_class: 'screen-shield-notifications-box' });
scrollView.add_actor(this._persistentNotificationBox);
this.actor.add(this._musicBin);
this.actor.add(this._residentNotificationBox, { x_fill: true });
this.actor.add(scrollView, { x_fill: true, x_align: St.Align.START });
this._sources = new Hash.Map();
Main.messageTray.getSources().forEach(Lang.bind(this, function(source) {
this._sourceAdded(Main.messageTray, source, true);
this._items = [];
Main.messageTray.getSummaryItems().forEach(Lang.bind(this, function(item) {
this._summaryItemAdded(Main.messageTray, item, true);
}));
this._updateVisibility();
this._sourceAddedId = Main.messageTray.connect('source-added', Lang.bind(this, this._sourceAdded));
this._summaryAddedId = Main.messageTray.connect('summary-item-added', Lang.bind(this, this._summaryItemAdded));
},
destroy: function() {
if (this._sourceAddedId) {
Main.messageTray.disconnect(this._sourceAddedId);
this._sourceAddedId = 0;
if (this._summaryAddedId) {
Main.messageTray.disconnect(this._summaryAddedId);
this._summaryAddedId = 0;
}
let items = this._sources.items();
for (let i = 0; i < items.length; i++) {
let [source, obj] = items[i];
this._removeSource(source, obj);
}
for (let i = 0; i < this._items.length; i++)
this._removeItem(this._items[i]);
this._items = [];
this.actor.destroy();
},
_updateVisibility: function() {
this._musicBin.visible = this._musicBin.child != null && this._musicBin.child.visible;
this._notificationBox.visible = this._notificationBox.get_children().some(function(a) {
this._residentNotificationBox.visible = this._residentNotificationBox.get_n_children() > 0;
this._persistentNotificationBox.visible = this._persistentNotificationBox.get_children().some(function(a) {
return a.visible;
});
this.actor.visible = this._musicBin.visible || this._notificationBox.visible;
this.actor.visible = this._residentNotificationBox.visible || this._persistentNotificationBox.visible;
},
_sourceIsResident: function(source) {
return source.hasResidentNotification() && !source.isChat;
},
_makeNotificationCountText: function(count, isChat) {
@@ -160,16 +178,18 @@ const NotificationsBox = new Lang.Class({
return ngettext("%d new notification", "%d new notifications", count).format(count);
},
_makeNotificationSource: function(source, box) {
_makeNotificationSource: function(source) {
let box = new St.BoxLayout({ style_class: 'screen-shield-notification-source' });
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
box.add(sourceActor.actor, { y_fill: true });
let textBox = new St.BoxLayout({ vertical: true });
box.add(textBox, { y_fill: false, y_align: St.Align.START });
let title = new St.Label({ text: source.title,
let label = new St.Label({ text: source.title,
style_class: 'screen-shield-notification-label' });
textBox.add(title);
textBox.add(label);
let count = source.unseenCount;
let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat),
@@ -177,179 +197,118 @@ const NotificationsBox = new Lang.Class({
textBox.add(countLabel);
box.visible = count != 0;
return [title, countLabel];
return [box, countLabel];
},
_makeNotificationDetailedSource: function(source, box) {
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
box.add(sourceActor.actor, { y_fill: true });
let textBox = new St.BoxLayout({ vertical: true });
box.add(textBox, { y_fill: false, y_align: St.Align.START });
let title = new St.Label({ text: source.title,
style_class: 'screen-shield-notification-label' });
textBox.add(title);
let visible = false;
for (let i = 0; i < source.notifications.length; i++) {
let n = source.notifications[i];
if (n.acknowledged || n.isMusic)
continue;
let body = '';
if (n.bannerBodyText) {
body = n.bannerBodyMarkup ? n.bannerBodyText :
GLib.markup_escape_text(n.bannerBodyMarkup, -1);
}
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
label.clutter_text.set_markup('<b>' + n.title + '</b> ' + body);
textBox.add(label);
visible = true;
}
box.visible = visible;
return [title, null];
},
_showSource: function(source, obj, box) {
let musicNotification = source.getMusicNotification();
if (musicNotification != null &&
this._musicBin.child == null) {
if (musicNotification.actor.get_parent() != null)
musicNotification.actor.get_parent().remove_actor(musicNotification.actor);
this._musicBin.child = musicNotification.actor;
this._musicBin.child.visible = obj.visible;
musicNotification.expand(false /* animate */);
obj.musicNotification = musicNotification;
}
if (obj.detailed) {
[obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
} else {
[obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
}
box.visible = obj.visible &&
(source.unseenCount > (musicNotification ? 1 : 0));
},
_sourceAdded: function(tray, source, dontUpdateVisibility) {
// Ignore transient sources
if (source.isTransient)
_summaryItemAdded: function(tray, item, dontUpdateVisibility) {
// Ignore transient sources, or sources explicitly marked not to show
// in the lock screen
if (item.source.isTransient || !item.source.showInLockScreen)
return;
let obj = {
visible: source.policy.showInLockScreen,
detailed: source.policy.detailsInLockScreen,
item: item,
source: item.source,
resident: this._sourceIsResident(item.source),
contentUpdatedId: 0,
sourceDestroyId: 0,
sourceCountChangedId: 0,
sourceTitleChangedId: 0,
sourceUpdatedId: 0,
musicNotification: null,
sourceBox: null,
titleLabel: null,
countLabel: null,
};
obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source' });
this._showSource(source, obj, obj.sourceBox);
this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
if (obj.resident) {
this._residentNotificationBox.add(item.notificationStackWidget);
item.closeButton.hide();
item.prepareNotificationStackForShowing();
} else {
[obj.sourceBox, obj.countLabel] = this._makeNotificationSource(item.source);
this._persistentNotificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
}
obj.sourceCountChangedId = source.connect('count-updated', Lang.bind(this, function(source) {
this._countChanged(source, obj);
}));
obj.sourceTitleChangedId = source.connect('title-changed', Lang.bind(this, function(source) {
this._titleChanged(source, obj);
}));
obj.policyChangedId = source.policy.connect('policy-changed', Lang.bind(this, function(policy, key) {
if (key == 'show-in-lock-screen')
this._visibleChanged(source, obj);
else
this._detailedChanged(source, obj);
}));
obj.sourceDestroyId = source.connect('destroy', Lang.bind(this, function(source) {
this._onSourceDestroy(source, obj);
}));
this._sources.set(source, obj);
obj.contentUpdatedId = item.connect('content-updated', Lang.bind(this, this._onItemContentUpdated));
obj.sourceCountChangedId = item.source.connect('count-updated', Lang.bind(this, this._onSourceChanged));
obj.sourceTitleChangedId = item.source.connect('title-changed', Lang.bind(this, this._onSourceChanged));
obj.sourceDestroyId = item.source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
this._items.push(obj);
if (!dontUpdateVisibility)
this._updateVisibility();
},
_titleChanged: function(source, obj) {
obj.titleLabel.text = source.title;
_findSource: function(source) {
for (let i = 0; i < this._items.length; i++) {
if (this._items[i].source == source)
return i;
}
return -1;
},
_countChanged: function(source, obj) {
if (obj.detailed) {
// A new notification was pushed, or a previous notification was destroyed.
// Give up, and build the list again.
_onItemContentUpdated: function(item) {
let obj = this._items[this._findSource(item.source)];
this._updateItem(obj);
},
obj.sourceBox.destroy_all_children();
obj.titleLabel = obj.countLabel = null;
this._showSource(source, obj, obj.sourceBox);
_onSourceChanged: function(source) {
let obj = this._items[this._findSource(source)];
this._updateItem(obj);
},
_updateItem: function(obj) {
let itemShouldBeResident = this._sourceIsResident(obj.source);
if (itemShouldBeResident && obj.resident) {
// Nothing to do here, the actor is already updated
return;
}
if (obj.resident && !itemShouldBeResident) {
// make into a regular item
obj.item.doneShowingNotificationStack();
this._residentNotificationBox.remove_actor(obj.item.notificationStackWidget);
[obj.sourceBox, obj.countLabel] = this._makeNotificationSource(obj.source);
this._persistentNotificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
} else if (itemShouldBeResident && !obj.resident) {
// make into a resident item
obj.sourceBox.destroy();
obj.sourceBox = obj.countLabel = null;
obj.resident = true;
this._residentNotificationBox.add(obj.item.notificationStackWidget);
obj.item.closeButton.hide();
obj.item.prepareNotificationStackForShowing();
} else {
let count = source.unseenCount;
obj.countLabel.text = this._makeNotificationCountText(count, source.isChat);
// just update the counter
let count = obj.source.unseenCount;
obj.countLabel.text = this._makeNotificationCountText(count, obj.source.isChat);
obj.sourceBox.visible = count != 0;
}
obj.sourceBox.visible = obj.visible &&
(source.unseenCount > (obj.musicNotification ? 1 : 0));
this._updateVisibility();
},
_visibleChanged: function(source, obj) {
if (obj.visible == source.policy.showInLockScreen)
return;
_onSourceDestroy: function(source) {
let idx = this._findSource(source);
obj.visible = source.policy.showInLockScreen;
if (obj.musicNotification)
obj.musicNotification.actor.visible = obj.visible;
obj.sourceBox.visible = obj.visible &&
source.unseenCount > (obj.musicNotification ? 1 : 0);
this._removeItem(this._items[idx]);
this._items.splice(idx, 1);
this._updateVisibility();
},
_detailedChanged: function(source, obj) {
if (obj.detailed == source.policy.detailsInLockScreen)
return;
obj.detailed = source.policy.detailsInLockScreen;
obj.sourceBox.destroy_all_children();
obj.titleLabel = obj.countLabel = null;
this._showSource(source, obj, obj.sourceBox);
},
_onSourceDestroy: function(source, obj) {
this._removeSource(source, obj);
this._updateVisibility();
},
_removeSource: function(source, obj) {
obj.sourceBox.destroy();
obj.sourceBox = obj.titleLabel = obj.countLabel = null;
if (obj.musicNotification) {
this._musicBin.child = null;
obj.musicNotification = null;
_removeItem: function(obj) {
if (obj.resident) {
obj.item.doneShowingNotificationStack();
this._residentNotificationBox.remove_actor(obj.item.notificationStackWidget);
} else {
obj.sourceBox.destroy();
}
source.disconnect(obj.sourceDestroyId);
source.disconnect(obj.sourceCountChangedId);
source.disconnect(obj.sourceTitleChangedId);
source.policy.disconnect(obj.policyChangedId);
this._sources.delete(source);
obj.item.disconnect(obj.contentUpdatedId);
obj.source.disconnect(obj.sourceDestroyId);
obj.source.disconnect(obj.sourceCountChangedId);
obj.source.disconnect(obj.sourceTitleChangedId);
},
});
@@ -435,7 +394,6 @@ const ScreenShield = new Lang.Class({
reactive: true,
can_focus: true,
name: 'lockScreenGroup',
visible: false,
});
this._lockScreenGroup.connect('key-release-event',
Lang.bind(this, this._onLockScreenKeyRelease));
@@ -447,16 +405,16 @@ const ScreenShield = new Lang.Class({
name: 'lockScreenContents' });
this._lockScreenContents.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
let backgroundActor = new Meta.BackgroundActor({ screen: global.screen,
settings: this._settings });
backgroundActor.add_glsl_snippet(Meta.SnippetHook.FRAGMENT,
GLSL_EFFECT_DECLARATIONS,
GLSL_EFFECT_CODE,
false);
let backgroundActor = Meta.BackgroundActor.new_for_screen(global.screen);
backgroundActor.add_glsl_snippet(Meta.SnippetHook.TEXTURE_LOOKUP,
GLSL_BLUR_EFFECT_DECLARATIONS,
GLSL_BLUR_EFFECT_CODE,
true);
backgroundActor.set_uniform_float('desaturation',
1, 1, [0.6]);
backgroundActor.connect('notify::size', function(actor) {
actor.set_uniform_float('pixel_step', 2, 1, [1/actor.width, 1/actor.height]);
});
this._background = new St.Bin({ style_class: 'screen-shield-background',
child: backgroundActor });
@@ -509,36 +467,25 @@ const ScreenShield = new Lang.Class({
this._loginManager = LoginManager.getLoginManager();
this._loginSession = this._loginManager.getCurrentSessionProxy();
this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); }));
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.deactivate(false); }));
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.unlock(); }));
this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._isModal = false;
this._hasLockScreen = false;
this._isGreeter = false;
this._isActive = false;
this._isLocked = false;
this._inUnlockAnimation = false;
this._activationTime = 0;
this._becameActiveId = 0;
this._lockTimeoutId = 0;
this._lightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true,
fadeInTime: STANDARD_FADE_TIME,
fadeFactor: 1 });
this._lightbox.connect('shown', Lang.bind(this, this._onLightboxShown));
this.idleMonitor = new GnomeDesktop.IdleMonitor();
},
_liftShield: function(onPrimary, velocity) {
if (this._isLocked) {
this._ensureUnlockDialog(onPrimary, true /* allowCancel */);
this._hideLockScreen(true /* animate */, velocity);
} else {
this.deactivate(true /* animate */);
}
},
_onLockScreenKeyRelease: function(actor, event) {
let symbol = event.get_key_symbol();
@@ -556,7 +503,8 @@ const ScreenShield = new Lang.Class({
if (symbol == Clutter.KEY_Escape ||
symbol == Clutter.KEY_Return ||
symbol == Clutter.KEY_KP_Enter) {
this._liftShield(false, 0);
this._ensureUnlockDialog(true, true);
this._hideLockScreen(true, 0);
return true;
}
@@ -578,7 +526,8 @@ const ScreenShield = new Lang.Class({
// 7 standard scrolls to lift up
if (this._lockScreenScrollCounter > 35) {
this._liftShield(true, 0);
this._ensureUnlockDialog(false, true);
this._hideLockScreen(true, 0);
}
return true;
@@ -609,9 +558,7 @@ const ScreenShield = new Lang.Class({
_onDragBegin: function() {
Tweener.removeTweens(this._lockScreenGroup);
this._lockScreenState = MessageTray.State.HIDING;
if (this._isLocked)
this._ensureUnlockDialog(false, false);
this._ensureUnlockDialog(false, false);
return true;
},
@@ -632,7 +579,8 @@ const ScreenShield = new Lang.Class({
if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) {
// Complete motion automatically
let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
this._liftShield(true, -velocityY);
this._hideLockScreen(true, -velocityY);
this._ensureUnlockDialog(false, true);
} else {
// restore the lock screen to its original place
// try to use the same speed as the normal animation
@@ -672,81 +620,35 @@ const ScreenShield = new Lang.Class({
}
if (!this._isModal) {
Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
this._isModal = true;
}
if (this._lightbox.actor.visible ||
this._isActive) {
// We're either shown and active, or in the process of
// showing.
// The latter is a very unlikely condition (it requires
// idle-delay < 20), but in any case we have nothing
// to do at this point: either isActive is true, or
// it will soon be.
// isActive can also be true if the lightbox is hidden,
// in case the shield is down and the user hasn't unlocked yet
return;
}
this._lightbox.show();
if (!this._isActive) {
this._lightbox.show();
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
if (this._becameActiveId == 0)
this._becameActiveId = this.idleMonitor.connect('became-active',
Lang.bind(this, this._onUserBecameActive));
this._becameActiveId = this.idleMonitor.connect('became-active', Lang.bind(this, function() {
this.idleMonitor.disconnect(this._becameActiveId);
let shouldLock = this._settings.get_boolean(LOCK_ENABLED_KEY) && !this._isLocked;
let lightboxWasShown = this._lightbox.shown;
this._lightbox.hide();
if (shouldLock) {
let lockTimeout = Math.max(STANDARD_FADE_TIME, this._settings.get_uint(LOCK_DELAY_KEY));
this._lockTimeoutId = Mainloop.timeout_add(lockTimeout * 1000,
Lang.bind(this, function() {
this._lockTimeoutId = 0;
this.lock(true);
return false;
}));
let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
if (shouldLock || this._isLocked) {
this.lock(false);
} else if (this._isActive) {
this.unlock();
}
}));
this._isActive = true;
this.emit('lock-status-changed');
}
},
_onUserBecameActive: function() {
// This function gets called here when the user becomes active
// after gnome-session changed the status to IDLE
// There are four possibilities here:
// - we're called when already locked; isActive and isLocked are true,
// we just go back to the lock screen curtain
// - we're called before the lightbox is fully shown; at this point
// isActive is false, so we just hide the ligthbox, reset the activationTime
// and go back to the unlocked desktop
// - we're called after showing the lightbox, but before the lock
// delay; this is mostly like the case above, but isActive is true now
// so we need to notify gnome-settings-daemon to go back to the normal
// policies for blanking
// (they're handled by the same code, and we emit one extra ActiveChanged
// signal in the case above)
// - we're called after showing the lightbox and after lock-delay; the
// session is effectivelly locked now, it's time to build and show
// the lock screen
this.idleMonitor.disconnect(this._becameActiveId);
this._becameActiveId = 0;
let lightboxWasShown = this._lightbox.shown;
this._lightbox.hide();
// Shortcircuit in case the mouse was moved before the fade completed
if (!lightboxWasShown) {
this.deactivate(false);
return;
}
},
_onLightboxShown: function() {
this.activate(false);
},
showDialog: function() {
// Ensure that the stage window is mapped, before taking a grab
// otherwise X errors out
@@ -761,7 +663,6 @@ const ScreenShield = new Lang.Class({
this.actor.show();
this._isGreeter = Main.sessionMode.isGreeter;
this._isLocked = true;
this._ensureUnlockDialog(true, true);
this._hideLockScreen(false, 0);
},
@@ -782,9 +683,6 @@ const ScreenShield = new Lang.Class({
},
_hideLockScreen: function(animate, velocity) {
if (this._lockScreenState == MessageTray.State.HIDDEN)
return;
this._lockScreenState = MessageTray.State.HIDING;
if (animate) {
@@ -826,7 +724,7 @@ const ScreenShield = new Lang.Class({
let constructor = Main.sessionMode.unlockDialog;
if (!constructor) {
// This session mode has no locking capabilities
this.deactivate(true);
this.unlock();
return;
}
@@ -836,10 +734,8 @@ const ScreenShield = new Lang.Class({
let time = global.get_current_time();
this._dialog.connect('loaded', Lang.bind(this, function() {
if (!this._dialog.open(time, onPrimary)) {
// This is kind of an impossible error: we're already modal
// by the time we reach this...
log('Could not open login dialog: failed to acquire grab');
this.deactivate(true);
this.unlock();
}
}));
@@ -855,17 +751,10 @@ const ScreenShield = new Lang.Class({
},
_onUnlockSucceded: function() {
this.deactivate(true);
this._tweenUnlocked();
},
_resetLockScreen: function(animateLockScreen, animateLockDialog) {
// Don't reset the lock screen unless it is completely hidden
// This prevents the shield going down if the lock-delay timeout
// fires while the user is dragging (which has the potential
// to confuse our state)
if (this._lockScreenState != MessageTray.State.HIDDEN)
return;
this._ensureLockScreen();
this._lockDialogGroup.scale_x = 1;
this._lockDialogGroup.scale_y = 1;
@@ -932,12 +821,6 @@ const ScreenShield = new Lang.Class({
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenScrollCounter = 0;
let prevIsActive = this._isActive;
this._isActive = true;
if (prevIsActive != this._isActive)
this.emit('active-changed');
this.emit('lock-screen-shown');
},
@@ -959,10 +842,12 @@ const ScreenShield = new Lang.Class({
this._lockScreenContents.add_actor(this._lockScreenContentsBox);
this._notificationsBox = new NotificationsBox();
this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
y_fill: true,
expand: true });
if (this._settings.get_boolean('show-notifications')) {
this._notificationsBox = new NotificationsBox();
this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
y_fill: true,
expand: true });
}
this._hasLockScreen = true;
},
@@ -987,10 +872,6 @@ const ScreenShield = new Lang.Class({
},
get locked() {
return this._isLocked;
},
get active() {
return this._isActive;
},
@@ -998,20 +879,27 @@ const ScreenShield = new Lang.Class({
return this._activationTime;
},
deactivate: function(animate) {
this._hideLockScreen(animate, 0);
_tweenUnlocked: function() {
this._inUnlockAnimation = true;
this.unlock();
Tweener.addTween(this._lockDialogGroup, {
scale_x: 0,
scale_y: 0,
time: animate ? Overview.ANIMATION_TIME : 0,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, this._completeDeactivate),
onComplete: function() {
if (this._dialog) {
this._dialog.destroy();
this._dialog = null;
}
this.actor.hide();
this._inUnlockAnimation = false;
},
onCompleteScope: this
});
},
_completeDeactivate: function() {
unlock: function() {
if (this._hasLockScreen)
this._clearLockScreen();
@@ -1027,31 +915,26 @@ const ScreenShield = new Lang.Class({
this._isModal = false;
}
this.actor.hide();
if (!this._inUnlockAnimation)
this.actor.hide();
if (Main.sessionMode.currentMode == 'lock-screen')
Main.sessionMode.popMode('lock-screen');
if (Main.sessionMode.currentMode == 'unlock-dialog')
Main.sessionMode.popMode('unlock-dialog');
if (this._becameActiveId != 0) {
this.idleMonitor.disconnect(this._becameActiveId);
this._becameActiveId = 0;
}
if (this._lockTimeoutId != 0) {
Mainloop.source_remove(this._lockTimeoutId);
this._lockTimeoutId = 0;
}
this._activationTime = 0;
this._isActive = false;
this._isLocked = false;
this.emit('active-changed');
this.emit('locked-changed');
this.emit('lock-status-changed');
},
activate: function(animate) {
lock: function(animate) {
if (!this._isModal) {
Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
this._isModal = true;
}
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
@@ -1066,28 +949,9 @@ const ScreenShield = new Lang.Class({
this._resetLockScreen(animate, animate);
// We used to set isActive and emit active-changed here,
// but now we do that from lockScreenShown, which means
// there is a 0.3 seconds window during which the lock
// screen is effectively visible and the screen is locked, but
// the DBus interface reports the screensaver is off.
// This is because when we emit ActiveChanged(true),
// gnome-settings-daemon blanks the screen, and we don't want
// blank during the animation.
// This is not a problem for the idle fade case, because we
// activate without animation in that case.
},
lock: function(animate) {
if (!this._isModal) {
Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
this._isModal = true;
}
this._isActive = true;
this._isLocked = true;
this.activate(animate);
this.emit('locked-changed');
this.emit('lock-status-changed');
},
});
Signals.addSignalMethods(ScreenShield.prototype);
@@ -1121,13 +985,13 @@ const ScreenShieldFallback = new Lang.Class({
else
this._locked = false;
this.emit('active-changed', this._locked);
this.emit('lock-status-changed', this._locked);
},
_onSignal: function(proxy, senderName, signalName, params) {
if (signalName == 'ActiveChanged') {
[this._locked] = params.deep_unpack();
this.emit('active-changed', this._locked);
this.emit('lock-status-changed', this._locked);
}
},

View File

@@ -1,272 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const ScreenshotIface = <interface name="org.gnome.Shell.Screenshot">
<method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="ScreenshotWindow">
<arg type="b" direction="in" name="include_frame"/>
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="Screenshot">
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>
<method name="SelectArea">
<arg type="i" direction="out" name="x"/>
<arg type="i" direction="out" name="y"/>
<arg type="i" direction="out" name="width"/>
<arg type="i" direction="out" name="height"/>
</method>
<method name="FlashArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
</method>
</interface>;
const ScreenshotService = new Lang.Class({
Name: 'ScreenshotService',
_init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot');
Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
_onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) {
if (flash && result) {
let flashspot = new Flashspot(area);
flashspot.fire();
}
let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
invocation.return_value(retval);
},
ScreenshotAreaAsync : function (params, invocation) {
let [x, y, width, height, flash, filename, callback] = params;
let screenshot = new Shell.Screenshot();
screenshot.screenshot_area (x, y, width, height, filename,
Lang.bind(this, this._onScreenshotComplete,
flash, invocation));
},
ScreenshotWindowAsync : function (params, invocation) {
let [include_frame, include_cursor, flash, filename] = params;
let screenshot = new Shell.Screenshot();
screenshot.screenshot_window (include_frame, include_cursor, filename,
Lang.bind(this, this._onScreenshotComplete,
flash, invocation));
},
ScreenshotAsync : function (params, invocation) {
let [include_cursor, flash, filename] = params;
let screenshot = new Shell.Screenshot();
screenshot.screenshot(include_cursor, filename,
Lang.bind(this, this._onScreenshotComplete,
flash, invocation));
},
SelectAreaAsync: function (params, invocation) {
let selectArea = new SelectArea();
selectArea.show();
selectArea.connect('finished', Lang.bind(this,
function(selectArea, areaRectangle) {
if (areaRectangle) {
let retval = GLib.Variant.new('(iiii)',
[areaRectangle.x, areaRectangle.y,
areaRectangle.width, areaRectangle.height]);
invocation.return_value(retval);
} else {
invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
"Operation was cancelled");
}
}));
},
FlashArea: function(x, y, width, height) {
let flashspot = new Flashspot({ x : x, y : y, width: width, height: height});
flashspot.fire();
}
});
const SelectArea = new Lang.Class({
Name: 'SelectArea',
_init: function() {
this._startX = -1;
this._startY = -1;
this._lastX = 0;
this._lastY = 0;
this._initRubberbandColors();
this._group = new St.Widget({ visible: false,
reactive: true,
x: 0,
y: 0 });
Main.uiGroup.add_actor(this._group);
this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this._group.connect('button-release-event',
Lang.bind(this, this._onButtonRelease));
this._group.connect('key-press-event',
Lang.bind(this, this._onKeyPress));
this._group.connect('motion-event',
Lang.bind(this, this._onMotionEvent));
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this._group.add_constraint(constraint);
this._rubberband = new Clutter.Rectangle({ color: this._background,
has_border: true,
border_width: 1,
border_color: this._border });
this._group.add_actor(this._rubberband);
},
show: function() {
if (!Main.pushModal(this._group) || this._group.visible)
return;
global.set_cursor(Shell.Cursor.CROSSHAIR);
this._group.visible = true;
},
_initRubberbandColors: function() {
function colorFromRGBA(rgba) {
return new Clutter.Color({ red: rgba.red * 255,
green: rgba.green * 255,
blue: rgba.blue * 255,
alpha: rgba.alpha * 255 });
}
let path = new Gtk.WidgetPath();
path.append_type(Gtk.IconView);
let context = new Gtk.StyleContext();
context.set_path(path);
context.add_class('rubberband');
this._background = colorFromRGBA(context.get_background_color(Gtk.StateFlags.NORMAL));
this._border = colorFromRGBA(context.get_border_color(Gtk.StateFlags.NORMAL));
},
_getGeometry: function() {
return { x: Math.min(this._startX, this._lastX),
y: Math.min(this._startY, this._lastY),
width: Math.abs(this._startX - this._lastX),
height: Math.abs(this._startY - this._lastY) };
},
_onKeyPress: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape)
this._destroy(null, false);
return;
},
_onMotionEvent: function(actor, event) {
if (this._startX == -1 || this._startY == -1)
return false;
[this._lastX, this._lastY] = event.get_coords();
let geometry = this._getGeometry();
this._rubberband.set_position(geometry.x, geometry.y);
this._rubberband.set_size(geometry.width, geometry.height);
return false;
},
_onButtonPress: function(actor, event) {
[this._startX, this._startY] = event.get_coords();
this._rubberband.set_position(this._startX, this._startY);
return false;
},
_onButtonRelease: function(actor, event) {
this._destroy(this._getGeometry(), true);
return false;
},
_destroy: function(geometry, fade) {
Tweener.addTween(this._group,
{ opacity: 0,
time: fade ? 0.2 : 0,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
Main.popModal(this._group);
this._group.destroy();
global.unset_cursor();
this.emit('finished', geometry);
})
});
}
});
Signals.addSignalMethods(SelectArea.prototype);
const FLASHSPOT_ANIMATION_OUT_TIME = 0.5; // seconds
const Flashspot = new Lang.Class({
Name: 'Flashspot',
Extends: Lightbox.Lightbox,
_init: function(area) {
this.parent(Main.uiGroup, { inhibitEvents: true,
width: area.width,
height: area.height });
this.actor.style_class = 'flashspot';
this.actor.set_position(area.x, area.y);
},
fire: function() {
this.actor.show();
this.actor.opacity = 255;
Tweener.addTween(this.actor,
{ opacity: 0,
time: FLASHSPOT_ANIMATION_OUT_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this.destroy();
})
});
}
});

View File

@@ -17,26 +17,6 @@ const Search = imports.ui.search;
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const MaxWidthBin = new Lang.Class({
Name: 'MaxWidthBin',
Extends: St.Bin,
vfunc_allocate: function(box, flags) {
let themeNode = this.get_theme_node();
let maxWidth = themeNode.get_max_width();
let availWidth = box.x2 - box.x1;
let adjustedBox = box;
if (availWidth > maxWidth) {
let excessWidth = availWidth - maxWidth;
adjustedBox.x1 += Math.floor(excessWidth / 2);
adjustedBox.x2 -= Math.floor(excessWidth / 2);
}
this.parent(adjustedBox, flags);
}
});
const SearchResult = new Lang.Class({
Name: 'SearchResult',
@@ -198,7 +178,7 @@ const ListSearchResults = new Lang.Class({
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this.actor.add(this._content, { expand: true });
this.actor.add_actor(this._content);
this._notDisplayedResult = [];
this._terms = [];
@@ -321,19 +301,12 @@ const SearchResults = new Lang.Class({
this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true });
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
x_fill: true,
y_fill: true,
child: this._content });
let scrollChild = new St.BoxLayout();
scrollChild.add(this._contentBin, { expand: true });
this._scrollView = new St.ScrollView({ x_fill: true,
y_fill: false,
style_class: 'vfade' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.add_actor(scrollChild);
this._scrollView.add_actor(this._content);
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this._scrollView.add_action(action);

View File

@@ -30,6 +30,5 @@ const HorizontalSeparator = new Lang.Class({
cr.setSource(pattern);
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
cr.fill();
cr.$dispose();
}
});

View File

@@ -9,8 +9,8 @@ const Config = imports.misc.config;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
const ExtensionUtils = imports.misc.extensionUtils;
const Flashspot = imports.ui.flashspot;
const Main = imports.ui.main;
const Screenshot = imports.ui.screenshot;
const GnomeShellIface = <interface name="org.gnome.Shell">
<method name="Eval">
@@ -18,6 +18,34 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<arg type="b" direction="out" name="success" />
<arg type="s" direction="out" name="result" />
</method>
<method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="ScreenshotWindow">
<arg type="b" direction="in" name="include_frame"/>
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="Screenshot">
<arg type="b" direction="in" name="include_cursor"/>
<arg type="b" direction="in" name="flash"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="FlashArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
</method>
<property name="Mode" type="s" access="read" />
<property name="OverviewActive" type="b" access="readwrite" />
<property name="ShellVersion" type="s" access="read" />
@@ -48,7 +76,6 @@ const GnomeShell = new Lang.Class({
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
this._extensionsSerivce = new GnomeShellExtensions();
this._screenshotService = new Screenshot.ScreenshotService();
},
/**
@@ -84,6 +111,82 @@ const GnomeShell = new Lang.Class({
return [success, returnValue];
},
_onScreenshotComplete: function(obj, result, area, flash, invocation) {
if (flash && result) {
let flashspot = new Flashspot.Flashspot(area);
flashspot.fire();
}
let retval = GLib.Variant.new('(b)', [result]);
invocation.return_value(retval);
},
/**
* ScreenshotArea:
* @x: The X coordinate of the area
* @y: The Y coordinate of the area
* @width: The width of the area
* @height: The height of the area
* @flash: Whether to flash the area or not
* @filename: The filename for the screenshot
*
* Takes a screenshot of the passed in area and saves it
* in @filename as png image, it returns a boolean
* indicating whether the operation was successful or not.
*
*/
ScreenshotAreaAsync : function (params, invocation) {
let [x, y, width, height, flash, filename, callback] = params;
let screenshot = new Shell.Screenshot();
screenshot.screenshot_area (x, y, width, height, filename,
Lang.bind(this, this._onScreenshotComplete,
flash, invocation));
},
/**
* ScreenshotWindow:
* @include_frame: Whether to include the frame or not
* @include_cursor: Whether to include the cursor image or not
* @flash: Whether to flash the window area or not
* @filename: The filename for the screenshot
*
* Takes a screenshot of the focused window (optionally omitting the frame)
* and saves it in @filename as png image, it returns a boolean
* indicating whether the operation was successful or not.
*
*/
ScreenshotWindowAsync : function (params, invocation) {
let [include_frame, include_cursor, flash, filename] = params;
let screenshot = new Shell.Screenshot();
screenshot.screenshot_window (include_frame, include_cursor, filename,
Lang.bind(this, this._onScreenshotComplete,
flash, invocation));
},
/**
* Screenshot:
* @filename: The filename for the screenshot
* @include_cursor: Whether to include the cursor image or not
* @flash: Whether to flash the screen or not
*
* Takes a screenshot of the whole screen and saves it
* in @filename as png image, it returns a boolean
* indicating whether the operation was successful or not.
*
*/
ScreenshotAsync : function (params, invocation) {
let [include_cursor, flash, filename] = params;
let screenshot = new Shell.Screenshot();
screenshot.screenshot(include_cursor, filename,
Lang.bind(this, this._onScreenshotComplete,
flash, invocation));
},
FlashArea: function(x, y, width, height) {
let flashspot = new Flashspot.Flashspot({ x : x, y : y, width: width, height: height});
flashspot.fire();
},
Mode: global.session_mode,
get OverviewActive() {
@@ -247,8 +350,8 @@ const ScreenSaverDBus = new Lang.Class({
this.parent();
this._screenShield = screenShield;
screenShield.connect('active-changed', Lang.bind(this, function(shield) {
this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.active]));
screenShield.connect('lock-status-changed', Lang.bind(this, function(shield) {
this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.locked]));
}));
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this);
@@ -269,13 +372,13 @@ const ScreenSaverDBus = new Lang.Class({
SetActive: function(active) {
if (active)
this._screenShield.activate(true);
this._screenShield.lock(true);
else
this._screenShield.unlock(false);
this._screenShield.unlock();
},
GetActive: function() {
return this._screenShield.active;
return this._screenShield.locked;
},
GetActiveTime: function() {

View File

@@ -9,7 +9,6 @@ const St = imports.gi.St;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@@ -287,7 +286,6 @@ const Indicator = new Lang.Class({
_ensureSource: function() {
if (!this._source) {
this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active');
this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-bluetooth-panel');
Main.messageTray.add(this._source);
}
},
@@ -448,5 +446,10 @@ const PinNotification = new Lang.Class({
return this._entry.clutter_text.text.length == 6;
else
return true;
},
grabFocus: function(lockTray) {
this.parent(lockTray);
global.stage.set_key_focus(this._entry);
}
});

View File

@@ -115,14 +115,9 @@ const IBusManager = new Lang.Class({
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
} catch(e) {
let engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
}
this._engineChanged(this._ibus, engine.get_name());
}));
this._updateReadiness();
@@ -337,14 +332,14 @@ const InputSourceIndicator = new Lang.Class({
Main.wm.addKeybinding('switch-input-source',
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES,
Shell.KeyBindingMode.ALL,
Main.KeybindingMode.ALL,
Lang.bind(this, this._switchInputSource));
this._keybindingActionBackward =
Main.wm.addKeybinding('switch-input-source-backward',
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES |
Meta.KeyBindingFlags.REVERSED,
Shell.KeyBindingMode.ALL,
Main.KeybindingMode.ALL,
Lang.bind(this, this._switchInputSource));
this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
@@ -371,13 +366,6 @@ const InputSourceIndicator = new Lang.Class({
this._sessionUpdated();
this.menu.addSettingsAction(_("Region and Language Settings"), 'gnome-region-panel.desktop');
this._sourcesPerWindow = false;
this._focusWindowNotifyId = 0;
this._overviewShowingId = 0;
this._overviewHiddenId = 0;
this._settings.connect('changed::per-window', Lang.bind(this, this._sourcesPerWindowChanged));
this._sourcesPerWindowChanged();
},
_sessionUpdated: function() {
@@ -443,8 +431,6 @@ const InputSourceIndicator = new Lang.Class({
this._mruSources = currentSource.concat(this._mruSources);
break;
}
this._changePerWindowSource();
},
_inputSourcesChanged: function() {
@@ -484,8 +470,6 @@ const InputSourceIndicator = new Lang.Class({
let is = new InputSource(type, id, displayName, shortName, i);
is.connect('activate', Lang.bind(this, function() {
if (this._currentSource.index == is.index)
return;
this._settings.set_value(KEY_CURRENT_INPUT_SOURCE,
GLib.Variant.new_uint32(is.index));
}));
@@ -718,82 +702,6 @@ const InputSourceIndicator = new Lang.Class({
}
},
_getNewInputSource: function(current) {
for (let i in this._inputSources) {
let is = this._inputSources[i];
if (is.type == current.type &&
is.id == current.id)
return is;
}
return this._currentSource;
},
_getCurrentWindow: function() {
if (Main.overview.visible)
return Main.overview;
else
return global.display.focus_window;
},
_setPerWindowInputSource: function() {
let window = this._getCurrentWindow();
if (!window)
return;
if (!window._inputSources) {
window._inputSources = this._inputSources;
window._currentSource = this._currentSource;
} else if (window._inputSources == this._inputSources) {
window._currentSource.activate();
} else {
window._inputSources = this._inputSources;
window._currentSource = this._getNewInputSource(window._currentSource);
window._currentSource.activate();
}
},
_sourcesPerWindowChanged: function() {
this._sourcesPerWindow = this._settings.get_boolean('per-window');
if (this._sourcesPerWindow && this._focusWindowNotifyId == 0) {
this._focusWindowNotifyId = global.display.connect('notify::focus-window',
Lang.bind(this, this._setPerWindowInputSource));
this._overviewShowingId = Main.overview.connect('showing',
Lang.bind(this, this._setPerWindowInputSource));
this._overviewHiddenId = Main.overview.connect('hidden',
Lang.bind(this, this._setPerWindowInputSource));
} else if (!this._sourcesPerWindow && this._focusWindowNotifyId != 0) {
global.display.disconnect(this._focusWindowNotifyId);
this._focusWindowNotifyId = 0;
Main.overview.disconnect(this._overviewShowingId);
this._overviewShowingId = 0;
Main.overview.disconnect(this._overviewHiddenId);
this._overviewHiddenId = 0;
let windows = global.get_window_actors().map(function(w) {
return w.meta_window;
});
for (let i = 0; i < windows.length; ++i) {
delete windows[i]._inputSources;
delete windows[i]._currentSource;
}
delete Main.overview._inputSources;
delete Main.overview._currentSource;
}
},
_changePerWindowSource: function() {
if (!this._sourcesPerWindow)
return;
let window = this._getCurrentWindow();
if (!window)
return;
window._inputSources = this._inputSources;
window._currentSource = this._currentSource;
},
_containerGetPreferredWidth: function(container, for_height, alloc) {
// Here, and in _containerGetPreferredHeight, we need to query
// for the height of all children, but we ignore the results

View File

@@ -10,31 +10,6 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const VolumeMenu = imports.ui.status.volume;
const FakeStatusIcon = new Lang.Class({
Name: 'FakeStatusIcon',
_init: function(button) {
this.actor = new St.BoxLayout({ style_class: 'panel-status-button-box' });
this._button = button;
this._button.connect('icons-updated', Lang.bind(this, this._reconstructIcons));
this._button.actor.bind_property('visible', this.actor, 'visible',
GObject.BindingFlags.SYNC_CREATE);
this._reconstructIcons();
},
_reconstructIcons: function() {
this.actor.destroy_all_children();
this._button.icons.forEach(Lang.bind(this, function(icon) {
let newIcon = new St.Icon({ style_class: 'system-status-icon' });
icon.bind_property('gicon', newIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
icon.bind_property('visible', newIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
this.actor.add_actor(newIcon);
}));
}
});
const Indicator = new Lang.Class({
Name: 'LockScreenMenuIndicator',
Extends: PanelMenu.SystemStatusButton,
@@ -43,20 +18,41 @@ const Indicator = new Lang.Class({
this.parent(null, _("Volume, network, battery"));
this._box.style_class = 'lock-screen-status-button-box';
this._volumeControl = VolumeMenu.getMixerControl();
this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
this.menu.addMenuItem(this._volumeMenu);
this._volume = Main.panel.statusArea.volume;
if (this._volume) {
this._volumeIcon = this.addIcon(null);
this._volume.mainIcon.bind_property('gicon', this._volumeIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._volume.mainIcon.bind_property('visible', this._volumeIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
this._volume = new FakeStatusIcon(Main.panel.statusArea.volume);
this._box.add_child(this._volume.actor);
// Network may not exist if the user doesn't have NetworkManager
if (Main.panel.statusArea.network) {
this._network = new FakeStatusIcon(Main.panel.statusArea.network);
this._box.add_child(this._network.actor);
this._volumeControl = VolumeMenu.getMixerControl();
this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
this.menu.addMenuItem(this._volumeMenu);
}
this._battery = new FakeStatusIcon(Main.panel.statusArea.battery);
this._box.add_child(this._battery.actor);
this._network = Main.panel.statusArea.network;
if (this._network) {
this._networkIcon = this.addIcon(null);
this._network.mainIcon.bind_property('gicon', this._networkIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._network.mainIcon.bind_property('visible', this._networkIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
this._networkSecondaryIcon = this.addIcon(null);
this._network.secondaryIcon.bind_property('gicon', this._networkSecondaryIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._network.secondaryIcon.bind_property('visible', this._networkSecondaryIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
}
this._battery = Main.panel.statusArea.battery;
if (this._battery) {
this._batteryIcon = this.addIcon(null);
this._battery.mainIcon.bind_property('gicon', this._batteryIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._battery.mainIcon.bind_property('visible', this._batteryIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
}
}
});

View File

@@ -8,26 +8,16 @@ const NMClient = imports.gi.NMClient;
const Signals = imports.signals;
const St = imports.gi.St;
// Some of the new code depends on as-yet-unreleased NM
var NMGtk;
try {
NMGtk = imports.gi.NMGtk;
} catch(e) {
NMGtk = null;
}
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const ModemManager = imports.misc.modemManager;
const Util = imports.misc.util;
const NMConnectionCategory = {
INVALID: 'invalid',
WIRED: 'wired',
VIRTUAL: 'virtual',
WIRELESS: 'wireless',
WWAN: 'wwan',
VPN: 'vpn'
@@ -149,6 +139,46 @@ const NMNetworkMenuItem = new Lang.Class({
}
});
const NMWiredSectionTitleMenuItem = new Lang.Class({
Name: 'NMWiredSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem,
_init: function(label, params) {
params = params || { };
params.style_class = 'popup-subtitle-menu-item';
this.parent(label, false, params);
},
updateForDevice: function(device) {
if (device) {
this._device = device;
this.setStatus(device.getStatusLabel());
this.setToggleState(device.connected);
} else
this.setStatus('');
},
activate: function(event) {
this.parent(event);
if (!this._device) {
log('Section title activated when there is more than one device, should be non reactive');
return;
}
let newState = this._switch.state;
let ok;
if (newState)
ok = this._device.activate();
else
ok = this._device.deactivate();
if (!ok)
this._switch.setToggleState(false);
}
});
const NMWirelessSectionTitleMenuItem = new Lang.Class({
Name: 'NMWirelessSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem,
@@ -309,16 +339,19 @@ const NMDevice = new Lang.Class({
Extends: NMConnectionBased,
_init: function(client, device, connections) {
this._client = client;
this._setDevice(device);
this.parent(connections);
this.device = device;
this.device._delegate = this;
this._stateChangedId = this.device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
// protected
this._client = client;
this.parent(connections);
this._activeConnection = null;
this._activeConnectionItem = null;
this._autoConnectionItem = null;
this._overflowItem = null;
this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected, { style_class: 'popup-subtitle-menu-item' });
this.statusItem = new PopupMenu.PopupSwitchMenuItem(this._getDescription(), this.connected, { style_class: 'popup-subtitle-menu-item' });
this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
let ok;
if (state)
@@ -337,12 +370,23 @@ const NMDevice = new Lang.Class({
},
destroy: function() {
this._setDevice(null);
if (this.device)
this.device._delegate = null;
if (this._deferredWorkId) {
// Just clear out, the actual removal is handled when the
// actor is destroyed
this._deferredWorkId = 0;
if (this._stateChangedId) {
// Need to go through GObject.Object.prototype because
// nm_device_disconnect conflicts with g_signal_disconnect
GObject.Object.prototype.disconnect.call(this.device, this._stateChangedId);
this._stateChangedId = 0;
}
if (this._carrierChangedId) {
// see above for why this is needed
GObject.Object.prototype.disconnect.call(this.device, this._carrierChangedId);
this._carrierChangedId = 0;
}
if (this._firmwareChangedId) {
GObject.Object.prototype.disconnect.call(this.device, this._firmwareChangedId);
this._firmwareChangedId = 0;
}
this._clearSection();
@@ -351,33 +395,6 @@ const NMDevice = new Lang.Class({
this.section.destroy();
},
_setDevice: function(device) {
if (device) {
this.device = device;
this.device._delegate = this;
this._stateChangedId = this.device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
} else if (this.device) {
this.device._delegate = null;
if (this._stateChangedId) {
// Need to go through GObject.Object.prototype because
// nm_device_disconnect conflicts with g_signal_disconnect
GObject.Object.prototype.disconnect.call(this.device, this._stateChangedId);
this._stateChangedId = 0;
}
if (this._carrierChangedId) {
GObject.Object.prototype.disconnect.call(this.device, this._carrierChangedId);
this._carrierChangedId = 0;
}
if (this._firmwareChangedId) {
GObject.Object.prototype.disconnect.call(this.device, this._firmwareChangedId);
this._firmwareChangedId = 0;
}
this.device = null;
}
},
deactivate: function() {
this.device.disconnect(null);
return true;
@@ -392,7 +409,7 @@ const NMDevice = new Lang.Class({
// Otherwise, if no connection is currently configured,
// try automatic configuration (or summon the config dialog)
if (this._connections.length == 1) {
this._client.activate_connection(this._connections[0].connection, this.device || null, null, null);
this._client.activate_connection(this._connections[0].connection, this.device, null, null);
return true;
} else if (this._connections.length == 0) {
return this._activateAutomaticConnection();
@@ -412,7 +429,7 @@ const NMDevice = new Lang.Class({
},
get connected() {
return this.device && this.device.state == NetworkManager.DeviceState.ACTIVATED;
return this.device.state == NetworkManager.DeviceState.ACTIVATED;
},
clearActiveConnection: function(activeConnection) {
@@ -432,6 +449,7 @@ const NMDevice = new Lang.Class({
this._activeConnection = activeConnection;
this._clearSection();
this._queueCreateSection();
},
@@ -445,9 +463,6 @@ const NMDevice = new Lang.Class({
},
getStatusLabel: function() {
if (!this.device)
return null;
switch(this.device.state) {
case NetworkManager.DeviceState.DISCONNECTED:
case NetworkManager.DeviceState.ACTIVATED:
@@ -497,21 +512,14 @@ const NMDevice = new Lang.Class({
}
},
syncDescription: function() {
if (this.device && this.device._description)
this.statusItem.label.text = this.device._description;
},
// protected
_createAutomaticConnection: function() {
throw new TypeError('Invoking pure virtual function NMDevice.createAutomaticConnection');
},
_queueCreateSection: function() {
if (this._deferredWorkId) {
this._clearSection();
Main.queueDeferredWork(this._deferredWorkId);
}
this._clearSection();
Main.queueDeferredWork(this._deferredWorkId);
},
_clearSection: function() {
@@ -611,6 +619,7 @@ const NMDevice = new Lang.Class({
this._updateStatusItem();
this._clearSection();
this._queueCreateSection();
this.emit('state-changed');
},
@@ -634,6 +643,25 @@ const NMDevice = new Lang.Class({
this.statusItem.setStatus(this.getStatusLabel());
this.emit('state-changed');
},
_getDescription: function() {
let dev_product = this.device.get_product();
let dev_vendor = this.device.get_vendor();
if (!dev_product || !dev_vendor)
return '';
let product = Util.fixupPCIDescription(dev_product);
let vendor = Util.fixupPCIDescription(dev_vendor);
let out = '';
// Another quick hack; if all of the fixed up vendor string
// is found in product, ignore the vendor.
if (product.indexOf(vendor) == -1)
out += vendor + ' ';
out += product;
return out;
}
});
@@ -664,7 +692,6 @@ const NMDeviceWired = new Lang.Class({
Extends: NMDeviceSimple,
_init: function(client, device, connections) {
device._description = _("Wired");
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED;
@@ -692,7 +719,6 @@ const NMDeviceModem = new Lang.Class({
_init: function(client, device, connections) {
let is_wwan = false;
device._description = _("Mobile broadband");
this._enabled = true;
this.mobileDevice = null;
this._connectionType = 'ppp';
@@ -811,7 +837,6 @@ const NMDeviceBluetooth = new Lang.Class({
Extends: NMDevice,
_init: function(client, device, connections) {
device._description = _("Bluetooth");
this._autoConnectionName = this._makeConnectionName(device);
device.connect('notify::name', Lang.bind(this, this._updateAutoConnectionName));
@@ -854,8 +879,13 @@ const NMDeviceBluetooth = new Lang.Class({
_updateAutoConnectionName: function() {
this._autoConnectionName = this._makeConnectionName(this.device);
this._clearSection();
this._queueCreateSection();
this._updateStatusItem();
},
_getDescription: function() {
return this.device.name || _("Bluetooth");
}
});
@@ -1115,8 +1145,10 @@ const NMDeviceWireless = new Lang.Class({
this._networks.splice(res.network, 1);
let newPos = Util.insertSorted(this._networks, network, Lang.bind(this, this._networkSortFunction));
if (newPos != res.network)
if (newPos != res.network) {
this._clearSection();
this._queueCreateSection();
}
},
_accessPointAdded: function(device, accessPoint) {
@@ -1169,8 +1201,10 @@ const NMDeviceWireless = new Lang.Class({
let newPos = Util.insertSorted(this._networks, apObj, this._networkSortFunction);
// Queue an update of the UI if we changed the order
if (newPos != pos)
if (newPos != pos) {
this._clearSection();
this._queueCreateSection();
}
},
_accessPointRemoved: function(device, accessPoint) {
@@ -1230,10 +1264,12 @@ const NMDeviceWireless = new Lang.Class({
if (res.network < this._networks.length-1)
okNext = this._networkSortFunction(this._networks[res.network + 1], apObj) <= 0;
if (!okPrev || !okNext)
if (!okPrev || !okNext) {
this._clearSection();
this._queueCreateSection();
else if (apObj.item)
} else if (apObj.item) {
apObj.item.updateBestAP(apObj.accessPoints[0]);
}
}
},
@@ -1309,6 +1345,7 @@ const NMDeviceWireless = new Lang.Class({
if (forceupdate) {
this._networks.sort(this._networkSortFunction);
this._clearSection();
this._queueCreateSection();
}
},
@@ -1341,6 +1378,7 @@ const NMDeviceWireless = new Lang.Class({
if (forceupdate) {
this._networks.sort(this._networkSortFunction);
this._clearSection();
this._queueCreateSection();
}
},
@@ -1451,56 +1489,6 @@ const NMDeviceWireless = new Lang.Class({
},
});
const NMDeviceVirtual = new Lang.Class({
Name: 'NMDeviceVirtual',
Extends: NMDeviceSimple,
_init: function(client, iface, connections) {
this.iface = iface;
this.parent(client, null, connections);
this.category = NMConnectionCategory.VIRTUAL;
},
_shouldShowConnectionList: function() {
return this.hasConnections();
},
connectionValid: function(connection) {
return connection.get_virtual_iface_name() == this.iface;
},
addConnection: function(connection) {
if (!this.device && !this.hasConnections())
this.statusItem.label.text = NMGtk.utils_get_connection_device_name(connection);
this.parent(connection);
},
adoptDevice: function(device) {
if (device.get_iface() == this.iface) {
this._setDevice(device);
if (device._description)
this.syncDescription();
this._updateStatusItem();
this.emit('state-changed');
return true;
} else
return false;
},
removeDevice: function(device) {
if (device == this.device) {
this._setDevice(null);
this._updateStatusItem();
this.emit('state-changed');
}
},
hasConnections: function() {
return this._connections.length != 0;
}
});
const NMVPNSection = new Lang.Class({
Name: 'NMVPNSection',
Extends: NMConnectionBased,
@@ -1679,32 +1667,23 @@ const NMApplet = new Lang.Class({
this._mobileUpdateId = 0;
this._mobileUpdateDevice = null;
this._nmDevices = [];
this._devices = { };
this._virtualDevices = [ ];
this._devices.wired = {
section: new PopupMenu.PopupMenuSection(),
devices: [ ],
item: new NMWiredSectionTitleMenuItem(_("Wired"))
};
this._devices.wired.section.addMenuItem(this._devices.wired.item);
this._devices.wired.section.actor.hide();
this.menu.addMenuItem(this._devices.wired.section);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._devices.virtual = {
section: new PopupMenu.PopupMenuSection(),
devices: [ ],
};
this._devices.virtual.section.actor.hide();
this.menu.addMenuItem(this._devices.virtual.section);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._devices.wireless = {
section: new PopupMenu.PopupMenuSection(),
devices: [ ],
item: this._makeToggleItem('wireless', _("Wi-Fi"))
item: this._makeToggleItem('wireless', _("Wireless"))
};
this._devices.wireless.section.addMenuItem(this._devices.wireless.item);
this._devices.wireless.section.actor.hide();
@@ -1714,7 +1693,9 @@ const NMApplet = new Lang.Class({
this._devices.wwan = {
section: new PopupMenu.PopupMenuSection(),
devices: [ ],
item: this._makeToggleItem('wwan', _("Mobile broadband"))
};
this._devices.wwan.section.addMenuItem(this._devices.wwan.item);
this._devices.wwan.section.actor.hide();
this.menu.addMenuItem(this._devices.wwan.section);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@@ -1734,14 +1715,6 @@ const NMApplet = new Lang.Class({
this._dtypes[NetworkManager.DeviceType.INFINIBAND] = NMDeviceSimple;
// TODO: WiMax support
// Virtual device types
this._vtypes = { };
if (NMGtk) {
this._vtypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMDeviceVirtual;
this._vtypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMDeviceVirtual;
this._vtypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMDeviceVirtual;
}
// Connection types
this._ctypes = { };
this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
@@ -1752,11 +1725,6 @@ const NMApplet = new Lang.Class({
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED;
if (NMGtk) {
this._ctypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
this._ctypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
this._ctypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
}
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
this._settings = NMClient.RemoteSettings.new(null);
@@ -1784,7 +1752,6 @@ const NMApplet = new Lang.Class({
if (!this._source) {
this._source = new MessageTray.Source(_("Network Manager"),
'network-transmit-receive');
this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-network-panel');
this._source.connect('destroy', Lang.bind(this, function() {
this._source = null;
@@ -1809,34 +1776,20 @@ const NMApplet = new Lang.Class({
let devices = this._devices[category].devices;
let item = this._devices[category].item;
let section = this._devices[category].section;
let visible;
if (category == NMConnectionCategory.VIRTUAL)
visible = !section.isEmpty();
else
visible = devices.length > 0;
if (!visible)
if (devices.length == 0)
section.actor.hide();
else {
section.actor.show();
// Sync the relation between the section title
// item (the one with the airplane mode switch)
// and the individual device switches
if (item) {
if (devices.length == 1) {
let dev = devices[0];
dev.statusItem.actor.hide();
item.updateForDevice(dev);
} else {
devices.forEach(function(dev) {
dev.statusItem.actor.show();
});
// remove status text from the section title item
item.updateForDevice(null);
}
if (devices.length == 1) {
let dev = devices[0];
dev.statusItem.actor.hide();
item.updateForDevice(dev);
} else {
devices.forEach(function(dev) {
dev.statusItem.actor.show();
});
// remove status text from the section title item
item.updateForDevice(null);
}
}
},
@@ -1844,9 +1797,8 @@ const NMApplet = new Lang.Class({
_readDevices: function() {
let devices = this._client.get_devices() || [ ];
for (let i = 0; i < devices.length; ++i) {
this._deviceAdded(this._client, devices[i], true);
this._deviceAdded(this._client, devices[i]);
}
this._syncDeviceNames();
},
_notifyForDevice: function(device, iconName, title, text, urgency) {
@@ -1877,50 +1829,9 @@ const NMApplet = new Lang.Class({
MessageTray.Urgency.HIGH);
},
_syncDeviceNames: function() {
if (NMGtk) {
let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
for (let i = 0; i < this._nmDevices.length; i++) {
let device = this._nmDevices[i];
device._description = names[i];
if (device._delegate)
device._delegate.syncDescription();
}
} else {
for (let i = 0; i < this._nmDevices.length; i++) {
let device = this._nmDevices[i];
device._delegate.syncDescription();
}
}
},
_makeWrapperDevice: function(wrapperClass, device) {
let wrapper = new wrapperClass(this._client, device, this._connections);
_deviceAdded: function(client, device, skipSyncDeviceNames) {
if (device._delegate) {
// already seen, not adding again
return;
}
for (let i = 0; i < this._virtualDevices.length; i++) {
if (this._virtualDevices[i].adoptDevice(device)) {
this._nmDevices.push(device);
if (!skipSyncDeviceNames)
this._syncDeviceNames();
return;
}
}
let wrapperClass = this._dtypes[device.get_device_type()];
if (wrapperClass) {
let wrapper = new wrapperClass(this._client, device, this._connections);
this._addDeviceWrapper(wrapper);
this._nmDevices.push(device);
if (!skipSyncDeviceNames)
this._syncDeviceNames();
}
},
_addDeviceWrapper: function(wrapper) {
wrapper._activationFailedId = wrapper.connect('activation-failed',
Lang.bind(this, this._onActivationFailed));
wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
@@ -1932,36 +1843,35 @@ const NMApplet = new Lang.Class({
wrapper.disconnect(wrapper._destroyId);
});
let section = this._devices[wrapper.category].section;
section.addMenuItem(wrapper.statusItem);
section.addMenuItem(wrapper.section);
return wrapper;
},
let devices = this._devices[wrapper.category].devices;
devices.push(wrapper);
_deviceAdded: function(client, device) {
if (device._delegate) {
// already seen, not adding again
return;
}
let wrapperClass = this._dtypes[device.get_device_type()];
if (wrapperClass) {
let wrapper = this._makeWrapperDevice(wrapperClass, device);
let section = this._devices[wrapper.category].section;
let devices = this._devices[wrapper.category].devices;
this._syncSectionTitle(wrapper.category);
section.addMenuItem(wrapper.section, 1);
section.addMenuItem(wrapper.statusItem, 1);
devices.push(wrapper);
this._syncSectionTitle(wrapper.category);
}
},
_deviceRemoved: function(client, device) {
let pos = this._nmDevices.indexOf(device);
if (pos != -1) {
this._nmDevices.splice(pos, 1);
this._syncDeviceNames();
}
let wrapper = device._delegate;
if (!wrapper) {
if (!device._delegate) {
log('Removing a network device that was not added');
return;
}
if (wrapper instanceof NMDeviceVirtual)
wrapper.removeDevice(device);
else
this._removeDeviceWrapper(wrapper);
},
_removeDeviceWrapper: function(wrapper) {
let wrapper = device._delegate;
wrapper.destroy();
let devices = this._devices[wrapper.category].devices;
@@ -2162,13 +2072,6 @@ const NMApplet = new Lang.Class({
devices[i].removeConnection(connection);
}
if (section == NMConnectionCategory.VIRTUAL) {
let iface = connection.get_virtual_iface_name();
let wrapper = this._findVirtualDevice(iface);
if (wrapper && !wrapper.hasConnections())
this._removeDeviceWrapper(wrapper);
}
connection.disconnect(connection._removedId);
connection.disconnect(connection._updatedId);
connection._removedId = connection._updatedId = 0;
@@ -2182,27 +2085,6 @@ const NMApplet = new Lang.Class({
let section = connection._section;
if (section == NMConnectionCategory.VIRTUAL) {
let wrapperClass = this._vtypes[connection._type];
if (!wrapperClass)
return;
let iface = connection.get_virtual_iface_name();
let wrapper = this._findVirtualDevice(iface);
if (!wrapper) {
wrapper = new wrapperClass(this._client, iface, this._connections);
this._addDeviceWrapper(wrapper);
this._virtualDevices.push(wrapper);
// We might already have a device for this connection
for (let i = 0; i < this._nmDevices.length; i++) {
let device = this._nmDevices[i];
if (wrapper.adoptDevice(device))
break;
}
}
}
if (section == NMConnectionCategory.INVALID)
return;
if (section == NMConnectionCategory.VPN) {
@@ -2215,15 +2097,6 @@ const NMApplet = new Lang.Class({
}
},
_findVirtualDevice: function(iface) {
for (let i = 0; i < this._virtualDevices.length; i++) {
if (this._virtualDevices[i].iface == iface)
return this._virtualDevices[i];
}
return null;
},
_hideDevices: function() {
this._devicesHidden = true;
@@ -2239,7 +2112,6 @@ const NMApplet = new Lang.Class({
this._statusSection.actor.hide();
this._syncSectionTitle(NMConnectionCategory.WIRED);
this._syncSectionTitle(NMConnectionCategory.VIRTUAL);
this._syncSectionTitle(NMConnectionCategory.WIRELESS);
this._syncSectionTitle(NMConnectionCategory.WWAN);
},
@@ -2277,7 +2149,6 @@ const NMApplet = new Lang.Class({
this.setIcon('network-wireless-acquiring-symbolic');
break;
case NMConnectionCategory.WIRED:
case NMConnectionCategory.VIRTUAL:
this.setIcon('network-wired-acquiring-symbolic');
break;
default:
@@ -2317,7 +2188,6 @@ const NMApplet = new Lang.Class({
break;
}
case NMConnectionCategory.WIRED:
case NMConnectionCategory.VIRTUAL:
this.setIcon('network-wired-symbolic');
break;
case NMConnectionCategory.WWAN:

View File

@@ -7,7 +7,7 @@ const St = imports.gi.St;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
const BUS_NAME = 'org.gnome.SettingsDaemon';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const UPDeviceType = {
@@ -54,23 +54,14 @@ const Indicator = new Lang.Class({
_init: function() {
this.parent('battery-missing-symbolic', _("Battery"));
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
Lang.bind(this, function(proxy, error) {
if (error) {
log(error.message);
return;
}
this._proxy.connect('g-properties-changed',
Lang.bind(this, this._devicesChanged));
this._devicesChanged();
}));
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
this._deviceItems = [ ];
this._hasPrimary = false;
this._primaryDeviceId = null;
this._batteryItem = new PopupMenu.PopupMenuItem('', { reactive: false });
this._primaryPercentage = new St.Label({ style_class: 'popup-battery-percentage' });
this._primaryPercentage = new St.Label();
this._batteryItem.addActor(this._primaryPercentage, { align: St.Align.END });
this.menu.addMenuItem(this._batteryItem);
@@ -79,6 +70,10 @@ const Indicator = new Lang.Class({
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
this._proxy.connect('g-properties-changed',
Lang.bind(this, this._devicesChanged));
this._devicesChanged();
},
_readPrimaryDevice: function() {
@@ -188,8 +183,7 @@ const DeviceItem = new Lang.Class({
this._box.add_actor(this._label);
this.addActor(this._box);
let percentLabel = new St.Label({ text: C_("percent of battery remaining", "%d%%").format(Math.round(percentage)),
style_class: 'popup-battery-percentage' });
let percentLabel = new St.Label({ text: C_("percent of battery remaining", "%d%%").format(Math.round(percentage)) });
this.addActor(percentLabel, { align: St.Align.END });
//FIXME: ideally we would like to expose this._label and percentLabel
this.actor.label_actor = percentLabel;

View File

@@ -5,7 +5,6 @@ const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Gvc = imports.gi.Gvc;
const St = imports.gi.St;
const Signals = imports.signals;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@@ -27,210 +26,6 @@ function getMixerControl() {
return _mixerControl;
}
const StreamSlider = new Lang.Class({
Name: 'StreamSlider',
_init: function(control, title) {
this._control = control;
this.item = new PopupMenu.PopupMenuSection();
this._title = new PopupMenu.PopupMenuItem(title, { reactive: false });
this._slider = new PopupMenu.PopupSliderMenuItem(0);
this._slider.connect('value-changed', Lang.bind(this, this._sliderChanged));
this._slider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
this.item.addMenuItem(this._title);
this.item.addMenuItem(this._slider);
this._stream = null;
this._shouldShow = true;
},
get stream() {
return this._stream;
},
set stream(stream) {
if (this._stream) {
this._disconnectStream(this._stream);
}
this._stream = stream;
if (this._stream) {
this._connectStream(this._stream);
this._updateVolume();
} else {
this.emit('stream-updated');
}
this._updateVisibility();
},
_disconnectStream: function(stream) {
stream.disconnect(this._mutedChangedId);
this._mutedChangedId = 0;
stream.disconnect(this._volumeChangedId);
this._volumeChangedId = 0;
},
_connectStream: function(stream) {
this._mutedChangedId = stream.connect('notify::is-muted', Lang.bind(this, this._updateVolume));
this._volumeChangedId = stream.connect('notify::volume', Lang.bind(this, this._updateVolume));
},
_shouldBeVisible: function() {
return this._stream != null;
},
_updateVisibility: function() {
let visible = this._shouldBeVisible();
this._title.actor.visible = visible;
this._slider.actor.visible = visible;
},
scroll: function(event) {
this._slider.scroll(event);
},
setValue: function(value) {
// piggy-back off of sliderChanged
this._slider.setValue(value);
},
_sliderChanged: function(slider, value, property) {
if (!this._stream)
return;
let volume = value * this._control.get_vol_max_norm();
let prevMuted = this._stream.is_muted;
if (volume < 1) {
this._stream.volume = 0;
if (!prevMuted)
this._stream.change_is_muted(true);
} else {
this._stream.volume = volume;
if (prevMuted)
this._stream.change_is_muted(false);
}
this._stream.push_volume();
},
_notifyVolumeChange: function() {
global.cancel_theme_sound(VOLUME_NOTIFY_ID);
global.play_theme_sound(VOLUME_NOTIFY_ID,
'audio-volume-change',
_("Volume changed"),
Clutter.get_current_event ());
},
_updateVolume: function() {
let muted = this._stream.is_muted;
this._slider.setValue(muted ? 0 : (this._stream.volume / this._control.get_vol_max_norm()));
this.emit('stream-updated');
},
getIcon: function() {
if (!this._stream)
return null;
let volume = this._stream.volume;
if (this._stream.is_muted || volume <= 0) {
return 'audio-volume-muted-symbolic';
} else {
let n = Math.floor(3 * volume / this._control.get_vol_max_norm()) + 1;
if (n < 2)
return 'audio-volume-low-symbolic';
if (n >= 3)
return 'audio-volume-high-symbolic';
return 'audio-volume-medium-symbolic';
}
}
});
Signals.addSignalMethods(StreamSlider.prototype);
const OutputStreamSlider = new Lang.Class({
Name: 'OutputStreamSlider',
Extends: StreamSlider,
_connectStream: function(stream) {
this.parent(stream);
this._portChangedId = stream.connect('notify::port', Lang.bind(this, this._portChanged));
this._portChanged();
},
_findHeadphones: function(sink) {
// This only works for external headphones (e.g. bluetooth)
if (sink.get_form_factor() == 'headset' ||
sink.get_form_factor() == 'headphone')
return true;
// a bit hackish, but ALSA/PulseAudio have a number
// of different identifiers for headphones, and I could
// not find the complete list
if (sink.get_ports().length > 0)
return sink.get_port().port.indexOf('headphone') >= 0;
return false;
},
_disconnectStream: function(stream) {
this.parent(stream);
stream.disconnect(this._portChangedId);
this._portChangedId = 0;
},
_portChanged: function() {
let hasHeadphones = this._findHeadphones(this._stream);
if (hasHeadphones != this._hasHeadphones) {
this._hasHeadphones = hasHeadphones;
this.emit('headphones-changed', this._hasHeadphones);
}
}
});
const InputStreamSlider = new Lang.Class({
Name: 'InputStreamSlider',
Extends: StreamSlider,
_init: function(control, title) {
this.parent(control, title);
this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
},
_connectStream: function(stream) {
this.parent(stream);
this._maybeShowInput();
},
_maybeShowInput: function() {
// only show input widgets if any application is recording audio
let showInput = false;
let recordingApps = this._control.get_source_outputs();
if (this._stream && recordingApps) {
for (let i = 0; i < recordingApps.length; i++) {
let outputStream = recordingApps[i];
let id = outputStream.get_application_id();
// but skip gnome-volume-control and pavucontrol
// (that appear as recording because they show the input level)
if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) {
showInput = true;
break;
}
}
}
this._showInput = showInput;
this._updateVisibility();
},
_shouldBeVisible: function() {
return this.parent() && this._showInput;
}
});
const VolumeMenu = new Lang.Class({
Name: 'VolumeMenu',
Extends: PopupMenu.PopupMenuSection,
@@ -244,48 +39,207 @@ const VolumeMenu = new Lang.Class({
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
this._control.connect('default-sink-changed', Lang.bind(this, this._readOutput));
this._control.connect('default-source-changed', Lang.bind(this, this._readInput));
this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
this._volumeMax = this._control.get_vol_max_norm();
this._output = null;
this._outputVolumeId = 0;
this._outputMutedId = 0;
/* Translators: This is the label for audio volume */
this._output = new OutputStreamSlider(this._control, _("Volume"));
this._output.connect('stream-updated', Lang.bind(this, function() {
this.emit('icon-changed');
}));
this._output.connect('headphones-changed', Lang.bind(this, function(stream, value) {
this.emit('headphones-changed', value);
}));
this.addMenuItem(this._output.item);
this._input = new InputStreamSlider(this._control, _("Microphone"));
this.addMenuItem(this._input.item);
this._outputTitle = new PopupMenu.PopupMenuItem(_("Volume"), { reactive: false });
this._outputSlider = new PopupMenu.PopupSliderMenuItem(0);
this._outputSlider.connect('value-changed', Lang.bind(this, this._sliderChanged, '_output'));
this._outputSlider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
this.addMenuItem(this._outputTitle);
this.addMenuItem(this._outputSlider);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._input = null;
this._inputVolumeId = 0;
this._inputMutedId = 0;
this._inputTitle = new PopupMenu.PopupMenuItem(_("Microphone"), { reactive: false });
this._inputSlider = new PopupMenu.PopupSliderMenuItem(0);
this._inputSlider.connect('value-changed', Lang.bind(this, this._sliderChanged, '_input'));
this._inputSlider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
this.addMenuItem(this._inputTitle);
this.addMenuItem(this._inputSlider);
this._onControlStateChanged();
},
scroll: function(event) {
this._output.scroll(event);
scroll: function(direction) {
let currentVolume = this._output.volume;
if (direction == Clutter.ScrollDirection.DOWN) {
let prev_muted = this._output.is_muted;
this._output.volume = Math.max(0, currentVolume - this._volumeMax * VOLUME_ADJUSTMENT_STEP);
if (this._output.volume < 1) {
this._output.volume = 0;
if (!prev_muted)
this._output.change_is_muted(true);
}
this._output.push_volume();
}
else if (direction == Clutter.ScrollDirection.UP) {
this._output.volume = Math.min(this._volumeMax, currentVolume + this._volumeMax * VOLUME_ADJUSTMENT_STEP);
this._output.change_is_muted(false);
this._output.push_volume();
}
this._notifyVolumeChange();
},
_onControlStateChanged: function() {
if (this._control.get_state() == Gvc.MixerControlState.READY) {
this._readInput();
this._readOutput();
this._readInput();
this._maybeShowInput();
} else {
this.emit('icon-changed');
this.emit('icon-changed', null);
}
},
_findHeadphones: function(sink) {
// This only works for external headphones (e.g. bluetooth)
if (sink.get_form_factor() == 'headset' ||
sink.get_form_factor() == 'headphone')
return true;
// a bit hackish, but ALSA/PulseAudio have a number
// of different identifiers for headphones, and I could
// not find the complete list
let port = sink.get_port();
if (port)
return port.port.indexOf('headphone') >= 0;
return false;
},
_portChanged: function() {
this.hasHeadphones = this._findHeadphones(this._output);
this.emit('headphones-changed');
},
_readOutput: function() {
this._output.stream = this._control.get_default_sink();
if (this._outputVolumeId) {
this._output.disconnect(this._outputVolumeId);
this._output.disconnect(this._outputMutedId);
this._output.disconnect(this._outputPortId);
this._outputVolumeId = 0;
this._outputMutedId = 0;
this._outputPortId = 0;
}
this._output = this._control.get_default_sink();
if (this._output) {
this._outputMutedId = this._output.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_output'));
this._outputVolumeId = this._output.connect('notify::volume', Lang.bind(this, this._volumeChanged, '_output'));
this._outputPortId = this._output.connect('notify::port', Lang.bind(this, this._portChanged));
this._mutedChanged(null, null, '_output');
this._volumeChanged(null, null, '_output');
this._portChanged();
} else {
this.hasHeadphones = false;
this._outputSlider.setValue(0);
this.emit('icon-changed', 'audio-volume-muted-symbolic');
}
},
_readInput: function() {
this._input.stream = this._control.get_default_source();
if (this._inputVolumeId) {
this._input.disconnect(this._inputVolumeId);
this._input.disconnect(this._inputMutedId);
this._inputVolumeId = 0;
this._inputMutedId = 0;
}
this._input = this._control.get_default_source();
if (this._input) {
this._inputMutedId = this._input.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_input'));
this._inputVolumeId = this._input.connect('notify::volume', Lang.bind(this, this._volumeChanged, '_input'));
this._mutedChanged (null, null, '_input');
this._volumeChanged (null, null, '_input');
} else {
this._inputTitle.actor.hide();
this._inputSlider.actor.hide();
}
},
getIcon: function() {
return this._output.getIcon();
_maybeShowInput: function() {
// only show input widgets if any application is recording audio
let showInput = false;
let recordingApps = this._control.get_source_outputs();
if (this._input && recordingApps) {
for (let i = 0; i < recordingApps.length; i++) {
let outputStream = recordingApps[i];
let id = outputStream.get_application_id();
// but skip gnome-volume-control and pavucontrol
// (that appear as recording because they show the input level)
if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) {
showInput = true;
break;
}
}
}
this._inputTitle.actor.visible = showInput;
this._inputSlider.actor.visible = showInput;
},
_volumeToIcon: function(volume) {
if (volume <= 0) {
return 'audio-volume-muted-symbolic';
} else {
let n = Math.floor(3 * volume / this._volumeMax) + 1;
if (n < 2)
return 'audio-volume-low-symbolic';
if (n >= 3)
return 'audio-volume-high-symbolic';
return 'audio-volume-medium-symbolic';
}
},
_sliderChanged: function(slider, value, property) {
if (this[property] == null) {
log ('Volume slider changed for %s, but %s does not exist'.format(property, property));
return;
}
let volume = value * this._volumeMax;
let prev_muted = this[property].is_muted;
if (volume < 1) {
this[property].volume = 0;
if (!prev_muted)
this[property].change_is_muted(true);
} else {
this[property].volume = volume;
if (prev_muted)
this[property].change_is_muted(false);
}
this[property].push_volume();
},
_notifyVolumeChange: function() {
global.cancel_theme_sound(VOLUME_NOTIFY_ID);
global.play_theme_sound(VOLUME_NOTIFY_ID, 'audio-volume-change');
},
_mutedChanged: function(object, param_spec, property) {
let muted = this[property].is_muted;
let slider = this[property+'Slider'];
slider.setValue(muted ? 0 : (this[property].volume / this._volumeMax));
if (property == '_output') {
if (muted)
this.emit('icon-changed', 'audio-volume-muted-symbolic');
else
this.emit('icon-changed', this._volumeToIcon(this._output.volume));
}
},
_volumeChanged: function(object, param_spec, property) {
this[property+'Slider'].setValue(this[property].volume / this._volumeMax);
if (property == '_output' && !this._output.is_muted)
this.emit('icon-changed', this._volumeToIcon(this._output.volume));
}
});
@@ -298,13 +252,13 @@ const Indicator = new Lang.Class({
this._control = getMixerControl();
this._volumeMenu = new VolumeMenu(this._control);
this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu) {
let icon = this._volumeMenu.getIcon();
this.actor.visible = (icon != null);
this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu, icon) {
this._hasPulseAudio = (icon != null);
this.setIcon(icon);
this._syncVisibility();
}));
this._volumeMenu.connect('headphones-changed', Lang.bind(this, function(menu, value) {
this._headphoneIcon.visible = value;
this._volumeMenu.connect('headphones-changed', Lang.bind(this, function() {
this._syncVisibility();
}));
this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' }));
@@ -318,7 +272,13 @@ const Indicator = new Lang.Class({
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
},
_syncVisibility: function() {
this.actor.visible = this._hasPulseAudio;
this.mainIcon.visible = this._hasPulseAudio;
this._headphoneIcon.visible = this._hasPulseAudio && this._volumeMenu.hasHeadphones;
},
_onScrollEvent: function(actor, event) {
this._volumeMenu.scroll(event);
this._volumeMenu.scroll(event.get_scroll_direction());
}
});

View File

@@ -46,8 +46,7 @@ const SwitcherPopup = new Lang.Class({
this._selectedIndex = 0;
this.actor = new Shell.GenericContainer({ style_class: 'switcher-popup',
reactive: true,
visible: false });
reactive: true });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
@@ -638,6 +637,5 @@ function drawArrow(area, side) {
Clutter.cairo_set_source_color(cr, bodyColor);
cr.fill();
cr.$dispose();
}

View File

@@ -115,7 +115,7 @@ const UnlockDialog = new Lang.Class({
_init: function(parentActor) {
this.parent({ shellReactive: true,
styleClass: 'login-dialog',
keybindingMode: Shell.KeyBindingMode.UNLOCK_SCREEN,
keybindingMode: Main.KeybindingMode.UNLOCK_SCREEN,
parentActor: parentActor
});
@@ -198,23 +198,18 @@ const UnlockDialog = new Lang.Class({
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
let screenSaverSettings = new Gio.Settings({ schema: 'org.gnome.desktop.screensaver' });
if (screenSaverSettings.get_boolean('user-switch-enabled')) {
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
style_class: 'login-dialog-not-listed-label' });
this._otherUserButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
can_focus: true,
child: otherUserLabel,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
this.dialogLayout.add(this._otherUserButton,
{ x_align: St.Align.START,
x_fill: false });
} else {
this._otherUserButton = null;
}
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
style_class: 'login-dialog-not-listed-label' });
this._otherUserButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
can_focus: true,
child: otherUserLabel,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
this.dialogLayout.add(this._otherUserButton,
{ x_align: St.Align.START,
x_fill: false });
this._updateSensitivity(true);
@@ -236,10 +231,8 @@ const UnlockDialog = new Lang.Class({
this._promptEntry.reactive = sensitive;
this._promptEntry.clutter_text.editable = sensitive;
this._updateOkButtonSensitivity(sensitive && this._promptEntry.text.length > 0);
if (this._otherUserButton) {
this._otherUserButton.reactive = sensitive;
this._otherUserButton.can_focus = sensitive;
}
this._otherUserButton.reactive = sensitive;
this._otherUserButton.can_focus = sensitive;
},
_updateOkButtonSensitivity: function(sensitive) {

View File

@@ -22,13 +22,12 @@ const Util = imports.misc.util;
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy'
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
const LOCK_ENABLED_KEY = 'lock-enabled';
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
const SHOW_FULL_NAME_IN_TOP_BAR_KEY = 'show-full-name-in-top-bar';
const SHOW_FULL_NAME_KEY = 'show-full-name';
const DIALOG_ICON_SIZE = 64;
@@ -478,7 +477,6 @@ const UserMenuButton = new Lang.Class({
this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA });
this._userManager = AccountsService.UserManager.get_default();
@@ -555,12 +553,10 @@ const UserMenuButton = new Lang.Class({
Lang.bind(this, this._updateLogout));
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
Lang.bind(this, this._updateLockScreen));
global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
Lang.bind(this, this._updateLogout));
this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_IN_TOP_BAR_KEY,
this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_KEY,
Lang.bind(this, this._updateUserName));
this._privacySettings.connect('changed::' + SHOW_FULL_NAME_IN_TOP_BAR_KEY,
Lang.bind(this, this._updateUserName));
global.settings.connect('changed::' + SHOW_FULL_NAME_KEY,
Lang.bind(this, this._updateUserName));
this._updateSwitchUser();
this._updateLogout();
this._updateLockScreen();
@@ -585,7 +581,6 @@ const UserMenuButton = new Lang.Class({
Lang.bind(this, this._updateHaveShutdown));
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
Main.screenShield.connect('locked-changed', Lang.bind(this, this._updatePresenceIcon));
this._sessionUpdated();
},
@@ -607,10 +602,10 @@ const UserMenuButton = new Lang.Class({
},
_updateUserName: function() {
let settings = this._privacySettings;
let settings = global.settings;
if (Main.sessionMode.isLocked)
settings = this._screenSaverSettings;
if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_IN_TOP_BAR_KEY))
if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_KEY))
this._name.set_text(this._user.get_real_name());
else
this._name.set_text("");
@@ -705,11 +700,6 @@ const UserMenuButton = new Lang.Class({
this._iconBox.child = this._idleIcon;
else
this._iconBox.child = this._offlineIcon;
if (Main.sessionMode.isLocked)
this._iconBox.visible = Main.screenShield.locked;
else
this._iconBox.visible = true;
},
_setupAccounts: function() {
@@ -830,7 +820,7 @@ const UserMenuButton = new Lang.Class({
_onMyAccountActivate: function() {
Main.overview.hide();
let app = Shell.AppSystem.get_default().lookup_app('gnome-user-accounts-panel.desktop');
let app = Shell.AppSystem.get_default().lookup_setting('gnome-user-accounts-panel.desktop');
app.activate();
},

View File

@@ -12,7 +12,6 @@ const St = imports.gi.St;
const AppDisplay = imports.ui.appDisplay;
const Main = imports.ui.main;
const Params = imports.misc.params;
const RemoteSearch = imports.ui.remoteSearch;
const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
@@ -47,7 +46,8 @@ const ViewSelector = new Lang.Class({
this._activePage = null;
this._searchActive = false;
this.active = false;
this._searchPending = false;
this._searchTimeoutId = 0;
this._searchSystem = new Search.SearchSystem();
@@ -77,17 +77,16 @@ const ViewSelector = new Lang.Class({
this._capturedEventId = 0;
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
this._workspacesPage = this._addPage(this._workspacesDisplay.actor, null,
_("Windows"), 'emblem-documents-symbolic');
this._appDisplay = new AppDisplay.AllAppDisplay();
this._appsPage = this._addPage(this._appDisplay.actor,
this._appsPage = this._addPage(this._appDisplay.actor, null,
_("Applications"), 'view-grid-symbolic');
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
this._searchPage = this._addPage(this._searchResults.actor,
_("Search"), 'edit-find-symbolic',
{ a11yFocus: this._entry });
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
_("Search"), 'edit-find-symbolic');
this._searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
@@ -136,8 +135,8 @@ const ViewSelector = new Lang.Class({
Main.wm.addKeybinding('toggle-application-view',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._toggleAppsPage));
},
@@ -170,16 +169,14 @@ const ViewSelector = new Lang.Class({
this._workspacesDisplay.hide();
},
_addPage: function(actor, name, a11yIcon, params) {
params = Params.parse(params, { a11yFocus: null });
_addPage: function(actor, a11yFocus, name, a11yIcon) {
let page = new St.Bin({ child: actor,
x_align: St.Align.START,
y_align: St.Align.START,
x_fill: true,
y_fill: true });
if (params.a11yFocus)
Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
if (a11yFocus)
Main.ctrlAltTabManager.addGroup(a11yFocus, name, a11yIcon);
else
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon,
{ proxy: this.actor,
@@ -223,7 +220,7 @@ const ViewSelector = new Lang.Class({
},
_onShowAppsButtonToggled: function() {
if (this._searchActive)
if (this.active)
this.reset();
else
this._showPage(this._showAppsButton.checked ? this._appsPage
@@ -244,7 +241,7 @@ const ViewSelector = new Lang.Class({
let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) {
if (this._searchActive)
if (this.active)
this.reset();
else if (this._showAppsButton.checked)
this._resetShowAppsButton();
@@ -252,9 +249,9 @@ const ViewSelector = new Lang.Class({
Main.overview.hide();
return true;
} else if (Clutter.keysym_to_unicode(symbol) ||
(symbol == Clutter.BackSpace && this._searchActive)) {
(symbol == Clutter.BackSpace && this.active)) {
this.startSearch(event);
} else if (!this._searchActive) {
} else if (!this.active) {
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
return true;
@@ -328,37 +325,39 @@ const ViewSelector = new Lang.Class({
},
_onTextChanged: function (se, prop) {
let searchPreviouslyActive = this._searchActive;
this._searchActive = this._entry.get_text() != '';
let startSearch = this._searchActive && !searchPreviouslyActive;
if (startSearch)
let searchPreviouslyActive = this.active;
this.active = this._entry.get_text() != '';
this._searchPending = this.active && !searchPreviouslyActive;
if (this._searchPending) {
this._searchResults.startingSearch();
if (this._searchActive) {
}
if (this.active) {
this._entry.set_secondary_icon(this._activeIcon);
if (this._iconClickedId == 0)
if (this._iconClickedId == 0) {
this._iconClickedId = this._entry.connect('secondary-icon-clicked',
Lang.bind(this, this.reset));
if (this._searchTimeoutId == 0)
this._searchTimeoutId = Mainloop.timeout_add(150,
Lang.bind(this, this._doSearch));
Lang.bind(this, function() {
this.reset();
}));
}
} else {
if (this._iconClickedId > 0) {
if (this._iconClickedId > 0)
this._entry.disconnect(this._iconClickedId);
this._iconClickedId = 0;
}
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._searchTimeoutId = 0;
}
this._iconClickedId = 0;
this._entry.set_secondary_icon(this._inactiveIcon);
this._searchCancelled();
}
if (!this.active) {
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._searchTimeoutId = 0;
}
return;
}
if (this._searchTimeoutId > 0)
return;
this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, this._doSearch));
},
_onKeyPress: function(entry, event) {
@@ -368,7 +367,16 @@ const ViewSelector = new Lang.Class({
this.reset();
return true;
}
} else if (this._searchActive) {
} else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
// We can't connect to 'activate' here because search providers
// might want to do something with the modifiers in activateDefault.
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._doSearch();
}
this._searchResults.activateDefault();
return true;
} else if (this.active) {
let arrowNext, nextDirection;
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
arrowNext = Clutter.Left;
@@ -392,15 +400,6 @@ const ViewSelector = new Lang.Class({
} else if (symbol == arrowNext && this._text.position == -1) {
this._searchResults.navigateFocus(nextDirection);
return true;
} else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
// We can't connect to 'activate' here because search providers
// might want to do something with the modifiers in activateDefault.
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._doSearch();
}
this._searchResults.activateDefault();
return true;
}
}
return false;

View File

@@ -105,74 +105,74 @@ const WindowManager = new Lang.Class({
this._workspaceSwitcherPopup = null;
this.setCustomKeybindingHandler('switch-to-workspace-left',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-right',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-up',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-down',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-left',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-right',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-up',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-down',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-applications',
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-group',
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-applications-backward',
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-group-backward',
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-windows',
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('switch-windows-backward',
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('switch-panels',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW |
Shell.KeyBindingMode.LOCK_SCREEN |
Shell.KeyBindingMode.UNLOCK_SCREEN |
Shell.KeyBindingMode.LOGIN_SCREEN,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW |
Main.KeybindingMode.LOCK_SCREEN |
Main.KeybindingMode.UNLOCK_SCREEN |
Main.KeybindingMode.LOGIN_SCREEN,
Lang.bind(this, this._startA11ySwitcher));
this.setCustomKeybindingHandler('switch-panels-backward',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW |
Shell.KeyBindingMode.LOCK_SCREEN |
Shell.KeyBindingMode.UNLOCK_SCREEN |
Shell.KeyBindingMode.LOGIN_SCREEN,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW |
Main.KeybindingMode.LOCK_SCREEN |
Main.KeybindingMode.UNLOCK_SCREEN |
Main.KeybindingMode.LOGIN_SCREEN,
Lang.bind(this, this._startA11ySwitcher));
this.addKeybinding('open-application-menu',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._openAppMenu));
Main.overview.connect('showing', Lang.bind(this, function() {
@@ -199,7 +199,7 @@ const WindowManager = new Lang.Class({
removeKeybinding: function(name) {
if (global.display.remove_keybinding(name))
this.allowKeybinding(name, Shell.KeyBindingMode.NONE);
this.allowKeybinding(name, Main.KeybindingMode.NONE);
},
allowKeybinding: function(name, modes) {
@@ -242,30 +242,22 @@ const WindowManager = new Lang.Class({
}
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
/* scale window down to 0x0.
* maybe TODO: get icon geometry passed through and move the window towards it?
*/
this._minimizing.push(actor);
let xDest, yDest, xScale, yScale;
let [success, geom] = actor.meta_window.get_icon_geometry();
if (success) {
xDest = geom.x;
yDest = geom.y;
xScale = geom.width / actor.width;
yScale = geom.height / actor.height;
} else {
/* scale window down to 0x0. */
let monitor = Main.layoutManager.findMonitorForWindow(actor.meta_window);
xDest = monitor.x;
yDest = monitor.y;
xScale = 0.0;
yScale = 0.0;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
xDest += monitor.width;
}
let monitor = Main.layoutManager.findMonitorForWindow(actor.meta_window);
let xDest = monitor.x;
let yDest = monitor.y;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
xDest += monitor.width;
Tweener.addTween(actor,
{ scale_x: xScale,
scale_y: yScale,
{ scale_x: 0.0,
scale_y: 0.0,
x: xDest,
y: yDest,
time: WINDOW_ANIMATION_TIME,
@@ -502,14 +494,14 @@ const WindowManager = new Lang.Class({
},
_filterKeybinding: function(shellwm, binding) {
if (Main.keybindingMode == Shell.KeyBindingMode.NONE)
if (Main.keybindingMode == Main.KeybindingMode.NONE)
return true;
// There's little sense in implementing a keybinding in mutter and
// not having it work in NORMAL mode; handle this case generically
// so we don't have to explicitly allow all builtin keybindings in
// NORMAL mode.
if (Main.keybindingMode == Shell.KeyBindingMode.NORMAL &&
if (Main.keybindingMode == Main.KeybindingMode.NORMAL &&
binding.is_builtin())
return false;

View File

@@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@@ -29,6 +30,9 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100;
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.shell.overrides';
const BUTTON_LAYOUT_KEY = 'button-layout';
// When calculating a layout, we calculate the scale of windows and the percent
// of the available area the new layout uses. If the values for the new layout,
// when weighted with the values as below, are worse than the previous layout's,
@@ -256,37 +260,23 @@ const WindowClone = new Lang.Class({
_onScroll : function (actor, event) {
let direction = event.get_scroll_direction();
let delta;
if (event.is_pointer_emulated())
return;
if (direction == Clutter.ScrollDirection.DOWN) {
delta = -SCROLL_SCALE_AMOUNT;
} else if (direction == Clutter.ScrollDirection.UP) {
delta = +SCROLL_SCALE_AMOUNT;
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
let [dx, dy] = event.get_scroll_delta();
delta = -dy * 10;
}
if (delta > 0) {
if (direction == Clutter.ScrollDirection.UP) {
if (this._zoomStep == undefined)
this._zoomStart();
if (this._zoomStep < 100) {
this._zoomStep += delta;
this._zoomStep = Math.min(100, this._zoomStep);
this._zoomStep += SCROLL_SCALE_AMOUNT;
this._zoomUpdate();
}
} else if (delta < 0) {
} else if (direction == Clutter.ScrollDirection.DOWN) {
if (this._zoomStep > 0) {
this._zoomStep += delta;
this._zoomStep -= SCROLL_SCALE_AMOUNT;
this._zoomStep = Math.max(0, this._zoomStep);
this._zoomUpdate();
}
if (this._zoomStep <= 0.0)
this._zoomEnd();
}
},
_zoomUpdate : function () {
@@ -451,6 +441,8 @@ const WindowOverlay = new Lang.Class({
this._parentActor = parentActor;
this._hidden = false;
this._settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
this.borderSize = 0;
this.border = new St.Bin({ style_class: 'window-clone-border' });
@@ -543,8 +535,15 @@ const WindowOverlay = new Lang.Class({
let button = this.closeButton;
let title = this.title;
let layout = Meta.prefs_get_button_layout();
let side = layout.left_buttons.indexOf(Meta.ButtonFunction.CLOSE) > -1 ? St.Side.LEFT : St.Side.RIGHT;
let layout = this._settings.get_string(BUTTON_LAYOUT_KEY);
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
let split = layout.split(":");
let side;
if (split[0].indexOf("close") > -1)
side = rtl ? St.Side.RIGHT : St.Side.LEFT;
else
side = rtl ? St.Side.LEFT : St.Side.RIGHT;
let buttonX;
let buttonY = cloneY - (button.height - button._overlap);
@@ -746,10 +745,11 @@ const LayoutStrategy = new Lang.Class({
Name: 'LayoutStrategy',
Abstract: true,
_init: function(monitor, rowSpacing, columnSpacing) {
_init: function(monitor, rowSpacing, columnSpacing, bottomPadding) {
this._monitor = monitor;
this._rowSpacing = rowSpacing;
this._columnSpacing = columnSpacing;
this._bottomPadding = bottomPadding;
},
_newRow: function() {
@@ -774,23 +774,24 @@ const LayoutStrategy = new Lang.Class({
windows: [] };
},
// Computes and returns a fancy scale for @window using the
// Compute the size and fancy scale for @window using the
// base scale, @scale.
_computeWindowScale: function(window, scale) {
// Since we align windows next to each other, the height of the
// thumbnails is much more important to preserve than the width of
// them, so two windows with equal height, but maybe differering
// widths line up.
let ratio = window.actor.height / this._monitor.height;
//
// Returns a list structure: [ scaledWidth, scaledHeight, fancyScale ]
// where scaledWidth and scaledHeight are the window's
// width and height, scaled by fancyScale for convenience.
_computeWindowSizeAndScale: function(window, scale) {
let width = window.actor.width;
let height = window.actor.height;
let ratio;
// The purpose of this manipulation here is to prevent windows
// from getting too small. For something like a calculator window,
// we need to bump up the size just a bit to make sure it looks
// good. We'll use a multiplier of 1.5 for this.
if (width > height)
ratio = width / this._monitor.width;
else
ratio = height / this._monitor.height;
// Map from [0, 1] to [1.5, 1]
let fancyScale = _interpolate(1.5, 1, ratio) * scale;
return fancyScale;
let fancyScale = (2 / (1 + ratio)) * scale;
return [width * fancyScale, height * fancyScale, fancyScale];
},
// Compute the size of each row, by assigning to the properties
@@ -828,7 +829,7 @@ const LayoutStrategy = new Lang.Class({
let area = layout.area;
let hspacing = (layout.maxColumns - 1) * this._columnSpacing;
let vspacing = (layout.numRows - 1) * this._rowSpacing;
let vspacing = (layout.numRows - 1) * this._rowSpacing + this._bottomPadding;
let spacedWidth = area.width - hspacing;
let spacedHeight = area.height - vspacing;
@@ -862,7 +863,7 @@ const LayoutStrategy = new Lang.Class({
y += row.height + this._rowSpacing;
}
let height = y - this._rowSpacing;
let height = y - this._rowSpacing + this._bottomPadding;
let baseY = (area.height - height) / 2;
for (let i = 0; i < rows.length; i++) {
@@ -872,10 +873,7 @@ const LayoutStrategy = new Lang.Class({
for (let j = 0; j < row.windows.length; j++) {
let window = row.windows[j];
let s = this._computeWindowScale(window, scale);
s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE);
let width = window.actor.width * s;
let height = window.actor.height * s;
let [width, height, s] = this._computeWindowSizeAndScale(window, scale);
let y = row.y + row.height - height;
let x = baseX;
@@ -936,9 +934,7 @@ const UnalignedLayoutStrategy = new Lang.Class({
for (; windowIdx < windows.length; windowIdx++) {
let window = windows[windowIdx];
let s = this._computeWindowScale(window, 1);
let width = window.actor.width * s;
let height = window.actor.height * s;
let [width, height] = this._computeWindowSizeAndScale(window, 1);
row.fullHeight = Math.max(row.fullHeight, height);
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
@@ -1004,9 +1000,9 @@ const GridLayoutStrategy = new Lang.Class({
let window = windows[windowIdx];
row.windows.push(window);
let s = this._computeWindowScale(window, 1);
maxWindowWidth = Math.max(maxWindowWidth, window.actor.width * s);
maxWindowHeight = Math.max(maxWindowHeight, window.actor.height * s);
let [width, height] = this._computeWindowSizeAndScale(window, 1);
maxWindowWidth = Math.max(maxWindowWidth, width);
maxWindowHeight = Math.max(maxWindowHeight, height);
}
}
@@ -1041,8 +1037,6 @@ const Workspace = new Lang.Class({
this._windowOverlaysGroup.set_size(0, 0);
this.actor = new St.Widget({ style_class: 'window-picker' });
if (monitorIndex != Main.layoutManager.primaryIndex)
this.actor.add_style_class_name('external-monitor');
this.actor.set_size(0, 0);
this._dropRect = new Clutter.Rectangle({ opacity: 0 });
@@ -1207,7 +1201,7 @@ const Workspace = new Lang.Class({
// Make the window slightly transparent to indicate it's hidden
Tweener.addTween(clone.actor,
{ opacity: 128,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeInQuad'
});
@@ -1629,7 +1623,7 @@ const Workspace = new Lang.Class({
}
},
_computeLayout: function(windows, area, rowSpacing, columnSpacing) {
_computeLayout: function(windows, area, rowSpacing, columnSpacing, bottomPadding) {
// We look for the largest scale that allows us to fit the
// largest row/tallest column on the workspace.
@@ -1645,7 +1639,7 @@ const Workspace = new Lang.Class({
break;
let strategyClass = numRows > 2 ? GridLayoutStrategy : UnalignedLayoutStrategy;
let strategy = new strategyClass(this._monitor, rowSpacing, columnSpacing);
let strategy = new strategyClass(this._monitor, rowSpacing, columnSpacing, bottomPadding);
let layout = { area: area, strategy: strategy, numRows: numRows, numColumns: numColumns };
strategy.computeLayout(windows, layout);
@@ -1677,12 +1671,6 @@ const Workspace = new Lang.Class({
// Window grid spacing
let columnSpacing = node.get_length('-horizontal-spacing');
let rowSpacing = node.get_length('-vertical-spacing');
let padding = {
left: node.get_padding(St.Side.LEFT),
top: node.get_padding(St.Side.TOP),
bottom: node.get_padding(St.Side.BOTTOM),
right: node.get_padding(St.Side.RIGHT),
};
if (!totalWindows)
return [];
@@ -1697,25 +1685,19 @@ const Workspace = new Lang.Class({
[leftBorder, rightBorder] = overlay.chromeWidths();
} else {
[closeButtonHeight, captionHeight] = [0, 0];
[leftBorder, rightBorder] = [0, 0];
}
rowSpacing += captionHeight;
columnSpacing += (rightBorder + leftBorder) / 2;
padding.top += closeButtonHeight;
padding.bottom += captionHeight;
padding.left += leftBorder;
padding.right += rightBorder;
columnSpacing += rightBorder;
let area = {
x: this._x + padding.left,
y: this._y + padding.top,
width: this._width - padding.left - padding.right,
height: this._height - padding.top - padding.bottom,
};
let area = { x: this._x, y: this._y, width: this._width, height: this._height };
area.y += closeButtonHeight;
area.height -= closeButtonHeight;
area.x += leftBorder;
area.width -= leftBorder;
if (!this._currentLayout)
this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing);
this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing, captionHeight);
let layout = this._currentLayout;
let strategy = layout.strategy;

View File

@@ -170,8 +170,7 @@ const WorkspaceThumbnail = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._background = new Meta.BackgroundActor({ screen: global.screen,
settings: Main.background });
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
this._contents.add_actor(this._background);
let monitor = Main.layoutManager.primaryMonitor;

View File

@@ -21,7 +21,6 @@ eu
fa
fi
fr
fur
ga
gl
gu

View File

@@ -11,7 +11,6 @@ js/misc/util.js
js/ui/appDisplay.js
js/ui/appFavorites.js
js/ui/calendar.js
js/ui/components/automountManager.js
js/ui/components/autorunManager.js
js/ui/components/keyring.js
js/ui/components/networkAgent.js

237
po/ar.po
View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-12-23 18:34+0200\n"
"POT-Creation-Date: 2012-12-09 04:45+0200\n"
"PO-Revision-Date: 2012-12-09 04:52+0200\n"
"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
"Language-Team: Arabic <doc@arabeyes.org>\n"
@@ -365,8 +365,8 @@ msgstr "نافذة الولوج"
msgid "Power"
msgstr "الطاقة"
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:675 ../js/ui/userMenu.js:679
#: ../js/ui/userMenu.js:790
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:674 ../js/ui/userMenu.js:678
#: ../js/ui/userMenu.js:789
msgid "Suspend"
msgstr "علّق"
@@ -374,8 +374,8 @@ msgstr "علّق"
msgid "Restart"
msgstr "أعِد التشغيل"
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:677
#: ../js/ui/userMenu.js:679 ../js/ui/userMenu.js:789
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:676
#: ../js/ui/userMenu.js:678 ../js/ui/userMenu.js:788
msgid "Power Off"
msgstr "أطفئ الحاسوب"
@@ -410,19 +410,27 @@ msgid "Execution of '%s' failed:"
msgstr "فشل تنفيذ '%s':"
#. Translators: Filter to display all applications
#: ../js/ui/appDisplay.js:258
#: ../js/ui/appDisplay.js:259
msgid "All"
msgstr "الكل"
#: ../js/ui/appDisplay.js:666
#: ../js/ui/appDisplay.js:318
msgid "APPLICATIONS"
msgstr "التطبيقات"
#: ../js/ui/appDisplay.js:375
msgid "SETTINGS"
msgstr "الإعدادات"
#: ../js/ui/appDisplay.js:679
msgid "New Window"
msgstr "نافذة جديدة"
#: ../js/ui/appDisplay.js:669 ../js/ui/dash.js:289
#: ../js/ui/appDisplay.js:682 ../js/ui/dash.js:289
msgid "Remove from Favorites"
msgstr "أزِل من المفضّلة"
#: ../js/ui/appDisplay.js:670
#: ../js/ui/appDisplay.js:683
msgid "Add to Favorites"
msgstr "أضِف إلى المفضّلة"
@@ -439,19 +447,19 @@ msgstr "أُزيل %s من مفضّلتك."
#. Translators: Shown in calendar event list for all day events
#. * Keep it short, best if you can use less then 10 characters
#.
#: ../js/ui/calendar.js:61
#: ../js/ui/calendar.js:62
msgctxt "event list time"
msgid "All Day"
msgstr "طوال اليوم"
#. Translators: Shown in calendar event list, if 24h format
#: ../js/ui/calendar.js:66
#: ../js/ui/calendar.js:67
msgctxt "event list time"
msgid "%H:%M"
msgstr "%H:%M"
#. Transators: Shown in calendar event list, if 12h format
#: ../js/ui/calendar.js:73
#: ../js/ui/calendar.js:74
msgctxt "event list time"
msgid "%l:%M %p"
msgstr "%l:%M %p"
@@ -461,43 +469,43 @@ msgstr "%l:%M %p"
#. * NOTE: These grid abbreviations are always shown together
#. * and in order, e.g. "S M T W T F S".
#.
#: ../js/ui/calendar.js:104
#: ../js/ui/calendar.js:114
msgctxt "grid sunday"
msgid "S"
msgstr "ح"
#. Translators: Calendar grid abbreviation for Monday
#: ../js/ui/calendar.js:106
#: ../js/ui/calendar.js:116
msgctxt "grid monday"
msgid "M"
msgstr "ن"
#. Translators: Calendar grid abbreviation for Tuesday
#: ../js/ui/calendar.js:108
#: ../js/ui/calendar.js:118
msgctxt "grid tuesday"
msgid "T"
msgstr "ث"
#. Translators: Calendar grid abbreviation for Wednesday
#: ../js/ui/calendar.js:110
#: ../js/ui/calendar.js:120
msgctxt "grid wednesday"
msgid "W"
msgstr "ر"
#. Translators: Calendar grid abbreviation for Thursday
#: ../js/ui/calendar.js:112
#: ../js/ui/calendar.js:122
msgctxt "grid thursday"
msgid "T"
msgstr "خ"
#. Translators: Calendar grid abbreviation for Friday
#: ../js/ui/calendar.js:114
#: ../js/ui/calendar.js:124
msgctxt "grid friday"
msgid "F"
msgstr "ج"
#. Translators: Calendar grid abbreviation for Saturday
#: ../js/ui/calendar.js:116
#: ../js/ui/calendar.js:126
msgctxt "grid saturday"
msgid "S"
msgstr "س"
@@ -508,77 +516,77 @@ msgstr "س"
#. * so they need to be unique (e.g. Tuesday and Thursday cannot
#. * both be 'T').
#.
#: ../js/ui/calendar.js:129
#: ../js/ui/calendar.js:139
msgctxt "list sunday"
msgid "Su"
msgstr "الأحد"
#. Translators: Event list abbreviation for Monday
#: ../js/ui/calendar.js:131
#: ../js/ui/calendar.js:141
msgctxt "list monday"
msgid "M"
msgstr "الاثنين"
#. Translators: Event list abbreviation for Tuesday
#: ../js/ui/calendar.js:133
#: ../js/ui/calendar.js:143
msgctxt "list tuesday"
msgid "T"
msgstr "الثلاثاء"
#. Translators: Event list abbreviation for Wednesday
#: ../js/ui/calendar.js:135
#: ../js/ui/calendar.js:145
msgctxt "list wednesday"
msgid "W"
msgstr "الأربعاء"
#. Translators: Event list abbreviation for Thursday
#: ../js/ui/calendar.js:137
#: ../js/ui/calendar.js:147
msgctxt "list thursday"
msgid "Th"
msgstr "الخميس"
#. Translators: Event list abbreviation for Friday
#: ../js/ui/calendar.js:139
#: ../js/ui/calendar.js:149
msgctxt "list friday"
msgid "F"
msgstr "الجمعة"
#. Translators: Event list abbreviation for Saturday
#: ../js/ui/calendar.js:141
#: ../js/ui/calendar.js:151
msgctxt "list saturday"
msgid "S"
msgstr "السبت"
#. Translators: Text to show if there are no events
#: ../js/ui/calendar.js:674
#: ../js/ui/calendar.js:700
msgid "Nothing Scheduled"
msgstr "الجدول خال"
#. Translators: Shown on calendar heading when selected day occurs on current year
#: ../js/ui/calendar.js:690
#: ../js/ui/calendar.js:716
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A %d %B"
#. Translators: Shown on calendar heading when selected day occurs on different year
#: ../js/ui/calendar.js:693
#: ../js/ui/calendar.js:719
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A %d %B %Y"
#: ../js/ui/calendar.js:703
#: ../js/ui/calendar.js:729
msgid "Today"
msgstr "اليوم"
#: ../js/ui/calendar.js:707
#: ../js/ui/calendar.js:733
msgid "Tomorrow"
msgstr "غدا"
#: ../js/ui/calendar.js:718
#: ../js/ui/calendar.js:744
msgid "This week"
msgstr "هذا الأسبوع"
#: ../js/ui/calendar.js:726
#: ../js/ui/calendar.js:752
msgid "Next week"
msgstr "الأسبوع القادم"
@@ -940,7 +948,7 @@ msgstr "أظهر الحساب"
msgid "Unknown reason"
msgstr "السبب غير معروف"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:81
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:87
msgid "Windows"
msgstr "النوافذ"
@@ -1080,7 +1088,7 @@ msgstr "هل تريد تنزيل وتثبيت '%s' من extensions.gnome.org؟"
msgid "tray"
msgstr "لوحة النظام"
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:309
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:195
#: ../js/ui/status/power.js:205
msgid "Keyboard"
msgstr "لوحة المفاتيح"
@@ -1107,9 +1115,7 @@ msgstr "اظهر الأخطاء"
msgid "Enabled"
msgstr "مفعّل"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:767 ../src/gvc/gvc-mixer-control.c:1830
#: ../js/ui/lookingGlass.js:767
msgid "Disabled"
msgstr "معطّل"
@@ -1141,15 +1147,15 @@ msgstr "افتح"
msgid "Remove"
msgstr "أزِل"
#: ../js/ui/messageTray.js:1552
#: ../js/ui/messageTray.js:1551
msgid "No Messages"
msgstr "لا رسائل"
#: ../js/ui/messageTray.js:1570
#: ../js/ui/messageTray.js:1568
msgid "Message Tray"
msgstr "لوحة الرسائل"
#: ../js/ui/messageTray.js:2639
#: ../js/ui/messageTray.js:2635
msgid "System Information"
msgstr "معلومات النظام"
@@ -1158,11 +1164,11 @@ msgctxt "program"
msgid "Unknown"
msgstr "غير معروف"
#: ../js/ui/overview.js:92
#: ../js/ui/overview.js:95
msgid "Undo"
msgstr "تراجع"
#: ../js/ui/overview.js:139
#: ../js/ui/overview.js:144
msgid "Overview"
msgstr "نظرة عامة"
@@ -1170,13 +1176,13 @@ msgstr "نظرة عامة"
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: ../js/ui/overview.js:218
#: ../js/ui/overview.js:221
msgid "Type to search..."
msgstr "اكتب نصا للبحث عنه..."
#. Translators: this is the name of the dock/favorites area on
#. the left of the overview
#: ../js/ui/overview.js:236
#: ../js/ui/overview.js:242
msgid "Dash"
msgstr "الشريط"
@@ -1199,7 +1205,7 @@ msgstr "الشريط العلوي"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:725
#: ../js/ui/popupMenu.js:732
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
@@ -1239,15 +1245,15 @@ msgstr[3] "%d تنبيهات جديدة"
msgstr[4] "%d تنبيها جديدا"
msgstr[5] "%d تنبيه جديد"
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:781
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:780
msgid "Lock"
msgstr "أوصِد"
#: ../js/ui/searchDisplay.js:403
#: ../js/ui/searchDisplay.js:277
msgid "Searching..."
msgstr "يبحث..."
#: ../js/ui/searchDisplay.js:451
#: ../js/ui/searchDisplay.js:325
msgid "No results."
msgstr "لا نتائج."
@@ -1363,7 +1369,7 @@ msgid "disconnecting..."
msgstr "يقطع الاتّصال..."
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:442
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:1453
msgid "connecting..."
msgstr "يتّصل..."
@@ -1379,7 +1385,7 @@ msgstr "إعدادات لوحة المفاتيح"
msgid "Mouse Settings"
msgstr "إعدادات الفأرة"
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:314
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:270
msgid "Sound Settings"
msgstr "إعدادات الصوت"
@@ -1443,15 +1449,15 @@ msgstr "من فضلك أدخل الرقم المذكور على الجهاز."
msgid "OK"
msgstr "حسنا"
#: ../js/ui/status/keyboard.js:363
#: ../js/ui/status/keyboard.js:228
msgid "Show Keyboard Layout"
msgstr "أظهر تخطيط لوحة المفاتيح"
#: ../js/ui/status/keyboard.js:368
#: ../js/ui/status/keyboard.js:233
msgid "Region and Language Settings"
msgstr "إعدادات الإقليم واللغة"
#: ../js/ui/status/lockScreenMenu.js:43
#: ../js/ui/status/lockScreenMenu.js:18
msgid "Volume, network, battery"
msgstr "الصوت، الشبكة، البطارية"
@@ -1471,7 +1477,7 @@ msgid "unmanaged"
msgstr "غير مُدار"
#. Translators: this is for network connections that require some kind of key or password
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1467
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1456
msgid "authentication required"
msgstr "الاستيثاق مطلوب"
@@ -1492,72 +1498,72 @@ msgstr "الكبل مفصول"
msgid "unavailable"
msgstr "غير متاح"
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1469
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1458
msgid "connection failed"
msgstr "فشل الاتصال"
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1403
#: ../js/ui/status/network.js:1545
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1392
#: ../js/ui/status/network.js:1534
msgid "More..."
msgstr "المزيد..."
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1333
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1322
msgid "Connected (private)"
msgstr "متّصل (شخصي)"
#: ../js/ui/status/network.js:641
#: ../js/ui/status/network.js:619
msgid "Auto Ethernet"
msgstr "إيثرنت تلقائي"
#: ../js/ui/status/network.js:688
#: ../js/ui/status/network.js:677
msgid "Auto broadband"
msgstr "شبكة هاتف محمول تلقائية"
#: ../js/ui/status/network.js:691
#: ../js/ui/status/network.js:680
msgid "Auto dial-up"
msgstr "اتصال هاتفي تلقائي"
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:820 ../js/ui/status/network.js:1350
#: ../js/ui/status/network.js:809 ../js/ui/status/network.js:1339
#, c-format
msgid "Auto %s"
msgstr "%s تلقائي"
#: ../js/ui/status/network.js:822
#: ../js/ui/status/network.js:811
msgid "Auto bluetooth"
msgstr "بلوتوث تلقائي"
#: ../js/ui/status/network.js:1352
#: ../js/ui/status/network.js:1341
msgid "Auto wireless"
msgstr "لاسلكي تلقائي"
#: ../js/ui/status/network.js:1595
#: ../js/ui/status/network.js:1584
msgid "Enable networking"
msgstr "فعّل الشبكات"
#: ../js/ui/status/network.js:1627
#: ../js/ui/status/network.js:1616
msgid "Wi-Fi"
msgstr "واي فاي"
#: ../js/ui/status/network.js:1646
#: ../js/ui/status/network.js:1635
msgid "Network Settings"
msgstr "إعدادات الشّبكة"
#: ../js/ui/status/network.js:1692
#: ../js/ui/status/network.js:1679
msgid "Network Manager"
msgstr "مدير الشبكة"
#: ../js/ui/status/network.js:1774
#: ../js/ui/status/network.js:1761
msgid "Connection failed"
msgstr "فشل الاتصال"
#: ../js/ui/status/network.js:1775
#: ../js/ui/status/network.js:1762
msgid "Activation of network connection failed"
msgstr "فشل تفعيل اتصال الشبكة"
#: ../js/ui/status/network.js:2092
#: ../js/ui/status/network.js:2079
msgid "Networking is disabled"
msgstr "عُطّلت الشبكات"
@@ -1675,11 +1681,11 @@ msgid "Unknown"
msgstr "غير معروف"
#. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:247 ../js/ui/status/volume.js:295
#: ../js/ui/status/volume.js:50 ../js/ui/status/volume.js:251
msgid "Volume"
msgstr "شدة الصوت"
#: ../js/ui/status/volume.js:256
#: ../js/ui/status/volume.js:62
msgid "Microphone"
msgstr "ميكروفون"
@@ -1715,31 +1721,31 @@ msgstr "ساكن"
msgid "Offline"
msgstr "غير متصل"
#: ../js/ui/userMenu.js:755
#: ../js/ui/userMenu.js:754
msgid "Notifications"
msgstr "التنبيهات"
#: ../js/ui/userMenu.js:763
#: ../js/ui/userMenu.js:762
msgid "Settings"
msgstr "الإعدادات"
#: ../js/ui/userMenu.js:771
#: ../js/ui/userMenu.js:770
msgid "Switch User"
msgstr "بدّل المستخدم"
#: ../js/ui/userMenu.js:776
#: ../js/ui/userMenu.js:775
msgid "Log Out"
msgstr "اخرج"
#: ../js/ui/userMenu.js:796
#: ../js/ui/userMenu.js:795
msgid "Install Updates & Restart"
msgstr "ثبّت التحديثات وأعد التشغيل"
#: ../js/ui/userMenu.js:814
#: ../js/ui/userMenu.js:813
msgid "Your chat status will be set to busy"
msgstr "ستُجعل حالة اتصالك ”مشغول“"
#: ../js/ui/userMenu.js:815
#: ../js/ui/userMenu.js:814
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@@ -1747,15 +1753,15 @@ msgstr ""
"التنبيهات معطلة الآن، بما فيها رسائل المحادثة. حالة اتصالك تغيرت حتى يعلم "
"الآخرون أنك قد لا ترى رسائلهم."
#: ../js/ui/viewSelector.js:85
#: ../js/ui/viewSelector.js:91
msgid "Applications"
msgstr "التطبيقات"
#: ../js/ui/viewSelector.js:89
#: ../js/ui/viewSelector.js:95
msgid "Search"
msgstr "ابحث"
#: ../js/ui/wanda.js:92
#: ../js/ui/wanda.js:94
#, c-format
msgid ""
"Sorry, no wisdom for you today:\n"
@@ -1764,11 +1770,15 @@ msgstr ""
"عذرًا, لا حكمة لك اليوم:\n"
"%s"
#: ../js/ui/wanda.js:96
#: ../js/ui/wanda.js:98
#, c-format
msgid "%s the Oracle says"
msgstr "يقول الحكيم %s"
#: ../js/ui/wanda.js:139
msgid "Your favorite Easter Egg"
msgstr ""
#: ../js/ui/windowAttentionHandler.js:19
#, c-format
msgid "'%s' is ready"
@@ -1778,36 +1788,6 @@ msgstr "'%s' جاهز"
msgid "Evolution Calendar"
msgstr "تقويم إيفُليوشِن"
#. translators:
#. * The number of sound outputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1837
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
msgstr[0] "لا مخرَج"
msgstr[1] "مخرَج واحد"
msgstr[2] "مخرَجين"
msgstr[3] "%u مخارج"
msgstr[4] "%u مخرجا"
msgstr[5] "%u مخرج"
#. translators:
#. * The number of sound inputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1847
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "لا مدخل"
msgstr[1] "مدخل واحد"
msgstr[2] "مدخلين"
msgstr[3] "%u مداخل"
msgstr[4] "%u مدخلا"
msgstr[5] "%u مدخل"
#: ../src/gvc/gvc-mixer-control.c:2371
msgid "System Sounds"
msgstr "أصوات النظام"
#: ../src/main.c:332
msgid "Print version"
msgstr "اطبع الإصدارة"
@@ -1849,12 +1829,6 @@ msgstr "المبدئي"
msgid "Authentication dialog was dismissed by the user"
msgstr "أغلق المستخدم مربع الاستيثاق الحِواري"
#~ msgid "APPLICATIONS"
#~ msgstr "التطبيقات"
#~ msgid "SETTINGS"
#~ msgstr "الإعدادات"
#~ msgid "Subscription request"
#~ msgstr "طلب اشتراك"
@@ -1903,6 +1877,27 @@ msgstr "أغلق المستخدم مربع الاستيثاق الحِواري"
#~ msgid "System Settings"
#~ msgstr "إعدادات النظام"
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "لا مخرَج"
#~ msgstr[1] "مخرَج واحد"
#~ msgstr[2] "مخرَجين"
#~ msgstr[3] "%u مخارج"
#~ msgstr[4] "%u مخرجا"
#~ msgstr[5] "%u مخرج"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "لا مدخل"
#~ msgstr[1] "مدخل واحد"
#~ msgstr[2] "مدخلين"
#~ msgstr[3] "%u مداخل"
#~ msgstr[4] "%u مدخلا"
#~ msgstr[5] "%u مدخل"
#~ msgid "System Sounds"
#~ msgstr "أصوات النظام"
#~ msgid "Failed to unmount '%s'"
#~ msgstr "فشل فصْل '%s'"

475
po/as.po

File diff suppressed because it is too large Load Diff

727
po/be.po

File diff suppressed because it is too large Load Diff

880
po/de.po

File diff suppressed because it is too large Load Diff

594
po/es.po

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ msgstr ""
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-12-09 13:03+0000\n"
"PO-Revision-Date: 2012-12-19 16:47+0300\n"
"PO-Revision-Date: 2012-12-18 17:13+0300\n"
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
"Language-Team: Estonian <>\n"
"Language: et\n"
@@ -153,8 +153,8 @@ msgid ""
"state of the checkbox."
msgstr ""
"Shell küsib parooli, kui haagitakse krüpteeritud seade või kaugfailisüsteem. "
"Kui parooli on võimalik salvestada edaspidiseks kasutuseks, näidatakse "
"'Salvesta parool' märkeruutu. See võti määrab selle märkeruudu vaikimisi "
"Kui parooli on võimalik salvestada järgmise kasutuse jaoks, näidatakse "
"\"Jäta parool meelde\" märkeruutu. See võti määrab märkeruudu vaikimisi "
"oleku."
msgid "Show the week date in the calendar"
@@ -257,9 +257,9 @@ msgid ""
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
"only' (shows only the application icon) or 'both'."
msgstr ""
"Seadistab, kuidas aknaid aknavahetajas kuvatakse. Sobivad väärtused on "
"'thumbnail-only' (näidatakse ainult pisipilti aknast), 'app-icon-"
"only' (näidatakse ainult akna ikooni) või 'both' (mõlemad)."
"Seadistab, kuidas aknaid akendevahetajas kuvatakse. Sobivad väärtused on "
"'thumbnail-only' (näidatakse ainult pisipilti), 'app-icon-only' (näidatakse "
"ainult rakenduse ikooni) või 'both' (näidatakse mõlemaid)."
msgid "Attach modal dialog to the parent window"
msgstr "Modaaldialoog kuulub vanemakna juurde"

2083
po/eu.po

File diff suppressed because it is too large Load Diff

1874
po/fur.po

File diff suppressed because it is too large Load Diff

632
po/gl.po

File diff suppressed because it is too large Load Diff

779
po/he.po

File diff suppressed because it is too large Load Diff

873
po/hu.po

File diff suppressed because it is too large Load Diff

888
po/it.po

File diff suppressed because it is too large Load Diff

1832
po/kk.po

File diff suppressed because it is too large Load Diff

962
po/lt.po

File diff suppressed because it is too large Load Diff

471
po/nb.po

File diff suppressed because it is too large Load Diff

705
po/nl.po

File diff suppressed because it is too large Load Diff

477
po/pa.po

File diff suppressed because it is too large Load Diff

839
po/pl.po

File diff suppressed because it is too large Load Diff

944
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

344
po/sk.po
View File

@@ -10,8 +10,8 @@ msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-01-08 18:17+0000\n"
"PO-Revision-Date: 2013-01-01 17:50+0100\n"
"POT-Creation-Date: 2012-12-09 02:53+0000\n"
"PO-Revision-Date: 2012-11-19 22:23+0100\n"
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
"Language: sk\n"
@@ -40,7 +40,7 @@ msgstr "Zobrazí lištu správ"
#: ../data/50-gnome-shell-system.xml.in.h:3
msgid "Focus the active notification"
msgstr "Zamerať aktívne oznámenie"
msgstr "Zamerať na aktívne oznámenia"
# tooltip
#: ../data/50-gnome-shell-system.xml.in.h:4
@@ -166,23 +166,20 @@ msgstr ""
"s jedným používateľom alebo jednou reláciou."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
#, fuzzy
#| msgid "Always show the 'Log out' menuitem in the user menu."
msgid "Show full name in the user menu"
msgstr "Zobraziť celé meno v ponuke používateľa"
msgstr "Vždy zobraziť položku „Odhlásiť sa“ v ponuke používateľa"
# description
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
msgid "Whether the users full name is shown in the user menu or not."
msgstr "Určuje, či bude alebo nebude zobrazené celé meno v ponuke používateľa."
msgstr ""
# summary
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid ""
"Whether to remember password for mounting encrypted or remote filesystems"
msgstr ""
"Určiť, či bude zapamätané heslo pre pripojenie zašifrovaných alebo "
"prenosných súborových systémov"
# description
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid ""
"The shell will request a password when an encrypted device or a remote "
@@ -190,10 +187,6 @@ msgid ""
"'Remember Password' checkbox will be present. This key sets the default "
"state of the checkbox."
msgstr ""
"Shell bude po pripojení zašifrovaného alebo prenosného súborového systému "
"požadovať heslo. Ak bude možné toto heslo uložiť pre neskoršie použitie, "
"zobrazí sa zaškrtávacie pole „Zapamätať heslo“. Tento kľúč nastaví "
"predvolený stav zaškrtávacieho poľa."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Show the week date in the calendar"
@@ -316,11 +309,11 @@ msgstr ""
"základe aktuálneho dátumu a použije túto príponu. Pri nahrávaní do iného "
"formátu kontajneru by mala byť zmenená."
# PM: tento preklad podľa mňa nezodpovedá nasledujúcemu dlhému popisu nastavenia. Ide skor o režim tvorby ikon (z) aplikácií
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
#, fuzzy
#| msgid "Open the application menu"
msgid "The application icon mode."
msgstr "Režim aplikácií s ikonami."
msgstr "Otvorí ponuku aplikácií"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
msgid ""
@@ -328,9 +321,6 @@ msgid ""
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
"only' (shows only the application icon) or 'both'."
msgstr ""
"Konfiguruje, ako sa majú zobraziť okná v prepínači. Platné možnosti sú "
"„thumbnail-only“ (zobrazí miniatúru okna), „app-icon-only“ (zobrazí iba "
"ikonu aplikácie) alebo „both“ (zobrazí oboje)."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
msgid "Attach modal dialog to the parent window"
@@ -378,11 +368,11 @@ msgstr "Rozšírenie"
msgid "Select an extension to configure using the combobox above."
msgstr "Použitím ponuky vyberte rozšírenie na nastavenie"
#: ../js/gdm/loginDialog.js:566
#: ../js/gdm/loginDialog.js:565
msgid "Session..."
msgstr "Relácia…"
#: ../js/gdm/loginDialog.js:723
#: ../js/gdm/loginDialog.js:722
msgctxt "title"
msgid "Sign In"
msgstr "Prihlásenie"
@@ -391,35 +381,35 @@ msgstr "Prihlásenie"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: ../js/gdm/loginDialog.js:787
#: ../js/gdm/loginDialog.js:786
msgid "Not listed?"
msgstr "Nie ste v zozname?"
#: ../js/gdm/loginDialog.js:963 ../js/ui/components/networkAgent.js:137
#: ../js/gdm/loginDialog.js:962 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:413 ../js/ui/unlockDialog.js:178
msgid "Cancel"
msgstr "Zrušiť"
#: ../js/gdm/loginDialog.js:979
#: ../js/gdm/loginDialog.js:978
msgctxt "button"
msgid "Sign In"
msgstr "Prihlásiť sa"
#: ../js/gdm/loginDialog.js:979
#: ../js/gdm/loginDialog.js:978
msgid "Next"
msgstr "Ďalej"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: ../js/gdm/loginDialog.js:1087 ../js/ui/components/networkAgent.js:260
#: ../js/gdm/loginDialog.js:1086 ../js/ui/components/networkAgent.js:260
#: ../js/ui/components/networkAgent.js:278
msgid "Username: "
msgstr "Používateľské meno: "
#: ../js/gdm/loginDialog.js:1383
#: ../js/gdm/loginDialog.js:1382
msgid "Login Window"
msgstr "Prihlasovacie okno"
@@ -428,8 +418,8 @@ msgstr "Prihlasovacie okno"
msgid "Power"
msgstr "Napájanie"
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:675 ../js/ui/userMenu.js:679
#: ../js/ui/userMenu.js:790
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:674 ../js/ui/userMenu.js:678
#: ../js/ui/userMenu.js:789
msgid "Suspend"
msgstr "Uspať"
@@ -437,8 +427,8 @@ msgstr "Uspať"
msgid "Restart"
msgstr "Reštartovať"
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:677
#: ../js/ui/userMenu.js:679 ../js/ui/userMenu.js:789
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:676
#: ../js/ui/userMenu.js:678 ../js/ui/userMenu.js:788
msgid "Power Off"
msgstr "Vypnúť"
@@ -473,19 +463,27 @@ msgid "Execution of '%s' failed:"
msgstr "Spustenie „%s“ zlyhalo:"
#. Translators: Filter to display all applications
#: ../js/ui/appDisplay.js:258
#: ../js/ui/appDisplay.js:259
msgid "All"
msgstr "Všetky"
#: ../js/ui/appDisplay.js:666
#: ../js/ui/appDisplay.js:318
msgid "APPLICATIONS"
msgstr "APLIKÁCIE"
#: ../js/ui/appDisplay.js:375
msgid "SETTINGS"
msgstr "NASTAVENIA"
#: ../js/ui/appDisplay.js:679
msgid "New Window"
msgstr "Nové okno"
#: ../js/ui/appDisplay.js:669 ../js/ui/dash.js:289
#: ../js/ui/appDisplay.js:682 ../js/ui/dash.js:289
msgid "Remove from Favorites"
msgstr "Odstrániť z obľúbených"
#: ../js/ui/appDisplay.js:670
#: ../js/ui/appDisplay.js:683
msgid "Add to Favorites"
msgstr "Pridať do obľúbených"
@@ -502,19 +500,19 @@ msgstr "Program %s bol odstránený z obľúbených."
#. Translators: Shown in calendar event list for all day events
#. * Keep it short, best if you can use less then 10 characters
#.
#: ../js/ui/calendar.js:61
#: ../js/ui/calendar.js:62
msgctxt "event list time"
msgid "All Day"
msgstr "Celý deň"
#. Translators: Shown in calendar event list, if 24h format
#: ../js/ui/calendar.js:66
#: ../js/ui/calendar.js:67
msgctxt "event list time"
msgid "%H:%M"
msgstr "%H:%M"
#. Transators: Shown in calendar event list, if 12h format
#: ../js/ui/calendar.js:73
#: ../js/ui/calendar.js:74
msgctxt "event list time"
msgid "%l:%M %p"
msgstr "%l:%M %p"
@@ -524,43 +522,43 @@ msgstr "%l:%M %p"
#. * NOTE: These grid abbreviations are always shown together
#. * and in order, e.g. "S M T W T F S".
#.
#: ../js/ui/calendar.js:104
#: ../js/ui/calendar.js:114
msgctxt "grid sunday"
msgid "S"
msgstr "Ne"
#. Translators: Calendar grid abbreviation for Monday
#: ../js/ui/calendar.js:106
#: ../js/ui/calendar.js:116
msgctxt "grid monday"
msgid "M"
msgstr "Po"
#. Translators: Calendar grid abbreviation for Tuesday
#: ../js/ui/calendar.js:108
#: ../js/ui/calendar.js:118
msgctxt "grid tuesday"
msgid "T"
msgstr "Ut"
#. Translators: Calendar grid abbreviation for Wednesday
#: ../js/ui/calendar.js:110
#: ../js/ui/calendar.js:120
msgctxt "grid wednesday"
msgid "W"
msgstr "St"
#. Translators: Calendar grid abbreviation for Thursday
#: ../js/ui/calendar.js:112
#: ../js/ui/calendar.js:122
msgctxt "grid thursday"
msgid "T"
msgstr "Št"
#. Translators: Calendar grid abbreviation for Friday
#: ../js/ui/calendar.js:114
#: ../js/ui/calendar.js:124
msgctxt "grid friday"
msgid "F"
msgstr "Pi"
#. Translators: Calendar grid abbreviation for Saturday
#: ../js/ui/calendar.js:116
#: ../js/ui/calendar.js:126
msgctxt "grid saturday"
msgid "S"
msgstr "So"
@@ -571,77 +569,77 @@ msgstr "So"
#. * so they need to be unique (e.g. Tuesday and Thursday cannot
#. * both be 'T').
#.
#: ../js/ui/calendar.js:129
#: ../js/ui/calendar.js:139
msgctxt "list sunday"
msgid "Su"
msgstr "Ne"
#. Translators: Event list abbreviation for Monday
#: ../js/ui/calendar.js:131
#: ../js/ui/calendar.js:141
msgctxt "list monday"
msgid "M"
msgstr "Po"
#. Translators: Event list abbreviation for Tuesday
#: ../js/ui/calendar.js:133
#: ../js/ui/calendar.js:143
msgctxt "list tuesday"
msgid "T"
msgstr "Ut"
#. Translators: Event list abbreviation for Wednesday
#: ../js/ui/calendar.js:135
#: ../js/ui/calendar.js:145
msgctxt "list wednesday"
msgid "W"
msgstr "St"
#. Translators: Event list abbreviation for Thursday
#: ../js/ui/calendar.js:137
#: ../js/ui/calendar.js:147
msgctxt "list thursday"
msgid "Th"
msgstr "Št"
#. Translators: Event list abbreviation for Friday
#: ../js/ui/calendar.js:139
#: ../js/ui/calendar.js:149
msgctxt "list friday"
msgid "F"
msgstr "Pi"
#. Translators: Event list abbreviation for Saturday
#: ../js/ui/calendar.js:141
#: ../js/ui/calendar.js:151
msgctxt "list saturday"
msgid "S"
msgstr "So"
#. Translators: Text to show if there are no events
#: ../js/ui/calendar.js:674
#: ../js/ui/calendar.js:700
msgid "Nothing Scheduled"
msgstr "Žiadne naplánované udalosti"
#. Translators: Shown on calendar heading when selected day occurs on current year
#: ../js/ui/calendar.js:690
#: ../js/ui/calendar.js:716
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %e. %B"
#. Translators: Shown on calendar heading when selected day occurs on different year
#: ../js/ui/calendar.js:693
#: ../js/ui/calendar.js:719
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A, %e. %B %Y"
#: ../js/ui/calendar.js:703
#: ../js/ui/calendar.js:729
msgid "Today"
msgstr "Dnes"
#: ../js/ui/calendar.js:707
#: ../js/ui/calendar.js:733
msgid "Tomorrow"
msgstr "Zajtra"
#: ../js/ui/calendar.js:718
#: ../js/ui/calendar.js:744
msgid "This week"
msgstr "Tento týždeň"
#: ../js/ui/calendar.js:726
#: ../js/ui/calendar.js:752
msgid "Next week"
msgstr "Ďalší týždeň"
@@ -659,11 +657,11 @@ msgstr "Otvoriť pomocou programu %s"
msgid "Eject"
msgstr "Vysunúť"
#: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268
#: ../js/ui/components/keyring.js:86 ../js/ui/components/polkitAgent.js:260
msgid "Password:"
msgstr "Heslo:"
#: ../js/ui/components/keyring.js:101
#: ../js/ui/components/keyring.js:105
msgid "Type again:"
msgstr "Zadajte znovu:"
@@ -752,7 +750,7 @@ msgstr "Požaduje sa overenie totožnosti"
msgid "Administrator"
msgstr "Správca"
#: ../js/ui/components/polkitAgent.js:165
#: ../js/ui/components/polkitAgent.js:166
msgid "Authenticate"
msgstr "Overiť totožnosť"
@@ -760,7 +758,7 @@ msgstr "Overiť totožnosť"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383
#: ../js/ui/components/polkitAgent.js:248 ../js/ui/shellMountOperation.js:383
msgid "Sorry, that didn't work. Please try again."
msgstr "Prepáčte, ale nezabralo to. Skúste to, prosím, znova."
@@ -789,7 +787,7 @@ msgstr "Prenos súborov"
#: ../js/ui/components/telepathyClient.js:417
msgid "Chat"
msgstr "Rozhovor"
msgstr ""
#: ../js/ui/components/telepathyClient.js:477
msgid "Unmute"
@@ -803,25 +801,28 @@ msgstr "Stlmiť"
#: ../js/ui/components/telepathyClient.js:931
#, no-c-format
msgid "<b>Yesterday</b>, <b>%H:%M</b>"
msgstr "<b>Včera</b> o <b>%H:%M</b>"
msgstr ""
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30
#: ../js/ui/components/telepathyClient.js:937
#, no-c-format
#, fuzzy, no-c-format
#| msgid "<b>%H:%M</b> on <b>%A</b>"
msgid "<b>%A</b>, <b>%H:%M</b>"
msgstr "v <b>%A</b> o <b>%H:%M</b>"
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"
#: ../js/ui/components/telepathyClient.js:942
#, no-c-format
#, fuzzy, no-c-format
#| msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>"
msgstr "<b>%e.</b> <b>%B</b> o <b>%H:%M</b>"
msgstr "v <b>%A</b> o <b>%H:%M</b>, <b>%e.</b> <b>%B</b>"
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"
#: ../js/ui/components/telepathyClient.js:946
#, no-c-format
#, fuzzy, no-c-format
#| msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "
msgstr "<b>%e.</b> <b>%B</b> <b>%Y</b> o <b>%H:%M</b>"
msgstr "v <b>%A</b> o <b>%H:%M</b>, <b>%e.</b> <b>%B</b>"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
@@ -1000,17 +1001,19 @@ msgstr "Vnútorná chyba"
#: ../js/ui/components/telepathyClient.js:1339
#, c-format
msgid "Unable to connect to %s"
msgstr "Nepodarilo sa pripojiť účet %s"
msgstr ""
#: ../js/ui/components/telepathyClient.js:1344
#, fuzzy
#| msgid "Edit account"
msgid "View account"
msgstr "Zobraziť účet"
msgstr "Upraviť účet"
#: ../js/ui/components/telepathyClient.js:1384
msgid "Unknown reason"
msgstr "Neznámy dôvod"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:81
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:87
msgid "Windows"
msgstr "Okná"
@@ -1019,18 +1022,18 @@ msgstr "Okná"
msgid "Show Applications"
msgstr "Zobrazí aplikácie"
#: ../js/ui/dateMenu.js:87
#: ../js/ui/dateMenu.js:86
msgid "Date and Time Settings"
msgstr "Nastavenia dátumu a času"
#: ../js/ui/dateMenu.js:112
#: ../js/ui/dateMenu.js:111
msgid "Open Calendar"
msgstr "Otvoriť kalendár"
#. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#.
#: ../js/ui/dateMenu.js:191
#: ../js/ui/dateMenu.js:201
msgid "%A %B %e, %Y"
msgstr "%A, %e. %B %Y"
@@ -1139,81 +1142,85 @@ msgstr "Inštalovať"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Stiahnuť a nainštalovať „%s“ z extensions.gnome.org?"
#: ../js/ui/keyboard.js:291
#: ../js/ui/keyboard.js:308
msgid "tray"
msgstr "lišta"
#: ../js/ui/keyboard.js:636 ../js/ui/status/keyboard.js:309
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:195
#: ../js/ui/status/power.js:205
msgid "Keyboard"
msgstr "Klávesnica"
#: ../js/ui/lookingGlass.js:692
#: ../js/ui/lookingGlass.js:691
msgid "No extensions installed"
msgstr "Žiadne nainštalované rozšírenia"
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:746
#: ../js/ui/lookingGlass.js:745
#, c-format
msgid "%s has not emitted any errors."
msgstr "%s nevyslal žiadnu chybu."
#: ../js/ui/lookingGlass.js:752
#: ../js/ui/lookingGlass.js:751
msgid "Hide Errors"
msgstr "Skryť chyby"
#: ../js/ui/lookingGlass.js:756 ../js/ui/lookingGlass.js:816
#: ../js/ui/lookingGlass.js:755 ../js/ui/lookingGlass.js:815
msgid "Show Errors"
msgstr "Zobraziť chyby"
#: ../js/ui/lookingGlass.js:765
#: ../js/ui/lookingGlass.js:764
msgid "Enabled"
msgstr "Povolené"
#: ../js/ui/lookingGlass.js:768
#: ../js/ui/lookingGlass.js:767
msgid "Disabled"
msgstr "Zakázané"
#: ../js/ui/lookingGlass.js:770
#: ../js/ui/lookingGlass.js:769
msgid "Error"
msgstr "Chyba"
#: ../js/ui/lookingGlass.js:772
#: ../js/ui/lookingGlass.js:771
msgid "Out of date"
msgstr "Neaktuálne"
#: ../js/ui/lookingGlass.js:774
#: ../js/ui/lookingGlass.js:773
msgid "Downloading"
msgstr "Sťahuje sa"
# PK: ide tu o zdrojovy kod?
#: ../js/ui/lookingGlass.js:798
#: ../js/ui/lookingGlass.js:797
msgid "View Source"
msgstr "Zobraziť zdroj"
#: ../js/ui/lookingGlass.js:807
#: ../js/ui/lookingGlass.js:806
msgid "Web Page"
msgstr "Webová stránka"
#: ../js/ui/messageTray.js:1090
#: ../js/ui/messageTray.js:1088
msgid "Open"
msgstr "Otvoriť"
#: ../js/ui/messageTray.js:1097
#: ../js/ui/messageTray.js:1095
msgid "Remove"
msgstr "Odstrániť"
#: ../js/ui/messageTray.js:1554
# DK: zvazoval som pouzit "Panel správ"
# neviem co bude vhodnejsie ako preklad "tray"
#: ../js/ui/messageTray.js:1551
#, fuzzy
#| msgid "Message Tray"
msgid "No Messages"
msgstr "Žiadne správy"
msgstr "Lišta správ"
# DK: zvazoval som pouzit "Panel správ"
# neviem co bude vhodnejsie ako preklad "tray"
#: ../js/ui/messageTray.js:1572
#: ../js/ui/messageTray.js:1568
msgid "Message Tray"
msgstr "Lišta správ"
#: ../js/ui/messageTray.js:2641
#: ../js/ui/messageTray.js:2635
msgid "System Information"
msgstr "Informácie o systéme"
@@ -1222,11 +1229,11 @@ msgctxt "program"
msgid "Unknown"
msgstr "Neznámy"
#: ../js/ui/overview.js:92
#: ../js/ui/overview.js:95
msgid "Undo"
msgstr "Vrátiť"
#: ../js/ui/overview.js:139
#: ../js/ui/overview.js:144
msgid "Overview"
msgstr "Prehľad"
@@ -1234,27 +1241,27 @@ msgstr "Prehľad"
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: ../js/ui/overview.js:218
#: ../js/ui/overview.js:221
msgid "Type to search..."
msgstr "Vyhľadávanie…"
#. Translators: this is the name of the dock/favorites area on
#. the left of the overview
#: ../js/ui/overview.js:236
#: ../js/ui/overview.js:242
msgid "Dash"
msgstr "Dok"
#: ../js/ui/panel.js:613
#: ../js/ui/panel.js:608
msgid "Quit"
msgstr "Ukončiť"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:642
#: ../js/ui/panel.js:637
msgid "Activities"
msgstr "Aktivity"
#: ../js/ui/panel.js:976
#: ../js/ui/panel.js:980
msgid "Top Bar"
msgstr "Horná lišta"
@@ -1263,7 +1270,7 @@ msgstr "Horná lišta"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:727
#: ../js/ui/popupMenu.js:732
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
@@ -1280,11 +1287,11 @@ msgstr "Zavrieť"
# v ostatnych retazcoch je pouzite %e, tak to bude asi OK
#. Translators: This is a time format for a date in
#. long format
#: ../js/ui/screenShield.js:113
#: ../js/ui/screenShield.js:112
msgid "%A, %B %d"
msgstr "%A, %e. %B"
#: ../js/ui/screenShield.js:177
#: ../js/ui/screenShield.js:176
#, c-format
msgid "%d new message"
msgid_plural "%d new messages"
@@ -1292,7 +1299,7 @@ msgstr[0] "%d nových správ"
msgstr[1] "%d nová správa"
msgstr[2] "%d nové správy"
#: ../js/ui/screenShield.js:179
#: ../js/ui/screenShield.js:178
#, c-format
msgid "%d new notification"
msgid_plural "%d new notifications"
@@ -1300,15 +1307,15 @@ msgstr[0] "%d nových oznámení"
msgstr[1] "%d nové oznámenie"
msgstr[2] "%d nové oznámenia"
#: ../js/ui/screenShield.js:403 ../js/ui/userMenu.js:781
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:780
msgid "Lock"
msgstr "Uzamknúť"
#: ../js/ui/searchDisplay.js:403
#: ../js/ui/searchDisplay.js:277
msgid "Searching..."
msgstr "Hľadá sa…"
#: ../js/ui/searchDisplay.js:451
#: ../js/ui/searchDisplay.js:325
msgid "No results."
msgstr "Žiadne výsledky."
@@ -1427,7 +1434,7 @@ msgid "disconnecting..."
msgstr "odpája sa…"
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:442
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:1453
msgid "connecting..."
msgstr "pripája sa…"
@@ -1443,7 +1450,7 @@ msgstr "Nastavenia klávesnice"
msgid "Mouse Settings"
msgstr "Nastavenia myši"
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:314
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:270
msgid "Sound Settings"
msgstr "Nastavenia zvuku"
@@ -1507,15 +1514,15 @@ msgstr "Zadajte PIN, ktoré je uvedené na zariadení."
msgid "OK"
msgstr "Ok"
#: ../js/ui/status/keyboard.js:363
#: ../js/ui/status/keyboard.js:228
msgid "Show Keyboard Layout"
msgstr "Zobraziť rozloženie klávesnice"
#: ../js/ui/status/keyboard.js:368
#: ../js/ui/status/keyboard.js:233
msgid "Region and Language Settings"
msgstr "Miestne a jazykové nastavenia"
#: ../js/ui/status/lockScreenMenu.js:43
#: ../js/ui/status/lockScreenMenu.js:18
msgid "Volume, network, battery"
msgstr "Hlasitosť, sieť, batéria"
@@ -1536,7 +1543,7 @@ msgid "unmanaged"
msgstr "nespravované"
#. Translators: this is for network connections that require some kind of key or password
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1467
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1456
msgid "authentication required"
msgstr "požaduje sa overenie totožnosti"
@@ -1557,72 +1564,72 @@ msgstr "kábel odpojený"
msgid "unavailable"
msgstr "nedostupné"
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1469
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1458
msgid "connection failed"
msgstr "pripojenie zlyhalo"
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1403
#: ../js/ui/status/network.js:1545
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1392
#: ../js/ui/status/network.js:1534
msgid "More..."
msgstr "Viac…"
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1333
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1322
msgid "Connected (private)"
msgstr "Pripojené (súkromne)"
#: ../js/ui/status/network.js:641
#: ../js/ui/status/network.js:619
msgid "Auto Ethernet"
msgstr "Automatický ethernet"
#: ../js/ui/status/network.js:688
#: ../js/ui/status/network.js:677
msgid "Auto broadband"
msgstr "Automatické širokopásmové pripojenie"
#: ../js/ui/status/network.js:691
#: ../js/ui/status/network.js:680
msgid "Auto dial-up"
msgstr "Automatické vytáčané pripojenie"
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:820 ../js/ui/status/network.js:1350
#: ../js/ui/status/network.js:809 ../js/ui/status/network.js:1339
#, c-format
msgid "Auto %s"
msgstr "Automatické pripojenie %s"
#: ../js/ui/status/network.js:822
#: ../js/ui/status/network.js:811
msgid "Auto bluetooth"
msgstr "Automatický bluetooth"
#: ../js/ui/status/network.js:1352
#: ../js/ui/status/network.js:1341
msgid "Auto wireless"
msgstr "Automatická bezdrôtová sieť"
#: ../js/ui/status/network.js:1595
#: ../js/ui/status/network.js:1584
msgid "Enable networking"
msgstr "Povoliť sieť"
#: ../js/ui/status/network.js:1627
#: ../js/ui/status/network.js:1616
msgid "Wi-Fi"
msgstr "Wi-Fi"
#: ../js/ui/status/network.js:1646
#: ../js/ui/status/network.js:1635
msgid "Network Settings"
msgstr "Nastavenia siete"
#: ../js/ui/status/network.js:1692
#: ../js/ui/status/network.js:1679
msgid "Network Manager"
msgstr "Správca siete"
#: ../js/ui/status/network.js:1774
#: ../js/ui/status/network.js:1761
msgid "Connection failed"
msgstr "Pripojenie zlyhalo"
#: ../js/ui/status/network.js:1775
#: ../js/ui/status/network.js:1762
msgid "Activation of network connection failed"
msgstr "Aktivácia pripojenia k sieti zlyhala"
#: ../js/ui/status/network.js:2092
#: ../js/ui/status/network.js:2079
msgid "Networking is disabled"
msgstr "Sieť je zakázaná"
@@ -1728,19 +1735,19 @@ msgid "Unknown"
msgstr "Neznáme"
#. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:247 ../js/ui/status/volume.js:295
#: ../js/ui/status/volume.js:50 ../js/ui/status/volume.js:251
msgid "Volume"
msgstr "Hlasitosť"
#: ../js/ui/status/volume.js:256
#: ../js/ui/status/volume.js:62
msgid "Microphone"
msgstr "Mikrofón"
#: ../js/ui/unlockDialog.js:203
#: ../js/ui/unlockDialog.js:201
msgid "Log in as another user"
msgstr "Prihlásiť ako iný používateľ"
#: ../js/ui/unlockDialog.js:229
#: ../js/ui/unlockDialog.js:224
msgid "Unlock Window"
msgstr "Odomykacie okno"
@@ -1768,31 +1775,31 @@ msgstr "Nečinný"
msgid "Offline"
msgstr "Odhlásený"
#: ../js/ui/userMenu.js:755
#: ../js/ui/userMenu.js:754
msgid "Notifications"
msgstr "Upozornenia"
#: ../js/ui/userMenu.js:763
#: ../js/ui/userMenu.js:762
msgid "Settings"
msgstr "Nastavenia"
#: ../js/ui/userMenu.js:771
#: ../js/ui/userMenu.js:770
msgid "Switch User"
msgstr "Prepnúť používateľa"
#: ../js/ui/userMenu.js:776
#: ../js/ui/userMenu.js:775
msgid "Log Out"
msgstr "Odhlásiť sa"
#: ../js/ui/userMenu.js:796
#: ../js/ui/userMenu.js:795
msgid "Install Updates & Restart"
msgstr "Nainštalovať aktualizácie a reštartovať"
#: ../js/ui/userMenu.js:814
#: ../js/ui/userMenu.js:813
msgid "Your chat status will be set to busy"
msgstr "Váš stav bude nastavený na zaneprázdnený"
#: ../js/ui/userMenu.js:815
#: ../js/ui/userMenu.js:814
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@@ -1800,15 +1807,15 @@ msgstr ""
"Oznámenia, vrátane správ rozhovoru, sú teraz zakázané. Váš stav online bol "
"nastavený tak, aby ostatní vedeli, že nemusíte vidieť ich správy."
#: ../js/ui/viewSelector.js:85
#: ../js/ui/viewSelector.js:91
msgid "Applications"
msgstr "Aplikácie"
#: ../js/ui/viewSelector.js:89
#: ../js/ui/viewSelector.js:95
msgid "Search"
msgstr "Hľadať"
#: ../js/ui/wanda.js:92
#: ../js/ui/wanda.js:94
#, c-format
msgid ""
"Sorry, no wisdom for you today:\n"
@@ -1817,11 +1824,15 @@ msgstr ""
"Prepáčte, dnes nie je pre vás pripravená žiadna múdrosť:\n"
"%s"
#: ../js/ui/wanda.js:96
#: ../js/ui/wanda.js:98
#, c-format
msgid "%s the Oracle says"
msgstr "Veštec hovorí %s"
#: ../js/ui/wanda.js:139
msgid "Your favorite Easter Egg"
msgstr "Vaše obľúbené veľkonočné vajce"
# %s je totiž titulok okna
# informacna bublina
#: ../js/ui/windowAttentionHandler.js:19
@@ -1876,30 +1887,6 @@ msgstr "Predvolený"
msgid "Authentication dialog was dismissed by the user"
msgstr "Dialógové okno overenia totožnosti bolo zatvorené používateľom"
#~ msgid "APPLICATIONS"
#~ msgstr "APLIKÁCIE"
#~ msgid "SETTINGS"
#~ msgstr "NASTAVENIA"
#~ msgid "Your favorite Easter Egg"
#~ msgstr "Vaše obľúbené veľkonočné vajce"
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "%u výstupov"
#~ msgstr[1] "%u výstup"
#~ msgstr[2] "%u výstupy"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "%u vstupov"
#~ msgstr[1] "%u vstup"
#~ msgstr[2] "%u vstupy"
#~ msgid "System Sounds"
#~ msgstr "Zvuky systému"
#~ msgid "Subscription request"
#~ msgstr "Žiadosť o potvrdenie prístupu"
@@ -1917,3 +1904,18 @@ msgstr "Dialógové okno overenia totožnosti bolo zatvorené používateľom"
#~ msgid "Reconnect"
#~ msgstr "Znovu sa pripojiť"
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "%u výstupov"
#~ msgstr[1] "%u výstup"
#~ msgstr[2] "%u výstupy"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "%u vstupov"
#~ msgstr[1] "%u vstup"
#~ msgstr[2] "%u vstupy"
#~ msgid "System Sounds"
#~ msgstr "Zvuky systému"

1073
po/sl.po

File diff suppressed because it is too large Load Diff

846
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3525
po/ug.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -115,7 +115,6 @@ shell_public_headers_h = \
shell-gtk-embed.h \
shell-global.h \
shell-invert-lightness-effect.h \
shell-keybinding-modes.h \
shell-mobile-providers.h \
shell-mount-operation.h \
shell-network-agent.h \
@@ -292,7 +291,7 @@ libgnome_shell_la_LIBADD = \
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
Shell-0.1.gir: libgnome-shell.la St-1.0.gir
Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-3.0 TelepathyGLib-0.12 TelepathyLogger-0.2 Soup-2.4 GMenu-3.0 NetworkManager-1.0 NMClient-1.0 xlib-2.0
Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-3.0 TelepathyGLib-0.12 TelepathyLogger-0.2 Soup-2.4 GMenu-3.0 NetworkManager-1.0 NMClient-1.0
Shell_0_1_gir_CFLAGS = $(libgnome_shell_la_CPPFLAGS) -I $(srcdir)
Shell_0_1_gir_LIBS = libgnome-shell.la
Shell_0_1_gir_FILES = $(libgnome_shell_la_gir_sources)

View File

@@ -1,12 +1,12 @@
#!/bin/sh
if [ -z "$GI_TYPELIB_PATH" ]; then
if [ -n "$GI_TYPELIB_PATH" ]; then
export GI_TYPELIB_PATH=@pkglibdir@
else
export GI_TYPELIB_PATH=@pkglibdir@:$GI_TYPELIB_PATH
fi
if [ -z "$LD_LIBRARY_PATH" ] ; then
if [ -n "$LD_LIBRARY_PATH" ] ; then
export LD_LIBRARY_PATH=@pkglibdir@
else
export LD_LIBRARY_PATH=@pkglibdir@:$LD_LIBRARY_PATH

View File

@@ -75,8 +75,9 @@ def start_shell():
if 'GI_TYPELIB_PATH' in os.environ:
typelib_dir += ':%s' % (os.environ['GI_TYPELIB_PATH'],)
env.update({'GI_TYPELIB_PATH' : typelib_dir,
'GNOME_SHELL_JS' : os.path.join(top_dir, "js"),
env.update({'GNOME_SHELL_JS' : os.path.join(top_dir, "js"),
'GNOME_SHELL_BINDIR' : self_dir,
'GI_TYPELIB_PATH' : typelib_dir,
'GNOME_SHELL_DATADIR' : os.path.join(top_dir, "data"),
'GSETTINGS_SCHEMA_DIR' : os.path.join(top_dir, "data") })

View File

@@ -284,44 +284,12 @@ gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin)
_shell_wm_kill_switch_workspace (get_shell_wm());
}
static gboolean
ignore_crossing_event (MetaPlugin *plugin,
XIEnterEvent *enter_event)
{
MetaScreen *screen = meta_plugin_get_screen (plugin);
ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (enter_event->event == clutter_x11_get_stage_window (stage))
{
/* If the pointer enters a child of the stage window (eg, a
* trayicon), we want to consider it to still be in the stage,
* so don't let Clutter see the event.
*/
if (enter_event->detail == XINotifyInferior)
return TRUE;
/* If the pointer is grabbed by a window it is not currently in,
* filter that out as well. In particular, if a trayicon grabs
* the pointer after a click on its label, we don't want to hide
* the message tray. Filtering out this event will leave Clutter
* out of sync, but that happens fairly often with grabs, and we
* can work around it. (Eg, shell_global_sync_pointer().)
*/
if (enter_event->mode == XINotifyGrab &&
(enter_event->detail == XINotifyNonlinear ||
enter_event->detail == XINotifyNonlinearVirtual))
return TRUE;
}
return FALSE;
}
static gboolean
gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
XEvent *xev)
{
MetaScreen *screen = meta_plugin_get_screen (plugin);
MetaDisplay *display = meta_screen_get_display (screen);
ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
#ifdef GLX_INTEL_swap_event
@@ -341,15 +309,26 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
}
#endif
/* Make sure that Clutter doesn't see certain focus change events,
* so that when we're moving into something like a tray icon, we
* don't unfocus the container. */
if (xev->type == GenericEvent &&
xev->xcookie.extension == meta_display_get_xinput_opcode (display))
if ((xev->xany.type == EnterNotify || xev->xany.type == LeaveNotify)
&& xev->xcrossing.window == clutter_x11_get_stage_window (stage))
{
XIEvent *input_event = (XIEvent *) xev->xcookie.data;
if ((input_event->evtype == XI_Enter || input_event->evtype == XI_Leave) &&
ignore_crossing_event (plugin, (XIEnterEvent *) input_event))
/* If the pointer enters a child of the stage window (eg, a
* trayicon), we want to consider it to still be in the stage,
* so don't let Clutter see the event.
*/
if (xev->xcrossing.detail == NotifyInferior)
return TRUE;
/* If the pointer is grabbed by a window it is not currently in,
* filter that out as well. In particular, if a trayicon grabs
* the pointer after a click on its label, we don't want to hide
* the message tray. Filtering out this event will leave Clutter
* out of sync, but that happens fairly often with grabs, and we
* can work around it. (Eg, shell_global_sync_pointer().)
*/
if (xev->xcrossing.mode == NotifyGrab &&
(xev->xcrossing.detail == NotifyNonlinear ||
xev->xcrossing.detail == NotifyNonlinearVirtual))
return TRUE;
}

View File

@@ -8,7 +8,6 @@
#include <stdlib.h>
#include <string.h>
#include <cogl-pango/cogl-pango.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include <gdk/gdk.h>
@@ -195,20 +194,6 @@ shell_introspection_init (void)
}
static void
shell_fonts_init (void)
{
CoglPangoFontMap *fontmap;
/* Disable text mipmapping; it causes problems on pre-GEM Intel
* drivers and we should just be rendering text at the right
* size rather than scaling it. If we do effects where we dynamically
* zoom labels, then we might want to reconsider.
*/
fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
}
static void
malloc_statistics_callback (ShellPerfLog *perf_log,
gpointer data)
@@ -411,7 +396,6 @@ main (int argc, char **argv)
shell_perf_log_init ();
shell_prefs_init ();
shell_introspection_init ();
shell_fonts_init ();
/* Turn on telepathy-glib debugging but filter it out in
* default_log_handler. This handler also exposes all the logs over D-Bus

View File

@@ -457,6 +457,38 @@ shell_app_system_get_tree (ShellAppSystem *self)
return self->priv->apps_tree;
}
/**
* shell_app_system_get_settings_tree:
*
* Return Value: (transfer none): The #GMenuTree for apps
*/
GMenuTree *
shell_app_system_get_settings_tree (ShellAppSystem *self)
{
return self->priv->settings_tree;
}
/**
* shell_app_system_lookup_setting:
* @system:
* @id: desktop file id
*
* Returns: (transfer none): Application in gnomecc.menu, or %NULL if none
*/
ShellApp *
shell_app_system_lookup_setting (ShellAppSystem *self,
const char *id)
{
ShellApp *app;
/* Actually defer to the main app set if there's overlap */
app = shell_app_system_lookup_app (self, id);
if (app != NULL)
return app;
return g_hash_table_lookup (self->priv->setting_id_to_app, id);
}
/**
* shell_app_system_get_default:
*

View File

@@ -60,7 +60,13 @@ GSList *shell_app_system_subsearch (ShellAppSystem *sys
GSList *previous_results,
GSList *terms);
GMenuTree *shell_app_system_get_settings_tree (ShellAppSystem *system);
GSList *shell_app_system_search_settings (ShellAppSystem *system,
GSList *terms);
ShellApp *shell_app_system_lookup_setting (ShellAppSystem *system,
const char *id);
#endif /* __SHELL_APP_SYSTEM_H__ */

View File

@@ -13,11 +13,10 @@
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <locale.h>
#include <X11/extensions/Xfixes.h>
#include <cogl-pango/cogl-pango.h>
#include <canberra.h>
#include <canberra-gtk.h>
#include <clutter/glx/clutter-glx.h>
#include <clutter/x11/clutter-x11.h>
#include <gdk/gdkx.h>
@@ -267,13 +266,8 @@ shell_global_init (ShellGlobal *global)
global->input_mode = SHELL_STAGE_INPUT_MODE_NORMAL;
global->sound_context = ca_gtk_context_get ();
ca_context_change_props (global->sound_context,
CA_PROP_APPLICATION_NAME, "GNOME Shell",
CA_PROP_APPLICATION_ID, "org.gnome.Shell",
CA_PROP_APPLICATION_ICON_NAME, "start-here",
CA_PROP_APPLICATION_LANGUAGE, setlocale (LC_MESSAGES, NULL),
NULL);
ca_context_create (&global->sound_context);
ca_context_change_props (global->sound_context, CA_PROP_APPLICATION_NAME, PACKAGE_NAME, CA_PROP_APPLICATION_ID, "org.gnome.Shell", NULL);
ca_context_open (global->sound_context);
if (!shell_js)
@@ -622,9 +616,6 @@ shell_global_set_cursor (ShellGlobal *global,
case SHELL_CURSOR_POINTING_HAND:
name = "hand";
break;
case SHELL_CURSOR_CROSSHAIR:
name = "crosshair";
break;
default:
g_return_if_reached ();
}
@@ -647,9 +638,6 @@ shell_global_set_cursor (ShellGlobal *global,
case SHELL_CURSOR_POINTING_HAND:
cursor_type = GDK_HAND2;
break;
case SHELL_CURSOR_CROSSHAIR:
cursor_type = GDK_CROSSHAIR;
break;
case SHELL_CURSOR_DND_UNSUPPORTED_TARGET:
cursor_type = GDK_X_CURSOR;
break;
@@ -817,6 +805,20 @@ global_stage_after_paint (ClutterStage *stage,
"clutter.stagePaintDone");
}
static void
shell_fonts_init (ClutterStage *stage)
{
CoglPangoFontMap *fontmap;
/* Disable text mipmapping; it causes problems on pre-GEM Intel
* drivers and we should just be rendering text at the right
* size rather than scaling it. If we do effects where we dynamically
* zoom labels, then we might want to reconsider.
*/
fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
}
/* This is an IBus workaround. The flow of events with IBus is that every time
* it gets gets a key event, it:
*
@@ -955,6 +957,8 @@ _shell_global_set_plugin (ShellGlobal *global,
g_signal_connect (global->meta_display, "notify::focus-window",
G_CALLBACK (focus_window_changed), global);
shell_fonts_init (global->stage);
gdk_event_handler_set (gnome_shell_gdk_event_handler, global->stage, NULL);
global->focus_manager = st_focus_manager_get_for_stage (global->stage);
@@ -1400,6 +1404,7 @@ guint32
shell_global_get_current_time (ShellGlobal *global)
{
guint32 time;
const ClutterEvent *clutter_event;
/* In case we have a xdnd timestamp use it */
if (global->xdnd_timestamp != 0)
@@ -1410,7 +1415,7 @@ shell_global_get_current_time (ShellGlobal *global)
from some Clutter event callbacks.
clutter_get_current_event_time() will return the correct time
from a Clutter event callback, but may return CLUTTER_CURRENT_TIME
from a Clutter event callback, but may return an out-of-date
timestamp if called at other times.
So we try meta_display_get_current_time() first, since we
@@ -1420,9 +1425,17 @@ shell_global_get_current_time (ShellGlobal *global)
time = meta_display_get_current_time (global->meta_display);
if (time != CLUTTER_CURRENT_TIME)
return time;
return time;
/*
* We don't use clutter_get_current_event_time as it can give us a
* too old timestamp if there is no current event.
*/
clutter_event = clutter_get_current_event ();
return clutter_get_current_event_time ();
if (clutter_event != NULL)
return clutter_event_get_time (clutter_event);
else
return CLUTTER_CURRENT_TIME;
}
/**
@@ -1584,99 +1597,21 @@ shell_global_run_at_leisure (ShellGlobal *global,
schedule_leisure_functions (global);
}
static void
build_ca_proplist_for_event (ca_proplist *props,
const char *event_id,
const char *event_description,
ClutterEvent *for_event)
{
ca_proplist_sets (props, CA_PROP_EVENT_ID, event_id);
ca_proplist_sets (props, CA_PROP_EVENT_DESCRIPTION, event_description);
ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile");
if (for_event)
{
if (clutter_event_type (for_event) != CLUTTER_KEY_PRESS &&
clutter_event_type (for_event) != CLUTTER_KEY_RELEASE)
{
ClutterPoint point;
clutter_event_get_position (for_event, &point);
ca_proplist_setf (props, CA_PROP_EVENT_MOUSE_X, "%d", (int)point.x);
ca_proplist_setf (props, CA_PROP_EVENT_MOUSE_Y, "%d", (int)point.y);
}
if (clutter_event_type (for_event) == CLUTTER_BUTTON_PRESS ||
clutter_event_type (for_event) == CLUTTER_BUTTON_RELEASE)
{
gint button;
button = clutter_event_get_button (for_event);
ca_proplist_setf (props, CA_PROP_EVENT_MOUSE_BUTTON, "%d", button);
}
}
}
/**
* shell_global_play_theme_sound:
* @global: the #ShellGlobal
* @id: an id, used to cancel later (0 if not needed)
* @name: the sound name
* @for_event: (allow-none): a #ClutterEvent in response to which the sound is played
*
* Plays a simple sound picked according to Freedesktop sound theme.
* Really just a workaround for libcanberra not being introspected.
*/
void
shell_global_play_theme_sound (ShellGlobal *global,
guint id,
const char *name,
const char *description,
ClutterEvent *for_event)
shell_global_play_theme_sound (ShellGlobal *global,
guint id,
const char *name)
{
ca_proplist *props;
ca_proplist_create (&props);
build_ca_proplist_for_event (props, name, description, for_event);
ca_context_play_full (global->sound_context, id, props, NULL, NULL);
ca_proplist_destroy (props);
}
/**
* shell_global_play_theme_sound_full:
* @global: the #ShellGlobal
* @id: an id, used to cancel later (0 if not needed)
* @name: the sound name
* @description: the localized description of the event that triggered this alert
* @for_event: (allow-none): a #ClutterEvent in response to which the sound is played
* @application_id: application on behalf of which the sound is played
* @application_name:
*
* Plays a simple sound picked according to Freedesktop sound theme.
* Really just a workaround for libcanberra not being introspected.
*/
void
shell_global_play_theme_sound_full (ShellGlobal *global,
guint id,
const char *name,
const char *description,
ClutterEvent *for_event,
const char *application_id,
const char *application_name)
{
ca_proplist *props;
ca_proplist_create (&props);
build_ca_proplist_for_event (props, name, description, for_event);
ca_proplist_sets (props, CA_PROP_APPLICATION_ID, application_id);
ca_proplist_sets (props, CA_PROP_APPLICATION_NAME, application_name);
ca_context_play_full (global->sound_context, id, props, NULL, NULL);
ca_proplist_destroy (props);
ca_context_play (global->sound_context, id, CA_PROP_EVENT_ID, name, NULL);
}
/**

View File

@@ -63,8 +63,7 @@ typedef enum {
SHELL_CURSOR_DND_UNSUPPORTED_TARGET,
SHELL_CURSOR_DND_MOVE,
SHELL_CURSOR_DND_COPY,
SHELL_CURSOR_POINTING_HAND,
SHELL_CURSOR_CROSSHAIR
SHELL_CURSOR_POINTING_HAND
} ShellCursor;
void shell_global_set_cursor (ShellGlobal *global,
@@ -121,18 +120,9 @@ void shell_global_sync_pointer (ShellGlobal *global);
GAppLaunchContext *
shell_global_create_app_launch_context (ShellGlobal *global);
void shell_global_play_theme_sound (ShellGlobal *global,
guint id,
const char *name,
const char *description,
ClutterEvent *for_event);
void shell_global_play_theme_sound_full (ShellGlobal *global,
void shell_global_play_theme_sound (ShellGlobal *global,
guint id,
const char *name,
const char *description,
ClutterEvent *for_event,
const char *application_id,
const char *application_name);
const char *name);
void shell_global_cancel_theme_sound (ShellGlobal *global,
guint id);

View File

@@ -1,35 +0,0 @@
/**
* ShellKeyBindingMode:
* @SHELL_KEYBINDING_MODE_NONE: block keybinding
* @SHELL_KEYBINDING_MODE_NORMAL: allow keybinding when in window mode,
* e.g. when the focus is in an application window
* @SHELL_KEYBINDING_MODE_OVERVIEW: allow keybinding while the overview
* is active
* @SHELL_KEYBINDING_MODE_LOCK_SCREEN: allow keybinding when the screen
* is locked, e.g. when the screen shield is shown
* @SHELL_KEYBINDING_MODE_UNLOCK_SCREEN: allow keybinding in the unlock
* dialog
* @SHELL_KEYBINDING_MODE_LOGIN_SCREEN: allow keybinding in the login screen
* @SHELL_KEYBINDING_MODE_MESSAGE_TRAY: allow keybinding while the message
* tray is popped up
* @SHELL_KEYBINDING_MODE_SYSTEM_MODAL: allow keybinding when a system modal
* dialog (e.g. authentification or session dialogs) is open
* @SHELL_KEYBINDING_MODE_LOOKING_GLASS: allow keybinding in looking glass
* @SHELL_KEYBINDING_MODE_ALL: always allow keybinding
*
* Controls in which GNOME Shell states a keybinding should be handled.
*/
typedef enum {
SHELL_KEYBINDING_MODE_NONE = 0,
SHELL_KEYBINDING_MODE_NORMAL = 1 << 0,
SHELL_KEYBINDING_MODE_OVERVIEW = 1 << 1,
SHELL_KEYBINDING_MODE_LOCK_SCREEN = 1 << 2,
SHELL_KEYBINDING_MODE_UNLOCK_SCREEN = 1 << 3,
SHELL_KEYBINDING_MODE_LOGIN_SCREEN = 1 << 4,
SHELL_KEYBINDING_MODE_MESSAGE_TRAY = 1 << 5,
SHELL_KEYBINDING_MODE_SYSTEM_MODAL = 1 << 6,
SHELL_KEYBINDING_MODE_LOOKING_GLASS = 1 << 7,
SHELL_KEYBINDING_MODE_ALL = ~SHELL_KEYBINDING_MODE_NONE
} ShellKeyBindingMode;

View File

@@ -32,7 +32,6 @@ typedef struct _screenshot_data {
ShellScreenshot *screenshot;
char *filename;
char *filename_used;
cairo_surface_t *image;
cairo_rectangle_int_t screenshot_area;
@@ -65,140 +64,25 @@ on_screenshot_written (GObject *source,
if (screenshot_data->callback)
screenshot_data->callback (screenshot_data->screenshot,
g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result)),
&screenshot_data->screenshot_area,
screenshot_data->filename_used);
&screenshot_data->screenshot_area);
cairo_surface_destroy (screenshot_data->image);
g_object_unref (screenshot_data->screenshot);
g_free (screenshot_data->filename);
g_free (screenshot_data->filename_used);
g_free (screenshot_data);
}
/* called in an I/O thread */
static GOutputStream *
get_stream_for_unique_path (const gchar *path,
const gchar *filename,
gchar **filename_used)
{
GOutputStream *stream;
GFile *file;
gchar *real_path, *real_filename, *name, *ptr;
gint idx;
ptr = g_strrstr (filename, ".png");
if (ptr != NULL)
real_filename = g_strndup (filename, ptr - filename);
else
real_filename = g_strdup (filename);
idx = 0;
real_path = NULL;
do
{
if (idx == 0)
name = g_strdup_printf ("%s.png", real_filename);
else
name = g_strdup_printf ("%s - %d.png", real_filename, idx);
real_path = g_build_filename (path, name, NULL);
g_free (name);
file = g_file_new_for_path (real_path);
stream = G_OUTPUT_STREAM (g_file_create (file, G_FILE_CREATE_NONE, NULL, NULL));
g_object_unref (file);
if (stream != NULL)
*filename_used = real_path;
else
g_free (real_path);
idx++;
}
while (stream == NULL);
g_free (real_filename);
return stream;
}
/* called in an I/O thread */
static GOutputStream *
get_stream_for_filename (const gchar *filename,
gchar **filename_used)
{
const gchar *path;
path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
if (!g_file_test (path, G_FILE_TEST_EXISTS))
{
path = g_get_home_dir ();
if (!g_file_test (path, G_FILE_TEST_EXISTS))
return NULL;
}
return get_stream_for_unique_path (path, filename, filename_used);
}
static GOutputStream *
prepare_write_stream (const gchar *filename,
gchar **filename_used)
{
GOutputStream *stream;
GFile *file;
if (g_path_is_absolute (filename))
{
file = g_file_new_for_path (filename);
*filename_used = g_strdup (filename);
stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
g_object_unref (file);
}
else
{
stream = get_stream_for_filename (filename, filename_used);
}
return stream;
}
static cairo_status_t
do_write_to_stream (void *closure,
const guchar *data,
guint length)
{
GOutputStream *stream = closure;
gboolean res;
res = g_output_stream_write_all (stream, data, length, NULL, NULL, NULL);
return res ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
}
static void
write_screenshot_thread (GSimpleAsyncResult *result,
GObject *object,
GCancellable *cancellable)
{
cairo_status_t status;
GOutputStream *stream;
_screenshot_data *screenshot_data = g_async_result_get_user_data (G_ASYNC_RESULT (result));
g_assert (screenshot_data != NULL);
stream = prepare_write_stream (screenshot_data->filename,
&screenshot_data->filename_used);
if (stream == NULL)
status = CAIRO_STATUS_FILE_NOT_FOUND;
else
status = cairo_surface_write_to_png_stream (screenshot_data->image, do_write_to_stream, stream);
status = cairo_surface_write_to_png (screenshot_data->image, screenshot_data->filename);
g_simple_async_result_set_op_res_gboolean (result, status == CAIRO_STATUS_SUCCESS);
g_clear_object (&stream);
}
static void

View File

@@ -26,9 +26,8 @@ GType shell_screenshot_get_type (void) G_GNUC_CONST;
ShellScreenshot *shell_screenshot_new (void);
typedef void (*ShellScreenshotCallback) (ShellScreenshot *screenshot,
gboolean success,
cairo_rectangle_int_t *screenshot_area,
const gchar *filename_used);
gboolean success,
cairo_rectangle_int_t *screenshot_area);
void shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
int x,

View File

@@ -180,7 +180,6 @@ void
shell_tray_icon_click (ShellTrayIcon *icon,
ClutterEvent *event)
{
XKeyEvent xkevent;
XButtonEvent xbevent;
XCrossingEvent xcevent;
GdkWindow *remote_window;
@@ -188,10 +187,8 @@ shell_tray_icon_click (ShellTrayIcon *icon,
int x_root, y_root;
Display *xdisplay;
Window xwindow, xrootwindow;
ClutterEventType event_type = clutter_event_type (event);
g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE ||
event_type == CLUTTER_KEY_RELEASE);
g_return_if_fail (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE);
gdk_error_trap_push ();
@@ -218,44 +215,22 @@ shell_tray_icon_click (ShellTrayIcon *icon,
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);
/* Now do the click */
if (event_type == CLUTTER_BUTTON_RELEASE)
{
xbevent.window = xwindow;
xbevent.root = xrootwindow;
xbevent.subwindow = None;
xbevent.time = xcevent.time;
xbevent.x = xcevent.x;
xbevent.y = xcevent.y;
xbevent.x_root = xcevent.x_root;
xbevent.y_root = xcevent.y_root;
xbevent.state = clutter_event_get_state (event);
xbevent.same_screen = True;
xbevent.type = ButtonPress;
xbevent.button = clutter_event_get_button (event);
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
xbevent.type = ButtonPress;
xbevent.window = xwindow;
xbevent.root = xrootwindow;
xbevent.subwindow = None;
xbevent.time = xcevent.time;
xbevent.x = xcevent.x;
xbevent.y = xcevent.y;
xbevent.x_root = xcevent.x_root;
xbevent.y_root = xcevent.y_root;
xbevent.state = clutter_event_get_state (event);
xbevent.button = clutter_event_get_button (event);
xbevent.same_screen = True;
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
xbevent.type = ButtonRelease;
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
}
else
{
xkevent.window = xwindow;
xkevent.root = xrootwindow;
xkevent.subwindow = None;
xkevent.time = xcevent.time;
xkevent.x = xcevent.x;
xkevent.y = xcevent.y;
xkevent.x_root = xcevent.x_root;
xkevent.y_root = xcevent.y_root;
xkevent.state = clutter_event_get_state (event);
xkevent.same_screen = True;
xkevent.type = KeyPress;
xkevent.keycode = clutter_event_get_key_code (event);
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent);
xkevent.type = KeyRelease;
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent);
}
xbevent.type = ButtonRelease;
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
/* And move the pointer back out */
xcevent.type = LeaveNotify;

View File

@@ -9,8 +9,6 @@
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#ifdef HAVE__NL_TIME_FIRST_WEEKDAY
#include <langinfo.h>
@@ -432,56 +430,3 @@ shell_util_create_pixbuf_from_data (const guchar *data,
bits_per_sample, width, height, rowstride,
(GdkPixbufDestroyNotify) g_free, NULL);
}
Pixmap
shell_util_get_root_background (void)
{
Display *display;
Pixmap pixmap;
Window rootwin;
Atom xrootpmap;
Atom actual_type;
int actual_format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *buffer;
display = gdk_x11_get_default_xdisplay ();
xrootpmap = gdk_x11_atom_to_xatom (gdk_atom_intern_static_string ("_XROOTPMAP_ID"));
rootwin = gdk_x11_get_default_root_xwindow ();
gdk_error_trap_push ();
actual_type = None;
buffer = NULL;
if (XGetWindowProperty (display, rootwin, xrootpmap,
0, G_MAXLONG,
False, XA_PIXMAP, &actual_type, &actual_format,
&n_items,
&bytes_after,
&buffer) != Success ||
actual_type == None)
{
if (buffer)
XFree (buffer);
gdk_error_trap_pop_ignored ();
return FALSE;
}
if (gdk_error_trap_pop () != Success ||
n_items == 0 ||
actual_type != XA_PIXMAP ||
actual_format != 32)
{
if (buffer)
XFree (buffer);
return FALSE;
}
pixmap = *((Pixmap*) buffer);
XFree (buffer);
return pixmap;
}

View File

@@ -7,7 +7,6 @@
#include <clutter/clutter.h>
#include <libsoup/soup.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdkx.h>
G_BEGIN_DECLS
@@ -47,8 +46,6 @@ GdkPixbuf *shell_util_create_pixbuf_from_data (const guchar *data,
int height,
int rowstride);
Pixmap shell_util_get_root_background (void);
G_END_DECLS
#endif /* __SHELL_UTIL_H__ */

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