Compare commits
2 Commits
wip/gcampa
...
3.7.3.1-br
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7d598b7725 | ||
![]() |
9f890982b2 |
51
NEWS
51
NEWS
@@ -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
|
||||
=====
|
||||
|
93
configure.ac
93
configure.ac
@@ -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)
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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>
|
@@ -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>
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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 \
|
||||
|
@@ -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,
|
||||
|
141
js/misc/hash.js
141
js/misc/hash.js
@@ -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;
|
||||
},
|
||||
});
|
@@ -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
|
||||
|
@@ -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 });
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
},
|
||||
|
@@ -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();
|
||||
},
|
||||
|
||||
|
@@ -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();
|
||||
},
|
||||
|
||||
|
@@ -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));
|
||||
},
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
45
js/ui/flashspot.js
Normal 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();
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
},
|
||||
|
1043
js/ui/layout.js
1043
js/ui/layout.js
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
@@ -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);
|
||||
|
127
js/ui/main.js
127
js/ui/main.js
@@ -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() {
|
||||
|
@@ -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) {
|
||||
|
@@ -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 });
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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!');
|
||||
|
@@ -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([]);
|
||||
}
|
||||
},
|
||||
|
@@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
|
@@ -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();
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
@@ -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);
|
||||
|
@@ -30,6 +30,5 @@ const HorizontalSeparator = new Lang.Class({
|
||||
cr.setSource(pattern);
|
||||
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
|
||||
cr.fill();
|
||||
cr.$dispose();
|
||||
}
|
||||
});
|
||||
|
@@ -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() {
|
||||
|
@@ -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);
|
||||
}
|
||||
});
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -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:
|
||||
|
@@ -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;
|
||||
|
@@ -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());
|
||||
}
|
||||
});
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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();
|
||||
},
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -21,7 +21,6 @@ eu
|
||||
fa
|
||||
fi
|
||||
fr
|
||||
fur
|
||||
ga
|
||||
gl
|
||||
gu
|
||||
|
@@ -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
237
po/ar.po
@@ -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'"
|
||||
|
||||
|
12
po/et.po
12
po/et.po
@@ -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"
|
||||
|
1061
po/pt_BR.po
1061
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
344
po/sk.po
344
po/sk.po
@@ -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"
|
||||
|
846
po/sr@latin.po
846
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
830
po/zh_CN.po
830
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
893
po/zh_HK.po
893
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
900
po/zh_TW.po
900
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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") })
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
16
src/main.c
16
src/main.c
@@ -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
|
||||
|
@@ -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:
|
||||
*
|
||||
|
@@ -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__ */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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
Reference in New Issue
Block a user