Compare commits

..

4 Commits

Author SHA1 Message Date
Debarshi Ray
28585a817a workspace: Use the schema for the current mode to get 'button-layout'
https://bugzilla.gnome.org/show_bug.cgi?id=689234
2012-11-28 19:25:46 +01:00
Debarshi Ray
8b5d07c1a5 main: Use the schema for the current mode to override 'button-layout'
https://bugzilla.gnome.org/show_bug.cgi?id=689234
2012-11-28 19:25:46 +01:00
Debarshi Ray
6cbdb6beae sessionMode: Define a new foo mode
A new parameter called buttonLayout was introduced to parametrize the
schema used for the 'button-layout' setting.

https://bugzilla.gnome.org/show_bug.cgi?id=689234
2012-11-28 19:25:46 +01:00
Debarshi Ray
b8f9a108f9 data: Add a new schema for foo mode
The foo mode will have a different default value for button-layout as
compared to the standard GNOME 3 mode. To avoid one mode from
overwriting the setting from another, lets use a different schema
for this mode.

https://bugzilla.gnome.org/show_bug.cgi?id=689234
2012-11-28 19:25:46 +01:00
112 changed files with 10943 additions and 6502 deletions

3
.gitignore vendored
View File

@@ -38,7 +38,6 @@ docs/reference/*/*.txt
docs/reference/*/*.types docs/reference/*/*.types
docs/reference/*/html/ docs/reference/*/html/
docs/reference/*/xml/ docs/reference/*/xml/
docs/reference/shell/doc-gen-*
gtk-doc.make gtk-doc.make
js/misc/config.js js/misc/config.js
intltool-extract.in intltool-extract.in
@@ -86,8 +85,6 @@ src/test-theme
src/st.h src/st.h
src/stamp-st.h src/stamp-st.h
src/stamp-st.h.tmp src/stamp-st.h.tmp
src/st-scroll-view-fade-generated.c
src/stamp-st-scroll-view-fade-generated.c
stamp-h1 stamp-h1
tests/run-test.sh tests/run-test.sh
xmldocs.make xmldocs.make

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "src/gvc"]
path = src/gvc
url = git://git.gnome.org/libgnome-volume-control

View File

@@ -16,7 +16,6 @@ EXTRA_DIST = \
# These are files checked into Git that we don't want to distribute # These are files checked into Git that we don't want to distribute
DIST_EXCLUDE = \ DIST_EXCLUDE = \
.gitignore \ .gitignore \
.gitmodules \
gnome-shell.doap \ gnome-shell.doap \
HACKING \ HACKING \
MAINTAINERS \ MAINTAINERS \

57
NEWS
View File

@@ -1,60 +1,3 @@
3.7.3
=====
* Add 'No Messages' label when message tray is empty [Victoria; #686738]
* Use better icons in Ctrl-Alt-Tab popup [Stéphane; #641303]
* Show the OSK on the monitor where the focused window lives [Giovanni; #685856]
* Highlight window clone and caption when hovered [Giovanni, Marc; #665310]
* Improve login process indication [Stéphane; #687113]
* Omit empty categories in apps view [Stéphane; #687970]
* Style panel differently according to mode [Florian; #684573]
* Make it possible to hide the user name [Matthias; #688577]
* Consolidate and improve chat connection notifications [Giovanni; #687213]
* Improve notification scrollbar appearance [Carlos; #688393]
* Fade scroll view fade near scrolling edges [Jasper; #689249]
* Add a read-only org.gnome.Shell.Mode property [Debarshi; #689300]
* Don't close message tray after using context menus [Giovanni; #689296]
* Port swipe-scrolling to ClutterPanAction [Jasper, Florian; #689062, #689552]
* Remember state of 'Remember Password' checkbox [Ron; #688039]
* Improve timestamp format in chat notifications [Carlos; #680989]
* Improve style of missed-messages counter [Carlos; #686472]
* Omit connection failure notifications if cancelled by user [Giovanni; #684823]
* Add window-based Alt-Tab popup [Florian; #688913]
* Support external session mode definitions [Florian; #689304]
* Support session-mode-specific extensions [Florian; #689305]
* Support 'parentMode' property in session modes [Florian; #689308]
* Support a new org.gnome.ShellSearchProvider2 DBus interface
[Cosimo; #689735, #690009]
* Add "windows" to Ctrl-Alt-Tab popup [Jasper; #689653]
* Port PopupMenu to GrabHelper [Jasper; #689109, #689954]
* Show headphone icon when headphones are plugged in [Giovanni; #675902]
* Display (non-app) search results as list [Tanner, Cosimo; #681797]
* Skip diacritical marks in search terms [Aleksander; #648587]
* Expose all engine options in input sources [Giovanni, Rui; #682318]
* Add input source switcher popup [Rui; #682315]
* Add minimal support for InfiniBand in network menu [Dan; #677150]
* Misc bug fixes and cleanups [Sebastian, Aleksander, Giovanni, Tim, Cosimo,
Florian, Matthias, Rui, Lionel, Colin, Piotr, Guillaume, Bastien, Tanner,
Carlos, Stéphane, Jakub; #688422, #688379, #688750, #688771, #686800,
#688133, #688895, #688966, #683986, #688004, #689108, #689029, #683449,
#688196, #689304, #689243, #689295, #689325, #689400, #679168, #689568,
#689537, #689528, #689749, #689789, #689353, #689820, #689868, #689778,
#689959, #688589, #688589, #689955, #687250, #689965, #690046, #690049,
#689884, #682286, #690173, #690174, #672941, #689876, #687881, #690171,
#690241, #690312, #690175, #687955, #650843, #688234, #690427
Contributors:
Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Stéphane Démurget,
Guillaume Desmottes, Tanner Doshier, Piotr Drąg, Sebastian Keller,
Lionel Landwerlin, Tim Lunn, Victoria Martínez de la Cruz, Aleksander Morgado,
Florian Müllner, Bastien Nocera, Marc Plano-Lesay, Carlos Soriano Sánchez,
Jakub Steiner, Jasper St. Pierre, Colin Walters, Dan Winship, Ron Yorston
Translations:
Yuri Myasoedov [ru], Wouter Bolsterlee [nl], Yaron Shahrabani [he],
Nilamdyuti Goswami [as], Ani Peter [ml], Kjartan Maraas [nb],
Dr.T.Vasudevan [ta], A S Alam [pa], Shankar Prasad [kn], Khaled Hosny [ar],
Daniel Mustieles [es], Dušan Kazik [sk]
3.7.2 3.7.2
===== =====
* Enforce RTL in he for messages that might end up as LTR [Florian; #686630] * Enforce RTL in he for messages that might end up as LTR [Florian; #686630]

View File

@@ -13,14 +13,6 @@ PKG_NAME="gnome-shell"
exit 1 exit 1
} }
# Fetch submodules if needed
if test ! -f src/gvc/Makefile.am;
then
echo "+ Setting up submodules"
git submodule init
fi
git submodule update
which gnome-autogen.sh || { which gnome-autogen.sh || {
echo "You need to install gnome-common from GNOME Git (or from" echo "You need to install gnome-common from GNOME Git (or from"
echo "your OS vendor's package manager)." echo "your OS vendor's package manager)."

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.7.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.7.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@@ -65,7 +65,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.11.11 CLUTTER_MIN_VERSION=1.11.11
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.33.2 GJS_MIN_VERSION=1.33.2
MUTTER_MIN_VERSION=3.7.3 MUTTER_MIN_VERSION=3.7.2
GTK_MIN_VERSION=3.3.9 GTK_MIN_VERSION=3.3.9
GIO_MIN_VERSION=2.35.0 GIO_MIN_VERSION=2.35.0
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3
@@ -79,7 +79,6 @@ GCR_MIN_VERSION=3.3.90
GNOME_DESKTOP_REQUIRED_VERSION=3.7.1 GNOME_DESKTOP_REQUIRED_VERSION=3.7.1
GNOME_MENUS_REQUIRED_VERSION=3.5.3 GNOME_MENUS_REQUIRED_VERSION=3.5.3
NETWORKMANAGER_MIN_VERSION=0.9.7 NETWORKMANAGER_MIN_VERSION=0.9.7
PULSE_MIN_VERS=2.0
# Collect more than 20 libraries for a prize! # Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
@@ -126,8 +125,8 @@ LIBS=$saved_LIBS
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION) 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(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(TRAY, gtk+-3.0) PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0) PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2.2) PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2)
AC_MSG_CHECKING([for bluetooth support]) AC_MSG_CHECKING([for bluetooth support])
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0], PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
@@ -270,7 +269,6 @@ AC_CONFIG_FILES([
js/Makefile js/Makefile
src/calendar-server/evolution-calendar.desktop.in src/calendar-server/evolution-calendar.desktop.in
src/Makefile src/Makefile
src/gvc/Makefile
browser-plugin/Makefile browser-plugin/Makefile
tests/Makefile tests/Makefile
po/Makefile.in po/Makefile.in

View File

@@ -11,9 +11,7 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
@INTLTOOL_DESKTOP_RULE@ @INTLTOOL_DESKTOP_RULE@
introspectiondir = $(datadir)/dbus-1/interfaces introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = \ introspection_DATA = org.gnome.ShellSearchProvider.xml
org.gnome.ShellSearchProvider.xml \
org.gnome.ShellSearchProvider2.xml
themedir = $(pkgdatadir)/theme themedir = $(pkgdatadir)/theme
dist_theme_DATA = \ dist_theme_DATA = \
@@ -34,7 +32,6 @@ dist_theme_DATA = \
theme/gnome-shell.css \ theme/gnome-shell.css \
theme/logged-in-indicator.svg \ theme/logged-in-indicator.svg \
theme/message-tray-background.png \ theme/message-tray-background.png \
theme/more-results.svg \
theme/noise-texture.png \ theme/noise-texture.png \
theme/panel-button-border.svg \ theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \ theme/panel-button-highlight-narrow.svg \
@@ -57,7 +54,9 @@ keys_in_files = \
$(NULL) $(NULL)
keys_DATA = $(keys_in_files:.xml.in=.xml) keys_DATA = $(keys_in_files:.xml.in=.xml)
gsettings_SCHEMAS = org.gnome.shell.gschema.xml gsettings_SCHEMAS = \
org.gnome.shell.gschema.xml \
org.gnome.shell-foo.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@ @INTLTOOL_XML_NOMERGE_RULE@
@@ -84,7 +83,8 @@ EXTRA_DIST = \
$(menu_DATA) \ $(menu_DATA) \
$(convert_DATA) \ $(convert_DATA) \
$(keys_in_files) \ $(keys_in_files) \
org.gnome.shell.gschema.xml.in.in org.gnome.shell.gschema.xml.in.in \
org.gnome.shell-foo.gschema.xml.in.in
CLEANFILES = \ CLEANFILES = \
gnome-shell.desktop.in \ gnome-shell.desktop.in \
@@ -94,4 +94,6 @@ CLEANFILES = \
$(gsettings_SCHEMAS) \ $(gsettings_SCHEMAS) \
gschemas.compiled \ gschemas.compiled \
org.gnome.shell.gschema.valid \ org.gnome.shell.gschema.valid \
org.gnome.shell.gschema.xml.in org.gnome.shell.gschema.xml.in \
org.gnome.shell-foo.gschema.valid \
org.gnome.shell-foo.gschema.xml.in

View File

@@ -2,72 +2,146 @@
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'> 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node> <node>
<!--
org.gnome.Shell.SearchProvider:
@short_description: Search provider interface
The interface used for integrating into GNOME Shell's search
interface. This interface is deprecated, and org.gnome.Shell.SearchProvider2 should be used instead.
-->
<interface name="org.gnome.Shell.SearchProvider"> <interface name="org.gnome.Shell.SearchProvider">
<doc:doc>
<doc:description>
<doc:para>
The interface used for integrating into GNOME Shell's search
interface.
</doc:para>
</doc:description>
</doc:doc>
<!--
GetInitialResultSet:
@terms: Array of search terms, which the provider should treat as logical AND.
@results: An array of result identifier strings representing items which match the given search terms. Identifiers must be unique within the provider's domain, but other than that may be chosen freely by the provider.
Called when the user first begins a search.
-->
<method name="GetInitialResultSet"> <method name="GetInitialResultSet">
<arg type="as" name="terms" direction="in" /> <doc:doc>
<arg type="as" name="results" direction="out" /> <doc:description>
<doc:para>
Called when the user first begins a search.
</doc:para>
</doc:description>
</doc:doc>
<arg type="as" direction="in">
<doc:doc>
<doc:summary>
<doc:para>
Array of search terms, which the provider should treat as
logical AND.
</doc:para>
</doc:summary>
</doc:doc>
</arg>
<arg type="as" direction="out">
<doc:doc>
<doc:summary>
<doc:para>
An array of result identifier strings representing items which
match the given search terms. Identifiers must be unique within
the provider's domain, but other than that may be chosen freely
by the provider.
</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method> </method>
<!--
GetSubsearchResultSet:
@previous_results: Array of results previously returned by GetInitialResultSet().
@terms: Array of updated search terms, which the provider should treat as logical AND.
@results: An array of result identifier strings representing items which match the given search terms. Identifiers must be unique within the provider's domain, but other than that may be chosen freely by the provider.
Called when a search is performed which is a "subsearch" of
the previous search, e.g. the method may return less results, but
not more or different results.
This allows search providers to only search through the previous
result set, rather than possibly performing a full re-query.
-->
<method name="GetSubsearchResultSet"> <method name="GetSubsearchResultSet">
<arg type="as" name="previous_results" direction="in" /> <doc:doc>
<arg type="as" name="terms" direction="in" /> <doc:description>
<arg type="as" name="results" direction="out" /> <doc:para>
Called when a search is performed which is a "subsearch" of
the previous search, e.g. the method may return less results, but
not more or different results.
This allows search providers to only search through the previous
result set, rather than possibly performing a full re-query.
</doc:para>
</doc:description>
</doc:doc>
<arg type="as" direction="in">
<doc:doc>
<doc:summary>
<doc:para>
Array of item identifiers
</doc:para>
</doc:summary>
</doc:doc>
</arg>
<arg type="as" direction="in">
<doc:doc>
<doc:summary>
<doc:para>
Array of updated search terms, which the provider should treat as
logical AND.
</doc:para>
</doc:summary>
</doc:doc>
</arg>
<arg type="as" direction="out">
<doc:doc>
<doc:summary>
<doc:para>
An array of result identifier strings representing items which
match the given search terms. Identifiers must be unique within
the provider's domain, but other than that may be chosen freely
by the provider.
</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method> </method>
<!--
GetResultMetas:
@identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet()
@metas: A dictionary describing the given search result, containing 'id' and 'name' (both strings). Optionally, either 'gicon' (a serialized GIcon) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) can be specified if the result can be better served with a thumbnail of the content (such as with images).
Return an array of meta data used to display each given result
-->
<method name="GetResultMetas"> <method name="GetResultMetas">
<arg type="as" name="identifiers" direction="in" /> <doc:doc>
<arg type="aa{sv}" name="metas" direction="out" /> <doc:description>
<doc:para>
Return an array of meta data used to display each given result
</doc:para>
</doc:description>
</doc:doc>
<arg type="as" direction="in">
<doc:doc>
<doc:summary>
<doc:para>
An array of result identifiers as returned by
GetInitialResultSet() or GetSubsearchResultSet()
</doc:para>
</doc:summary>
</doc:doc>
</arg>
<arg type="aa{sv}" direction="out">
<doc:doc>
<doc:summary>
<doc:para>
A dictionary describing the given search result, containing
'id', 'name' (both strings) and either 'icon' (a serialized
GIcon) or 'icon-data' (raw image data as (iiibiiay) - width,
height, rowstride, has-alpha, bits per sample, channels, data)
</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method> </method>
<!--
ActivateResult:
@identifier: A result identifier as returned by GetInitialResultSet() or GetSubsearchResultSet()
Called when the users chooses a given result. The result should
be displayed in the application associated with the corresponding
provider.
This method is deprecated, and providers should implement ActivateResult2()
instead.
-->
<method name="ActivateResult"> <method name="ActivateResult">
<arg type="s" name="identifier" direction="in" /> <doc:doc>
<doc:description>
<doc:para>
Called when the users chooses a given result. The result should
be displayed in the application associated with the corresponding
provider.
</doc:para>
</doc:description>
</doc:doc>
<arg type="s" direction="in">
<doc:doc>
<doc:summary>
<doc:para>
A result identifier as returned by GetInitialResultSet() or
GetSubsearchResultSet()
</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method> </method>
</interface> </interface>
</node> </node>

View File

@@ -1,87 +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.SearchProvider2:
@short_description: Search provider interface
The interface used for integrating into GNOME Shell's search
interface (version 2).
-->
<interface name="org.gnome.Shell.SearchProvider2">
<!--
GetInitialResultSet:
@terms: Array of search terms, which the provider should treat as logical AND.
@results: An array of result identifier strings representing items which match the given search terms. Identifiers must be unique within the provider's domain, but other than that may be chosen freely by the provider.
Called when the user first begins a search.
-->
<method name="GetInitialResultSet">
<arg type="as" name="terms" direction="in" />
<arg type="as" name="results" direction="out" />
</method>
<!--
GetSubsearchResultSet:
@previous_results: Array of results previously returned by GetInitialResultSet().
@terms: Array of updated search terms, which the provider should treat as logical AND.
@results: An array of result identifier strings representing items which match the given search terms. Identifiers must be unique within the provider's domain, but other than that may be chosen freely by the provider.
Called when a search is performed which is a "subsearch" of
the previous search, e.g. the method may return less results, but
not more or different results.
This allows search providers to only search through the previous
result set, rather than possibly performing a full re-query.
-->
<method name="GetSubsearchResultSet">
<arg type="as" name="previous_results" direction="in" />
<arg type="as" name="terms" direction="in" />
<arg type="as" name="results" direction="out" />
</method>
<!--
GetResultMetas:
@identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet()
@metas: A dictionary describing the given search result, containing 'id' and 'name' (both strings). Optionally, either 'gicon' (a serialized GIcon) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) can be specified if the result can be better served with a thumbnail of the content (such as with images). A 'description' field (string) may also be specified if more context would help the user find the desired result.
Return an array of meta data used to display each given result
-->
<method name="GetResultMetas">
<arg type="as" name="identifiers" direction="in" />
<arg type="aa{sv}" name="metas" direction="out" />
</method>
<!--
ActivateResult:
@identifier: A result identifier as returned by GetInitialResultSet() or GetSubsearchResultSet()
@terms: Array of search terms, which the provider should treat as logical AND.
@timestamp: A timestamp of the user interaction that triggered this call
Called when the users chooses a given result. The result should
be displayed in the application associated with the corresponding
provider. The provided search terms can be used to allow launching a full search in
the application.
-->
<method name="ActivateResult">
<arg type="s" name="identifier" direction="in" />
<arg type="as" name="terms" direction="in" />
<arg type="u" name="timestamp" direction="in" />
</method>
<!--
LaunchSearch:
@terms: Array of search terms, which the provider should treat as logical AND.
@timestamp: A timestamp of the user interaction that triggered this call
Asks the search provider to launch a full search in the application for the provided terms.
-->
<method name="LaunchSearch">
<arg type="as" name="terms" direction="in" />
<arg type="u" name="timestamp" direction="in" />
</method>
</interface>
</node>

View File

@@ -0,0 +1,13 @@
<schemalist>
<schema id="org.gnome.shell-foo.overrides" path="/org/gnome/shell-foo/overrides/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="button-layout" type="s">
<default>":minimize,close"</default>
<_summary>Arrangement of buttons on the titlebar</_summary>
<_description>
This key overrides the key in org.gnome.desktop.wm.preferences when
running GNOME Shell in Foo mode.
</_description>
</key>
</schema>
</schemalist>

View File

@@ -70,16 +70,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
<_summary>Show full name in the user menu</_summary> <_summary>Show full name in the user menu</_summary>
<_description>Whether the users full name is shown in the user menu or not.</_description> <_description>Whether the users full name is shown in the user menu or not.</_description>
</key> </key>
<key name="remember-mount-password" type="b">
<default>false</default>
<_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary>
<_description>
The shell will request a password when an encrypted device or a
remote filesystem is mounted. If the password can be saved for
future use a 'Remember Password' checkbox will be present.
This key sets the default state of the checkbox.
</_description>
</key>
<child name="calendar" schema="org.gnome.shell.calendar"/> <child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="recorder" schema="org.gnome.shell.recorder"/> <child name="recorder" schema="org.gnome.shell.recorder"/>
<child name="keybindings" schema="org.gnome.shell.keybindings"/> <child name="keybindings" schema="org.gnome.shell.keybindings"/>
@@ -186,33 +176,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
</key> </key>
</schema> </schema>
<enum id="org.gnome.shell.window-switcher.AppIconMode">
<value value="1" nick="thumbnail-only"/>
<value value="2" nick="app-icon-only"/>
<value value="3" nick="both"/>
</enum>
<schema id="org.gnome.shell.window-switcher"
path="/org/gnome/shell/window-switcher/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="app-icon-mode" enum="org.gnome.shell.window-switcher.AppIconMode">
<default>'both'</default>
<_summary>The application icon mode.</_summary>
<_description>
Configures how the windows are shown in the switcher. Valid possibilities
are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-only'
(shows only the application icon) or 'both'.
</_description>
</key>
<key type="b" name="current-workspace-only">
<default>false</default>
<summary>Limit switcher to current workspace.</summary>
<description>
If true, only windows from the current workspace are shown in the switcher.
Otherwise, all windows are included.
</description>
</key>
</schema>
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/" <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">
<key name="attach-modal-dialogs" type="b"> <key name="attach-modal-dialogs" type="b">

View File

@@ -49,7 +49,7 @@ stage {
.switcher-list, .switcher-list,
.app-well-app > .overview-icon, .app-well-app > .overview-icon,
.show-apps > .overview-icon, .show-apps > .overview-icon,
.grid-search-result .overview-icon { .search-result-content > .overview-icon {
font-size: 9pt; font-size: 9pt;
font-weight: bold; font-weight: bold;
} }
@@ -558,10 +558,6 @@ StScrollBar StButton#vhandle:active {
spacing: 4px; spacing: 4px;
} }
.lock-screen-status-button-box {
spacing: 8px;
}
/* User Menu */ /* User Menu */
#panelUserMenu { #panelUserMenu {
@@ -617,15 +613,7 @@ StScrollBar StButton#vhandle:active {
/* Overview */ /* Overview */
#overview { #overview {
spacing: 24px; spacing: 40px;
}
#overview-group {
spacing: 32px;
}
.workspaces-display {
spacing: 32px; /* needs to be the same value as #overview-group */
} }
.window-caption { .window-caption {
@@ -714,8 +702,8 @@ StScrollBar StButton#vhandle:active {
} }
.window-picker { .window-picker {
-horizontal-spacing: 32px; -horizontal-spacing: 40px;
-vertical-spacing: 32px; -vertical-spacing: 40px;
} }
/* Dash */ /* Dash */
@@ -772,7 +760,7 @@ StScrollBar StButton#vhandle:active {
#searchResultsContent { #searchResultsContent {
padding-right: 20px; padding-right: 20px;
spacing: 16px; spacing: 36px;
} }
#searchResultsContent:rtl { #searchResultsContent:rtl {
@@ -780,22 +768,11 @@ StScrollBar StButton#vhandle:active {
padding-left: 20px; padding-left: 20px;
} }
.search-section { .search-section-header {
/* This should be equal to #searchResultsContent spacing */ padding: 4px 12px;
spacing: 16px; spacing: 4px;
} color: #6f6f6f;
font-size: .8em;
.search-section-separator {
-gradient-height: 1px;
-gradient-start: rgba(255,255,255,0);
-gradient-end: rgba(255,255,255,0.5);
-margin-horizontal: 1.5em;
height: 1px;
}
.search-section-content {
/* This is the space between the provider icon and the results container */
spacing: 32px;
} }
.search-statustext { .search-statustext {
@@ -804,8 +781,16 @@ StScrollBar StButton#vhandle:active {
font-weight: bold; font-weight: bold;
} }
.list-search-results { .search-section-results {
spacing: 3px; padding: 6px;
}
.search-section-list-results {
spacing: 4px;
}
.results-container {
spacing: 4px;
} }
/* Text labels are an odd number of pixels tall. The uneven top and bottom /* Text labels are an odd number of pixels tall. The uneven top and bottom
@@ -834,7 +819,7 @@ StScrollBar StButton#vhandle:active {
-x-offset: 8px; -x-offset: 8px;
} }
/* Application Launchers, Grid and List results */ /* Application Launchers and Grid */
.icon-grid { .icon-grid {
spacing: 36px; spacing: 36px;
@@ -886,34 +871,9 @@ StScrollBar StButton#vhandle:active {
padding: 4px 8px; padding: 4px 8px;
} }
.list-search-result-content {
spacing: 12px;
padding: 12px;
}
.list-search-result-title {
font-weight: bold;
font-size: 14pt;
color: white;
}
.list-search-result-description {
font-weight: bold;
font-size: 12pt;
color: #eeeeec;
}
.search-provider-icon-more {
width: 16px;
height: 16px;
background-image: url("more-results.svg");
}
.app-well-app > .overview-icon, .app-well-app > .overview-icon,
.show-apps > .overview-icon, .show-apps > .overview-icon,
.search-provider-icon, .search-result-content > .overview-icon {
.list-search-result,
.grid-search-result .overview-icon {
border-radius: 4px; border-radius: 4px;
padding: 3px; padding: 3px;
border: 1px rgba(0,0,0,0); border: 1px rgba(0,0,0,0);
@@ -929,9 +889,7 @@ StScrollBar StButton#vhandle:active {
.app-well-app:hover > .overview-icon, .app-well-app:hover > .overview-icon,
.show-apps:hover > .overview-icon, .show-apps:hover > .overview-icon,
.search-provider-icon:hover, .search-result-content:hover > .overview-icon {
.list-search-result:hover,
.grid-search-result:hover .overview-icon {
background-color: rgba(255,255,255,0.1); background-color: rgba(255,255,255,0.1);
text-shadow: black 0px 2px 2px; text-shadow: black 0px 2px 2px;
transition-duration: 100; transition-duration: 100;
@@ -966,14 +924,10 @@ StScrollBar StButton#vhandle:active {
} }
.app-well-app:focus > .overview-icon, .app-well-app:focus > .overview-icon,
.grid-search-result:focus .overview-icon, .search-result-content:focus > .overview-icon,
.show-apps:focus > .overview-icon, .show-apps:focus > .overview-icon,
.search-provider-icon:focus,
.list-search-result:focus,
.app-well-app:selected > .overview-icon, .app-well-app:selected > .overview-icon,
.grid-search-result:selected .overview-icon, .search-result-content:selected > .overview-icon {
.search-provider-icon:selected,
.list-search-result:selected {
background-color: rgba(255,255,255,0.33); background-color: rgba(255,255,255,0.33);
} }
@@ -1317,10 +1271,6 @@ StScrollBar StButton#vhandle:active {
outline: 1px solid rgba(128, 128, 128, 0.3); outline: 1px solid rgba(128, 128, 128, 0.3);
} }
.message-tray-summary {
height: 72px;
}
.no-messages-label { .no-messages-label {
font-family: cantarell, sans-serif; font-family: cantarell, sans-serif;
font-size: 11pt; font-size: 11pt;
@@ -1329,7 +1279,7 @@ StScrollBar StButton#vhandle:active {
.notification { .notification {
border-radius: 10px 10px 0px 0px; border-radius: 10px 10px 0px 0px;
background: rgba(0,0,0,0.9); background: rgba(0,0,0,0.8);
padding: 8px 8px 4px 8px; padding: 8px 8px 4px 8px;
spacing-rows: 10px; spacing-rows: 10px;
spacing-columns: 10px; spacing-columns: 10px;
@@ -1361,7 +1311,7 @@ StScrollBar StButton#vhandle:active {
.summary-boxpointer { .summary-boxpointer {
-arrow-border-radius: 15px; -arrow-border-radius: 15px;
-arrow-background-color: rgba(0,0,0,0.9); -arrow-background-color: rgba(0,0,0,0.8);
-arrow-base: 36px; -arrow-base: 36px;
-arrow-rise: 18px; -arrow-rise: 18px;
color: white; color: white;
@@ -1549,6 +1499,10 @@ StScrollBar StButton#vhandle:active {
border-radius: 4px; border-radius: 4px;
} }
#summary-mode {
height: 72px;
}
.summary-source-button { .summary-source-button {
padding: 6px 3px 6px 3px; padding: 6px 3px 6px 3px;
} }
@@ -1578,17 +1532,17 @@ StScrollBar StButton#vhandle:active {
.summary-source-counter { .summary-source-counter {
background-image: url("summary-counter.svg"); background-image: url("summary-counter.svg");
background-size: 2.4em; background-size: 2.5em;
font-size: 10pt; font-size: 10pt;
font-weight: bold; font-weight: bold;
height: 2.4em; height: 2.5em;
width: 2.4em; width: 2.5em;
-shell-counter-overlap-x: 13px; -shell-counter-overlap-x: 4px;
-shell-counter-overlap-y: 13px; -shell-counter-overlap-y: 4px;
} }
/* App Switcher */ /* App Switcher */
.switcher-popup { #altTabPopup {
padding: 8px; padding: 8px;
spacing: 16px; spacing: 16px;
} }
@@ -2405,21 +2359,16 @@ StScrollBar StButton#vhandle:active {
} }
.screen-shield-notification-source { .screen-shield-notification-source {
padding: 13px 24px; padding: 0 24px;
spacing: 5px; spacing: 5px;
} }
.screen-shield-notification-label { .screen-shield-notification-label {
font-size: 1.2em; font-size: 1.2em;
font-weight: bold; font-weight: bold;
padding: 0px 18px;
color: #babdb6; color: #babdb6;
} }
.screen-shield-notification-count-text {
padding: 0px 18px;
}
/* Remove background from notifications, otherwise /* Remove background from notifications, otherwise
opacity is doubled and they look darker opacity is doubled and they look darker
*/ */
@@ -2435,8 +2384,3 @@ StScrollBar StButton#vhandle:active {
padding-bottom: 0px; padding-bottom: 0px;
} }
.input-source-switcher-symbol {
font-size: 42pt;
width: 96px;
height: 96px;
}

View File

@@ -1,109 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg12430"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="more-results.svg">
<defs
id="defs12432" />
<sodipodi:namedview
id="base"
pagecolor="#7a7a7a"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="8.3155237"
inkscape:cy="0.89548874"
inkscape:document-units="px"
inkscape:current-layer="g14642-3-0"
showgrid="false"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="1200"
inkscape:window-y="187"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13002" />
</sodipodi:namedview>
<metadata
id="metadata12435">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
style="display:inline"
transform="translate(-141.99984,638.37113)"
inkscape:label="zoom-in"
id="g14642-3-0">
<path
sodipodi:type="inkscape:offset"
inkscape:radius="0"
inkscape:original="M 145.1875 400 C 144.5248 400 144 400.54899 144 401.21875 L 144 410.78125 C 144 411.45101 144.5248 412 145.1875 412 L 154.8125 412 C 155.4752 412 156 411.45101 156 410.78125 L 156 401.21875 C 156 400.54899 155.4752 400 154.8125 400 L 145.1875 400 z M 149 403 L 151 403 L 151 405 L 153 405 L 153 407 L 151 407 L 151 409 L 149 409 L 149 407 L 147 407 L 147 405 L 149 405 L 149 403 z "
xlink:href="#rect11749-5-0-1-8"
style="color:#bebebe;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;opacity:0.8"
id="path13004"
inkscape:href="#rect11749-5-0-1-8"
d="M 145.1875,400 C 144.5248,400 144,400.54899 144,401.21875 l 0,9.5625 c 0,0.66976 0.5248,1.21875 1.1875,1.21875 l 9.625,0 c 0.6627,0 1.1875,-0.54899 1.1875,-1.21875 l 0,-9.5625 C 156,400.54899 155.4752,400 154.8125,400 L 145.1875,400 z m 3.8125,3 2,0 0,2 2,0 0,2 -2,0 0,2 -2,0 0,-2 -2,0 0,-2 2,0 L 149,403 Z"
transform="translate(0,1)" />
<use
x="0"
y="0"
xlink:href="#path13004"
id="use11960"
transform="translate(1,-1)"
width="16"
height="16" />
<use
x="0"
y="0"
xlink:href="#use11960"
id="use11962"
transform="translate(-2,0)"
width="16"
height="16" />
<path
inkscape:connector-curvature="0"
style="color:#bebebe;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible"
d="M 145.1875,400 C 144.5248,400 144,400.54899 144,401.21875 l 0,9.5625 c 0,0.66976 0.5248,1.21875 1.1875,1.21875 l 9.625,0 c 0.6627,0 1.1875,-0.54899 1.1875,-1.21875 l 0,-9.5625 C 156,400.54899 155.4752,400 154.8125,400 L 145.1875,400 z m 3.8125,3 2,0 0,2 2,0 0,2 -2,0 0,2 -2,0 0,-2 -2,0 0,-2 2,0 L 149,403 Z"
id="rect11749-5-0-1-8" />
<rect
style="fill:none;stroke:none"
id="rect3620-5-4"
width="15.981825"
height="16"
x="142"
y="398"
rx="0"
ry="0" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -76,23 +76,9 @@ endif
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES= HTML_IMAGES=
doc-gen-org.gnome.Shell.SearchProvider.xml: $(top_srcdir)/data/org.gnome.ShellSearchProvider.xml
gdbus-codegen \
--interface-prefix org.gnome.ShellSearchProvider. \
--generate-docbook doc-gen \
$(top_srcdir)/data/org.gnome.ShellSearchProvider.xml
doc-gen-org.gnome.Shell.SearchProvider2.xml: $(top_srcdir)/data/org.gnome.ShellSearchProvider2.xml
gdbus-codegen \
--interface-prefix org.gnome.ShellSearchProvider2. \
--generate-docbook doc-gen \
$(top_srcdir)/data/org.gnome.ShellSearchProvider2.xml
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml # e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files= \ content_files=
doc-gen-org.gnome.Shell.SearchProvider.xml \
doc-gen-org.gnome.Shell.SearchProvider2.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files # These files must be listed here *and* in content_files

View File

@@ -43,8 +43,6 @@
</chapter> </chapter>
<chapter> <chapter>
<title>Integration helpers and utilities</title> <title>Integration helpers and utilities</title>
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/>
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/>
<xi:include href="xml/shell-global.xml"/> <xi:include href="xml/shell-global.xml"/>
<xi:include href="xml/shell-wm.xml"/> <xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-xfixes-cursor.xml"/> <xi:include href="xml/shell-xfixes-cursor.xml"/>

View File

@@ -52,6 +52,13 @@ its dependencies to build from tarballs.</description>
<gnome:userid>walters</gnome:userid> <gnome:userid>walters</gnome:userid>
</foaf:Person> </foaf:Person>
</maintainer> </maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Dan Winship</foaf:name>
<foaf:mbox rdf:resource="mailto:danw@gnome.org" />
<gnome:userid>danw</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer> <maintainer>
<foaf:Person> <foaf:Person>
<foaf:name>Marina Zhurakhinskaya</foaf:name> <foaf:name>Marina Zhurakhinskaya</foaf:name>

View File

@@ -62,7 +62,6 @@ nobase_dist_js_DATA = \
ui/main.js \ ui/main.js \
ui/messageTray.js \ ui/messageTray.js \
ui/modalDialog.js \ ui/modalDialog.js \
ui/separator.js \
ui/sessionMode.js \ ui/sessionMode.js \
ui/shellEntry.js \ ui/shellEntry.js \
ui/shellMountOperation.js \ ui/shellMountOperation.js \
@@ -86,7 +85,6 @@ nobase_dist_js_DATA = \
ui/status/power.js \ ui/status/power.js \
ui/status/volume.js \ ui/status/volume.js \
ui/status/bluetooth.js \ ui/status/bluetooth.js \
ui/switcherPopup.js \
ui/tweener.js \ ui/tweener.js \
ui/unlockDialog.js \ ui/unlockDialog.js \
ui/userMenu.js \ ui/userMenu.js \

View File

@@ -11,7 +11,6 @@ const Gio = imports.gi.Gio;
const ShellJS = imports.gi.ShellJS; const ShellJS = imports.gi.ShellJS;
const Config = imports.misc.config; const Config = imports.misc.config;
const FileUtils = imports.misc.fileUtils;
const ExtensionType = { const ExtensionType = {
SYSTEM: 1, SYSTEM: 1,
@@ -151,35 +150,53 @@ function installImporter(extension) {
const ExtensionFinder = new Lang.Class({ const ExtensionFinder = new Lang.Class({
Name: 'ExtensionFinder', Name: 'ExtensionFinder',
_loadExtension: function(extensionDir, info, perUserDir) { _scanExtensionsInDirectory: function(dir, type) {
let fileType = info.get_file_type(); let fileEnum;
if (fileType != Gio.FileType.DIRECTORY) let file, info;
return; try {
let uuid = info.get_name(); fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
let existing = extensions[uuid]; } catch(e) {
if (existing) { if (e.domain != Gio.io_error_quark() || e.code != Gio.IOErrorEnum.NOT_FOUND)
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path())); logError(e, 'Could not enumerate extensions directory');
return; return;
} }
let extension; while ((info = fileEnum.next_file(null)) != null) {
let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER let fileType = info.get_file_type();
: ExtensionType.SYSTEM; if (fileType != Gio.FileType.DIRECTORY)
try { continue;
extension = createExtensionObject(uuid, extensionDir, type); let uuid = info.get_name();
} catch(e) { let extensionDir = dir.get_child(uuid);
logError(e, 'Could not load extension %s'.format(uuid));
return; let existing = extensions[uuid];
if (existing) {
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path()));
continue;
}
let extension;
try {
extension = createExtensionObject(uuid, extensionDir, type);
} catch(e) {
logError(e, 'Could not load extension %s'.format(uuid));
continue;
}
this.emit('extension-found', extension);
} }
this.emit('extension-found', extension); fileEnum.close(null);
}, },
scanExtensions: function() { scanExtensions: function() {
let perUserDir = Gio.File.new_for_path(global.userdatadir); let userExtensionsDir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions']));
FileUtils.collectFromDatadirsAsync('extensions', this._scanExtensionsInDirectory(userExtensionsDir, ExtensionType.PER_USER);
{ processFile: Lang.bind(this, this._loadExtension),
includeUserDir: true, let systemDataDirs = GLib.get_system_data_dirs();
data: perUserDir }); for (let i = 0; i < systemDataDirs.length; i++) {
let dirPath = GLib.build_filenamev([systemDataDirs[i], 'gnome-shell', 'extensions']);
let dir = Gio.file_new_for_path(dirPath);
if (dir.query_exists(null))
this._scanExtensionsInDirectory(dir, ExtensionType.SYSTEM);
}
} }
}); });
Signals.addSignalMethods(ExtensionFinder.prototype); Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@@ -2,12 +2,10 @@
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Params = imports.misc.params;
function listDirAsync(file, callback) { function listDirAsync(file, callback) {
let allFiles = []; let allFiles = [];
file.enumerate_children_async('standard::name,standard::type', file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME,
Gio.FileQueryInfoFlags.NONE, Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_LOW, null, function (obj, res) { GLib.PRIORITY_LOW, null, function (obj, res) {
let enumerator = obj.enumerate_children_finish(res); let enumerator = obj.enumerate_children_finish(res);
@@ -25,63 +23,6 @@ function listDirAsync(file, callback) {
}); });
} }
function _collectFromDirectoryAsync(dir, loadState) {
function done() {
loadState.numLoading--;
if (loadState.loadedCallback &&
loadState.numLoading == 0)
loadState.loadedCallback(loadState.data);
}
dir.query_info_async('standard::type', Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT, null, function(object, res) {
try {
object.query_info_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
log(e.message);
done();
return;
}
listDirAsync(dir, Lang.bind(this, function(infos) {
for (let i = 0; i < infos.length; i++)
loadState.processFile(dir.get_child(infos[i].get_name()),
infos[i], loadState.data);
done();
}));
});
}
function collectFromDatadirsAsync(subdir, params) {
params = Params.parse(params, { includeUserDir: false,
processFile: null,
loadedCallback: null,
data: null });
let loadState = { data: params.data,
numLoading: 0,
loadedCallback: params.loadedCallback,
processFile: params.processFile };
if (params.processFile == null) {
if (params.loadedCallback)
params.loadedCallback(params.data);
return;
}
let dataDirs = GLib.get_system_data_dirs();
if (params.includeUserDir)
dataDirs.unshift(GLib.get_user_data_dir());
loadState.numLoading = dataDirs.length;
for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
let dir = Gio.File.new_for_path(path);
_collectFromDirectoryAsync(dir, loadState);
}
}
function deleteGFile(file) { function deleteGFile(file) {
// Work around 'delete' being a keyword in JS. // Work around 'delete' being a keyword in JS.
return file['delete'](null); return file['delete'](null);

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const GMenu = imports.gi.GMenu; const GMenu = imports.gi.GMenu;
@@ -19,6 +18,7 @@ const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Search = imports.ui.search;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace; const Workspace = imports.ui.workspace;
const Params = imports.misc.params; const Params = imports.misc.params;
@@ -48,16 +48,18 @@ const AlphabeticalView = new Lang.Class({
style_class: 'vfade' }); style_class: 'vfade' });
this.actor.add_actor(box); this.actor.add_actor(box);
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
let action = new Clutter.PanAction({ interpolate: true }); this.actor.connect('notify::mapped', Lang.bind(this,
action.connect('pan', Lang.bind(this, this._onPan)); function() {
this.actor.add_action(action); if (!this.actor.mapped)
}, return;
_onPan: function(action) { let adjustment = this.actor.vscroll.adjustment;
let [dist, dx, dy] = action.get_motion_delta(0); let direction = Overview.SwipeScrollDirection.VERTICAL;
let adjustment = this.actor.vscroll.adjustment; Main.overview.setScrollAdjustment(adjustment, direction);
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false; // Reset scroll on mapping
adjustment.value = 0;
}));
}, },
removeAll: function() { removeAll: function() {
@@ -221,7 +223,7 @@ const ViewByCategories = new Lang.Class({
this._loadCategory(dir, apps); this._loadCategory(dir, apps);
if (apps.length == 0) if (apps.length == 0)
return false; return;
} }
let button = new St.Button({ label: GLib.markup_escape_text (name, -1), let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
@@ -242,7 +244,6 @@ const ViewByCategories = new Lang.Class({
} }
this._categoryBox.add(button, { expand: true, x_fill: true, y_fill: false }); this._categoryBox.add(button, { expand: true, x_fill: true, y_fill: false });
return true;
}, },
_removeAll: function() { _removeAll: function() {
@@ -268,9 +269,8 @@ const ViewByCategories = new Lang.Class({
var dir = iter.get_directory(); var dir = iter.get_directory();
if (dir.get_is_nodisplay()) if (dir.get_is_nodisplay())
continue; continue;
this._addCategory(dir.get_name(), i, dir);
if (this._addCategory(dir.get_name(), i, dir)) i++;
i++;
} }
} }
@@ -311,10 +311,11 @@ const AllAppDisplay = new Lang.Class({
const AppSearchProvider = new Lang.Class({ const AppSearchProvider = new Lang.Class({
Name: 'AppSearchProvider', Name: 'AppSearchProvider',
Extends: Search.SearchProvider,
_init: function() { _init: function() {
this.parent(_("APPLICATIONS"));
this._appSys = Shell.AppSystem.get_default(); this._appSys = Shell.AppSystem.get_default();
this.id = 'applications';
}, },
getResultMetas: function(apps, callback) { getResultMetas: function(apps, callback) {
@@ -339,15 +340,18 @@ const AppSearchProvider = new Lang.Class({
this.searchSystem.pushResults(this, this._appSys.subsearch(previousResults, terms)); this.searchSystem.pushResults(this, this._appSys.subsearch(previousResults, terms));
}, },
activateResult: function(app) { activateResult: function(app, params) {
params = Params.parse(params, { workspace: -1,
timestamp: 0 });
let event = Clutter.get_current_event(); let event = Clutter.get_current_event();
let modifiers = event ? event.get_state() : 0; let modifiers = event ? event.get_state() : 0;
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK; let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
if (openNewWindow) if (openNewWindow)
app.open_new_window(-1); app.open_new_window(params.workspace);
else else
app.activate(); app.activate_full(params.workspace, params.timestamp);
}, },
dragActivateResult: function(id, params) { dragActivateResult: function(id, params) {
@@ -367,10 +371,13 @@ const AppSearchProvider = new Lang.Class({
const SettingsSearchProvider = new Lang.Class({ const SettingsSearchProvider = new Lang.Class({
Name: 'SettingsSearchProvider', Name: 'SettingsSearchProvider',
Extends: Search.SearchProvider,
_init: function() { _init: function() {
this.appInfo = Gio.DesktopAppInfo.new('gnome-control-center.desktop'); this.parent(_("SETTINGS"));
this._appSys = Shell.AppSystem.get_default(); this._appSys = Shell.AppSystem.get_default();
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
}, },
getResultMetas: function(prefs, callback) { getResultMetas: function(prefs, callback) {
@@ -379,7 +386,9 @@ const SettingsSearchProvider = new Lang.Class({
let pref = prefs[i]; let pref = prefs[i];
metas.push({ 'id': pref, metas.push({ 'id': pref,
'name': pref.get_name(), 'name': pref.get_name(),
'createIcon': function() { return null; } 'createIcon': function(size) {
return pref.create_icon_texture(size);
}
}); });
} }
callback(metas); callback(metas);
@@ -393,13 +402,21 @@ const SettingsSearchProvider = new Lang.Class({
this.searchSystem.pushResults(this, this._appSys.search_settings(terms)); this.searchSystem.pushResults(this, this._appSys.search_settings(terms));
}, },
activateResult: function(pref) { activateResult: function(pref, params) {
pref.activate(); params = Params.parse(params, { workspace: -1,
timestamp: 0 });
pref.activate_full(params.workspace, params.timestamp);
}, },
launchSearch: function(terms) { dragActivateResult: function(pref, params) {
// FIXME: this should be a remote search provider this.activateResult(pref, params);
this.appInfo.launch([], global.create_app_launch_context()); },
createResultActor: function (resultMeta, terms) {
let app = resultMeta['id'];
let icon = new AppWellIcon(app);
return icon.actor;
} }
}); });
@@ -554,7 +571,6 @@ const AppWellIcon = new Lang.Class({
this.actor.set_hover(true); this.actor.set_hover(true);
this._menu.popup(); this._menu.popup();
this._menuManager.ignoreRelease();
return false; return false;
}, },

View File

@@ -11,6 +11,7 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const MSECS_IN_DAY = 24 * 60 * 60 * 1000; const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const WEEKDATE_HEADER_WIDTH_DIGITS = 3;
const SHOW_WEEKDATE_KEY = 'show-weekdate'; const SHOW_WEEKDATE_KEY = 'show-weekdate';
// in org.gnome.desktop.interface // in org.gnome.desktop.interface
@@ -94,6 +95,15 @@ function _getCalendarWeekForDate(date) {
return weekNumber; return weekNumber;
} }
function _getDigitWidth(actor){
let context = actor.get_pango_context();
let themeNode = actor.get_theme_node();
let font = themeNode.get_font();
let metrics = context.get_metrics(font, context.get_language());
let width = metrics.get_approximate_digit_width();
return width;
}
function _getCalendarDayAbbreviation(dayNumber) { function _getCalendarDayAbbreviation(dayNumber) {
let abbreviations = [ let abbreviations = [
/* Translators: Calendar grid abbreviation for Sunday. /* Translators: Calendar grid abbreviation for Sunday.
@@ -335,6 +345,8 @@ const Calendar = new Lang.Class({
_init: function() { _init: function() {
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
this._weekdate = NaN;
this._digitWidth = NaN;
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' }); this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange)); this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
@@ -407,6 +419,8 @@ const Calendar = new Lang.Class({
this.actor.add(this._topBox, this.actor.add(this._topBox,
{ row: 0, col: 0, col_span: offsetCols + 7 }); { row: 0, col: 0, col_span: offsetCols + 7 });
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChange));
let back = new St.Button({ style_class: 'calendar-change-month-back' }); let back = new St.Button({ style_class: 'calendar-change-month-back' });
this._topBox.add(back); this._topBox.add(back);
back.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked)); back.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
@@ -443,6 +457,18 @@ const Calendar = new Lang.Class({
this._firstDayIndex = this.actor.get_n_children(); this._firstDayIndex = this.actor.get_n_children();
}, },
_onStyleChange: function(actor, event) {
// width of a digit in pango units
this._digitWidth = _getDigitWidth(this.actor) / Pango.SCALE;
this._setWeekdateHeaderWidth();
},
_setWeekdateHeaderWidth: function() {
if (this.digitWidth != NaN && this._useWeekdate && this._weekdateHeader) {
this._weekdateHeader.set_width (this._digitWidth * WEEKDATE_HEADER_WIDTH_DIGITS);
}
},
_onScroll : function(actor, event) { _onScroll : function(actor, event) {
switch (event.get_scroll_direction()) { switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP: case Clutter.ScrollDirection.UP:

View File

@@ -613,8 +613,7 @@ const NetworkAgent = new Lang.Class({
this._vpnRequests = { }; this._vpnRequests = { };
this._native.auto_register = false; this._native.auto_register = false;
if (this._native.registered) this._native.unregister();
this._native.unregister();
}, },
_newRequest: function(agent, requestId, connection, settingName, hints, flags) { _newRequest: function(agent, requestId, connection, settingName, hints, flags) {

View File

@@ -478,7 +478,7 @@ const ChatSource = new Lang.Class({
})); }));
item.connect('activate', Lang.bind(this, function() { item.connect('activate', Lang.bind(this, function() {
this.setMuted(!this.isMuted); this.setMuted(!this.isMuted);
this.emit('done-displaying-content', false); this.emit('done-displaying-content');
})); }));
rightClickMenu.add(item.actor); rightClickMenu.add(item.actor);
return rightClickMenu; return rightClickMenu;
@@ -926,24 +926,26 @@ const ChatNotification = new Lang.Class({
} }
// Show the word "Yesterday" and time if date is on yesterday // Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){ else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/ /* Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"*/
// xgettext:no-c-format // xgettext:no-c-format
format = _("<b>Yesterday</b>, <b>%H:%M</b>"); format = _("<b>%H:%M</b> on Yesterday");
} }
// Show a week day and time if date is in the last week // Show a week day and time if date is in the last week
else if (daysAgo < 7) { else if (daysAgo < 7) {
/* Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/ /* Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday*/
// xgettext:no-c-format // xgettext:no-c-format
format = _("<b>%A</b>, <b>%H:%M</b>"); format = _("<b>%H:%M</b> on <b>%A</b>");
} else if (date.getYear() == now.getYear()) { } else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/ /* Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
shown when you get a chat message in the same year */
// xgettext:no-c-format // xgettext:no-c-format
format = _("<b>%B</b> <b>%d</b>, <b>%H:%M</b>"); format = _("<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>");
} else { } else {
/* Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/ /* Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
shown when you get a chat message in a different year */
// xgettext:no-c-format // xgettext:no-c-format
format = _("<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "); format = _("<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y");
} }
return date.toLocaleFormat(format); return date.toLocaleFormat(format);

View File

@@ -1,14 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Lang = imports.lang; const Lang = imports.lang;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const AltTab = imports.ui.altTab;
const Main = imports.ui.main; const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@@ -26,9 +27,6 @@ const CtrlAltTabManager = new Lang.Class({
_init: function() { _init: function() {
this._items = []; this._items = [];
this.addGroup(global.window_group, _("Windows"),
'emblem-documents-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: Lang.bind(this, this._focusWindows) });
}, },
addGroup: function(root, name, icon, params) { addGroup: function(root, name, icon, params) {
@@ -42,13 +40,11 @@ const CtrlAltTabManager = new Lang.Class({
this._items.push(item); this._items.push(item);
root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); })); root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); }));
if (root instanceof St.Widget) global.focus_manager.add_group(root);
global.focus_manager.add_group(root);
}, },
removeGroup: function(root) { removeGroup: function(root) {
if (root instanceof St.Widget) global.focus_manager.remove_group(root);
global.focus_manager.remove_group(root);
for (let i = 0; i < this._items.length; i++) { for (let i = 0; i < this._items.length; i++) {
if (this._items[i].root == root) { if (this._items[i].root == root) {
this._items.splice(i, 1); this._items.splice(i, 1);
@@ -57,9 +53,11 @@ const CtrlAltTabManager = new Lang.Class({
} }
}, },
focusGroup: function(item, timestamp) { focusGroup: function(item) {
if (item.focusCallback) { if (item.window) {
item.focusCallback(timestamp); Main.activateWindow(item.window);
} else if (item.focusCallback) {
item.focusCallback();
} else { } else {
if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE || if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
global.stage_input_mode == Shell.StageInputMode.NORMAL) global.stage_input_mode == Shell.StageInputMode.NORMAL)
@@ -77,14 +75,24 @@ const CtrlAltTabManager = new Lang.Class({
if (a.sortGroup != b.sortGroup) if (a.sortGroup != b.sortGroup)
return a.sortGroup - b.sortGroup; return a.sortGroup - b.sortGroup;
let ax, bx, y; let y;
[ax, y] = a.proxy.get_transformed_position(); if (a.x == undefined) {
[bx, y] = b.proxy.get_transformed_position(); if (a.window)
a.x = a.window.get_compositor_private().x;
else
[a.x, y] = a.proxy.get_transformed_position();
}
if (b.x == undefined) {
if (b.window)
b.x = b.window.get_compositor_private().x;
else
[b.x, y] = b.proxy.get_transformed_position();
}
return ax - bx; return a.x - b.x;
}, },
popup: function(backward, binding, mask) { popup: function(backwards, mask) {
// Start with the set of focus groups that are currently mapped // Start with the set of focus groups that are currently mapped
let items = this._items.filter(function (item) { return item.proxy.mapped; }); let items = this._items.filter(function (item) { return item.proxy.mapped; });
@@ -102,7 +110,8 @@ const CtrlAltTabManager = new Lang.Class({
icon = app.create_icon_texture(POPUP_APPICON_SIZE); icon = app.create_icon_texture(POPUP_APPICON_SIZE);
else else
icon = textureCache.bind_pixbuf_property(windows[i], 'icon'); icon = textureCache.bind_pixbuf_property(windows[i], 'icon');
items.push({ name: windows[i].title, items.push({ window: windows[i],
name: windows[i].title,
iconActor: icon, iconActor: icon,
sortGroup: SortGroup.MIDDLE }); sortGroup: SortGroup.MIDDLE });
} }
@@ -114,63 +123,187 @@ const CtrlAltTabManager = new Lang.Class({
items.sort(Lang.bind(this, this._sortItems)); items.sort(Lang.bind(this, this._sortItems));
if (!this._popup) { if (!this._popup) {
this._popup = new CtrlAltTabPopup(items); this._popup = new CtrlAltTabPopup();
this._popup.show(backward, binding, mask); this._popup.show(items, backwards, mask);
this._popup.actor.connect('destroy', this._popup.actor.connect('destroy',
Lang.bind(this, function() { Lang.bind(this, function() {
this._popup = null; this._popup = null;
})); }));
} }
},
_focusWindows: function(timestamp) {
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
global.stage.key_focus = null;
global.screen.focus_default_window(timestamp);
} }
}); });
function mod(a, b) {
return (a + b) % b;
}
const CtrlAltTabPopup = new Lang.Class({ const CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup', Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup,
_createSwitcher: function() { _init : function() {
this._switcherList = new CtrlAltTabSwitcher(this._items); this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
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));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._haveModal = false;
this._modifierMask = 0;
this._selection = 0;
Main.uiGroup.add_actor(this.actor);
},
_getPreferredWidth: function (actor, forHeight, alloc) {
let primary = Main.layoutManager.primaryMonitor;
alloc.min_size = primary.width;
alloc.natural_size = primary.width;
},
_getPreferredHeight: function (actor, forWidth, alloc) {
let primary = Main.layoutManager.primaryMonitor;
alloc.min_size = primary.height;
alloc.natural_size = primary.height;
},
_allocate: function (actor, box, flags) {
let childBox = new Clutter.ActorBox();
let primary = Main.layoutManager.primaryMonitor;
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let vPadding = this.actor.get_theme_node().get_vertical_padding();
let hPadding = this.actor.get_theme_node().get_horizontal_padding();
let [childMinHeight, childNaturalHeight] = this._switcher.actor.get_preferred_height(primary.width - hPadding);
let [childMinWidth, childNaturalWidth] = this._switcher.actor.get_preferred_width(childNaturalHeight);
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
childBox.x2 = Math.min(primary.x + primary.width - hPadding, childBox.x1 + childNaturalWidth);
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._switcher.actor.allocate(childBox, flags);
},
show : function(items, startBackwards, mask) {
if (!Main.pushModal(this.actor))
return false;
this._haveModal = true;
this._modifierMask = AltTab.primaryModifier(mask);
this._keyPressEventId = this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
this._keyReleaseEventId = this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
this._items = items;
this._switcher = new CtrlAltTabSwitcher(items);
this.actor.add_actor(this._switcher.actor);
if (startBackwards)
this._selection = this._items.length - 1;
this._select(this._selection);
let [x, y, mods] = global.get_pointer();
if (!(mods & this._modifierMask)) {
this._finish();
return false;
}
this.actor.opacity = 0;
this.actor.show();
Tweener.addTween(this.actor,
{ opacity: 255,
time: POPUP_FADE_TIME,
transition: 'easeOutQuad'
});
return true; return true;
}, },
_initialSelection: function(backward, binding) { _next : function() {
if (binding == 'switch-panels') { return mod(this._selection + 1, this._items.length);
if (backward)
this._selectedIndex = this._items.length - 1;
} else if (binding == 'switch-panels-backward') {
if (!backward)
this._selectedIndex = this._items.length - 1;
}
this._select(this._selectedIndex);
}, },
_keyPressHandler: function(keysym, backwards, action) { _previous : function() {
if (action == Meta.KeyBindingAction.SWITCH_PANELS) return mod(this._selection - 1, this._items.length);
this._select(backwards ? this._previous() : this._next()); },
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(backwards ? this._next() : this._previous()); _keyPressEvent : function(actor, event) {
else if (keysym == Clutter.Left) let keysym = event.get_key_symbol();
this._select(this._previous()); let shift = (event.get_state() & Clutter.ModifierType.SHIFT_MASK);
else if (keysym == Clutter.Right) if (shift && keysym == Clutter.KEY_Tab)
keysym = Clutter.ISO_Left_Tab;
if (keysym == Clutter.KEY_Escape)
this.destroy();
else if (keysym == Clutter.KEY_Tab)
this._select(this._next()); this._select(this._next());
else if (keysym == Clutter.KEY_ISO_Left_Tab)
this._select(this._previous());
else if (keysym == Clutter.KEY_Left)
this._select(this._previous());
else if (keysym == Clutter.KEY_Right)
this._select(this._next());
return true;
}, },
_finish : function(time) { _keyReleaseEvent : function(actor, event) {
this.parent(time); let [x, y, mods] = global.get_pointer();
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time); let state = mods & this._modifierMask;
if (state == 0)
this._finish();
return true;
}, },
_finish : function() {
this.destroy();
Main.ctrlAltTabManager.focusGroup(this._items[this._selection]);
},
_popModal: function() {
if (this._haveModal) {
Main.popModal(this.actor);
this._haveModal = false;
}
},
destroy : function() {
this._popModal();
Tweener.addTween(this.actor,
{ opacity: 0,
time: POPUP_FADE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this.actor.destroy();
})
});
},
_onDestroy : function() {
this._popModal();
if (this._keyPressEventId)
this.actor.disconnect(this._keyPressEventId);
if (this._keyReleaseEventId)
this.actor.disconnect(this._keyReleaseEventId);
},
_select : function(num) {
this._selection = num;
this._switcher.highlight(num);
}
}); });
const CtrlAltTabSwitcher = new Lang.Class({ const CtrlAltTabSwitcher = new Lang.Class({
Name: 'CtrlAltTabSwitcher', Name: 'CtrlAltTabSwitcher',
Extends: SwitcherPopup.SwitcherList, Extends: AltTab.SwitcherList,
_init : function(items) { _init : function(items) {
this.parent(true); this.parent(true);

View File

@@ -234,7 +234,7 @@ const _Draggable = new Lang.Class({
this._dragY = this._dragStartY = stageY; this._dragY = this._dragStartY = stageY;
if (this.actor._delegate && this.actor._delegate.getDragActor) { if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor(); this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
this._dragActor.reparent(Main.uiGroup); this._dragActor.reparent(Main.uiGroup);
this._dragActor.raise_top(); this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true); Shell.util_set_hidden_from_pick(this._dragActor, true);

View File

@@ -129,7 +129,6 @@ function logExtensionError(uuid, error) {
extension.state = ExtensionState.ERROR; extension.state = ExtensionState.ERROR;
if (!extension.errors) if (!extension.errors)
extension.errors = []; extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message)); log('Extension "%s" had error: %s'.format(uuid, message));
_signals.emit('extension-state-changed', { uuid: uuid, _signals.emit('extension-state-changed', { uuid: uuid,
@@ -212,16 +211,8 @@ function initExtension(uuid) {
_signals.emit('extension-loaded', uuid); _signals.emit('extension-loaded', uuid);
} }
function getEnabledExtensions() {
let extensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
if (!Array.isArray(Main.sessionMode.enabledExtensions))
return extensions;
return Main.sessionMode.enabledExtensions.concat(extensions);
}
function onEnabledExtensionsChanged() { function onEnabledExtensionsChanged() {
let newEnabledExtensions = getEnabledExtensions(); let newEnabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
if (!enabled) if (!enabled)
return; return;
@@ -255,7 +246,7 @@ function onEnabledExtensionsChanged() {
function _loadExtensions() { function _loadExtensions() {
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged); global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
enabledExtensions = getEnabledExtensions(); enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', function(signals, extension) { finder.connect('extension-found', function(signals, extension) {
@@ -297,17 +288,10 @@ function disableAllExtensions() {
} }
function _sessionUpdated() { function _sessionUpdated() {
// For now sessionMode.allowExtensions controls extensions from both the if (Main.sessionMode.allowExtensions)
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (initted)
onEnabledExtensionsChanged();
enableAllExtensions(); enableAllExtensions();
} else { else
disableAllExtensions(); disableAllExtensions();
}
} }
function init() { function init() {

View File

@@ -43,6 +43,7 @@ const GrabHelper = new Lang.Class({
this._actors = []; this._actors = [];
this._capturedEventId = 0; this._capturedEventId = 0;
this._eventId = 0;
this._keyFocusNotifyId = 0; this._keyFocusNotifyId = 0;
this._focusWindowChangedId = 0; this._focusWindowChangedId = 0;
this._ignoreRelease = false; this._ignoreRelease = false;
@@ -77,12 +78,9 @@ const GrabHelper = new Lang.Class({
}, },
_isWithinGrabbedActor: function(actor) { _isWithinGrabbedActor: function(actor) {
let currentActor = this.currentGrab.actor;
while (actor) { while (actor) {
if (this._actors.indexOf(actor) != -1) if (this._actors.indexOf(actor) != -1)
return true; return true;
if (actor == currentActor)
return true;
actor = actor.get_parent(); actor = actor.get_parent();
} }
return false; return false;
@@ -92,14 +90,6 @@ const GrabHelper = new Lang.Class({
return this._grabStack[this._grabStack.length - 1] || {}; return this._grabStack[this._grabStack.length - 1] || {};
}, },
get grabbed() {
return this._grabStack.length > 0;
},
get grabStack() {
return this._grabStack;
},
_findStackIndex: function(actor) { _findStackIndex: function(actor) {
if (!actor) if (!actor)
return -1; return -1;
@@ -111,16 +101,6 @@ const GrabHelper = new Lang.Class({
return -1; return -1;
}, },
_actorInGrabStack: function(actor) {
while (actor) {
let idx = this._findStackIndex(actor);
if (idx >= 0)
return idx;
actor = actor.get_parent();
}
return -1;
},
isActorGrabbed: function(actor) { isActorGrabbed: function(actor) {
return this._findStackIndex(actor) >= 0; return this._findStackIndex(actor) >= 0;
}, },
@@ -160,7 +140,6 @@ const GrabHelper = new Lang.Class({
params = Params.parse(params, { actor: null, params = Params.parse(params, { actor: null,
modal: false, modal: false,
grabFocus: false, grabFocus: false,
focus: null,
onUngrab: null }); onUngrab: null });
let focus = global.stage.key_focus; let focus = global.stage.key_focus;
@@ -178,9 +157,7 @@ const GrabHelper = new Lang.Class({
if (params.grabFocus && !this._takeFocusGrab(hadFocus)) if (params.grabFocus && !this._takeFocusGrab(hadFocus))
return false; return false;
if (params.focus) if (hadFocus || params.grabFocus)
params.focus.grab_key_focus();
else if (hadFocus || params.grabFocus)
_navigateActor(newFocus); _navigateActor(newFocus);
this._grabStack.push(params); this._grabStack.push(params);
@@ -194,6 +171,7 @@ const GrabHelper = new Lang.Class({
return false; return false;
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
} }
this._modalCount++; this._modalCount++;
@@ -210,6 +188,11 @@ const GrabHelper = new Lang.Class({
this._capturedEventId = 0; this._capturedEventId = 0;
} }
if (this._eventId > 0) {
global.stage.disconnect(this._eventId);
this._eventId = 0;
}
Main.popModal(this._owner); Main.popModal(this._owner);
global.sync_pointer(); global.sync_pointer();
}, },
@@ -221,6 +204,7 @@ const GrabHelper = new Lang.Class({
this._grabbedFromKeynav = hadFocus; this._grabbedFromKeynav = hadFocus;
this._preGrabInputMode = global.stage_input_mode; this._preGrabInputMode = global.stage_input_mode;
this._prevFocusedWindow = metaDisplay.focus_window;
if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE || if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
this._preGrabInputMode == Shell.StageInputMode.NORMAL) { this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
@@ -259,7 +243,13 @@ const GrabHelper = new Lang.Class({
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
} }
global.screen.focus_default_window(global.get_current_time()); if (this._prevFocusedWindow) {
let metaDisplay = global.screen.get_display();
if (!metaDisplay.focus_window) {
metaDisplay.set_input_focus_window(this._prevFocusedWindow,
false, global.get_current_time());
}
}
}, },
// ignoreRelease: // ignoreRelease:
@@ -280,8 +270,7 @@ const GrabHelper = new Lang.Class({
// If the actor that was popped from the grab stack was not the actor // If the actor that was popped from the grab stack was not the actor
// That was passed in, this call is ignored. // That was passed in, this call is ignored.
ungrab: function(params) { ungrab: function(params) {
params = Params.parse(params, { actor: this.currentGrab.actor, params = Params.parse(params, { actor: this.currentGrab.actor });
isUser: false });
let grabStackIndex = this._findStackIndex(params.actor); let grabStackIndex = this._findStackIndex(params.actor);
if (grabStackIndex < 0) if (grabStackIndex < 0)
@@ -299,7 +288,7 @@ const GrabHelper = new Lang.Class({
let poppedGrab = poppedGrabs[i]; let poppedGrab = poppedGrabs[i];
if (poppedGrab.onUngrab) if (poppedGrab.onUngrab)
poppedGrab.onUngrab(params.isUser); poppedGrab.onUngrab();
if (poppedGrab.modal) if (poppedGrab.modal)
this._releaseModalGrab(); this._releaseModalGrab();
@@ -322,18 +311,12 @@ const GrabHelper = new Lang.Class({
if (release && this._ignoreRelease) { if (release && this._ignoreRelease) {
this._ignoreRelease = false; this._ignoreRelease = false;
return true; return false;
} }
if (!button && this._modalCount == 0) if (!button && this._modalCount == 0)
return false; 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())) if (this._isWithinGrabbedActor(event.get_source()))
return false; return false;
@@ -345,22 +328,33 @@ const GrabHelper = new Lang.Class({
// which should be a release event. // which should be a release event.
if (press) if (press)
this._ignoreRelease = true; this._ignoreRelease = true;
let i = this._actorInGrabStack(event.get_source()) + 1; this.ungrab({ actor: this._grabStack[0].actor });
this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
} }
return this._modalCount > 0; return this._modalCount > 0;
}, },
// We catch 'event' rather than 'key-press-event' so that we get
// a chance to run before the overview's own Escape check
_onEvent: function(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab();
return true;
}
return false;
},
_onKeyFocusChanged: function() { _onKeyFocusChanged: function() {
let focus = global.stage.key_focus; let focus = global.stage.key_focus;
if (!focus || !this._isWithinGrabbedActor(focus)) if (!focus || !this._isWithinGrabbedActor(focus))
this.ungrab({ isUser: true }); this.ungrab();
}, },
_focusWindowChanged: function() { _focusWindowChanged: function() {
let metaDisplay = global.screen.get_display(); let metaDisplay = global.screen.get_display();
if (metaDisplay.focus_window != null) if (metaDisplay.focus_window != null)
this.ungrab({ isUser: true }); this.ungrab();
} }
}); });

View File

@@ -23,8 +23,6 @@ const BaseIcon = new Lang.Class({
this.actor._delegate = this; this.actor._delegate = this;
this.actor.connect('style-changed', this.actor.connect('style-changed',
Lang.bind(this, this._onStyleChanged)); Lang.bind(this, this._onStyleChanged));
this.actor.connect('destroy',
Lang.bind(this, this._onDestroy));
this._spacing = 0; this._spacing = 0;
@@ -54,9 +52,6 @@ const BaseIcon = new Lang.Class({
this._setSizeManually = params.setSizeManually; this._setSizeManually = params.setSizeManually;
this.icon = null; this.icon = null;
let cache = St.TextureCache.get_default();
this._iconThemeChangedId = cache.connect('icon-theme-changed', Lang.bind(this, this._onIconThemeChanged));
}, },
_allocate: function(actor, box, flags) { _allocate: function(actor, box, flags) {
@@ -151,22 +146,7 @@ const BaseIcon = new Lang.Class({
size = found ? len : ICON_SIZE; size = found ? len : ICON_SIZE;
} }
if (this.iconSize == size && this._iconBin.child)
return;
this._createIconTexture(size); this._createIconTexture(size);
},
_onDestroy: function() {
if (this._iconThemeChangedId > 0) {
let cache = St.TextureCache.get_default();
cache.disconnect(this._iconThemeChangedId);
this._iconThemeChangedId = 0;
}
},
_onIconThemeChanged: function() {
this._createIconTexture(this.iconSize);
} }
}); });
@@ -218,11 +198,7 @@ const IconGrid = new Lang.Class({
_getPreferredHeight: function (grid, forWidth, alloc) { _getPreferredHeight: function (grid, forWidth, alloc) {
let children = this._getVisibleChildren(); let children = this._getVisibleChildren();
let nColumns; let [nColumns, usedWidth] = this._computeLayout(forWidth);
if (forWidth < 0)
nColumns = children.length;
else
nColumns = this._computeLayout(forWidth)[0];
let nRows; let nRows;
if (nColumns > 0) if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns); nRows = Math.ceil(children.length / nColumns);

View File

@@ -124,7 +124,7 @@ const LayoutManager = new Lang.Class({
this.addChrome(this.panelBox, { affectsStruts: true, this.addChrome(this.panelBox, { affectsStruts: true,
trackFullscreen: true }); trackFullscreen: true });
this.panelBox.connect('allocation-changed', this.panelBox.connect('allocation-changed',
Lang.bind(this, this._panelBoxChanged)); Lang.bind(this, this._updatePanelBarriers));
this.trayBox = new St.Widget({ name: 'trayBox', this.trayBox = new St.Widget({ name: 'trayBox',
layout_manager: new Clutter.BinLayout() }); layout_manager: new Clutter.BinLayout() });
@@ -256,11 +256,6 @@ const LayoutManager = new Lang.Class({
this.bottomMonitor.width, this.bottomMonitor.height); this.bottomMonitor.width, this.bottomMonitor.height);
}, },
_panelBoxChanged: function() {
this.emit('panel-box-changed');
this._updatePanelBarriers();
},
_updatePanelBarriers: function() { _updatePanelBarriers: function() {
if (this._leftPanelBarrier) if (this._leftPanelBarrier)
global.destroy_pointer_barrier(this._leftPanelBarrier); global.destroy_pointer_barrier(this._leftPanelBarrier);
@@ -325,7 +320,7 @@ const LayoutManager = new Lang.Class({
} else { } else {
let focusWindow = global.display.focus_window; let focusWindow = global.display.focus_window;
if (focusWindow) if (focusWindow)
i = this._chrome.findIndexForWindow(focusWindow); i = this._chrome.findIndexForWindow(focusWindow.get_compositor_private());
} }
return i; return i;
@@ -347,7 +342,7 @@ const LayoutManager = new Lang.Class({
}, },
_startupAnimation: function() { _startupAnimation: function() {
this.panelBox.translation_y = -this.panelBox.height; this.panelBox.anchor_y = this.panelBox.height;
let plymouthTransitionRunning = false; let plymouthTransitionRunning = false;
@@ -383,7 +378,7 @@ const LayoutManager = new Lang.Class({
} }
Tweener.addTween(this.panelBox, Tweener.addTween(this.panelBox,
{ translation_y: 0, { anchor_y: 0,
time: STARTUP_ANIMATION_TIME, time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete, onComplete: this._startupAnimationComplete,
@@ -392,7 +387,6 @@ const LayoutManager = new Lang.Class({
}, },
_startupAnimationComplete: function() { _startupAnimationComplete: function() {
this.emit('panel-box-changed');
this._chrome.thawUpdateRegions(); this._chrome.thawUpdateRegions();
}, },
@@ -513,11 +507,7 @@ const LayoutManager = new Lang.Class({
findMonitorForActor: function(actor) { findMonitorForActor: function(actor) {
return this.monitors[this._chrome.findIndexForActor(actor)]; return this.monitors[this._chrome.findIndexForActor(actor)];
}, }
findMonitorForWindow: function(window) {
return this.monitors[this._chrome.findIndexForWindow(window)];
},
}); });
Signals.addSignalMethods(LayoutManager.prototype); Signals.addSignalMethods(LayoutManager.prototype);
@@ -895,8 +885,7 @@ const Chrome = new Lang.Class({
}, },
findIndexForWindow: function(window) { findIndexForWindow: function(window) {
let rect = window.get_input_rect(); let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
let i = this._findMonitorForRect(rect.x, rect.y, rect.width, rect.height);
if (i >= 0) if (i >= 0)
return i; return i;
return this._primaryIndex; // Not on any monitor, pretend its on the primary return this._primaryIndex; // Not on any monitor, pretend its on the primary
@@ -914,8 +903,7 @@ const Chrome = new Lang.Class({
}, },
findMonitorForWindow: function(window) { findMonitorForWindow: function(window) {
let rect = window.get_input_rect(); let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
let i = this._findMonitorForRect(rect.x, rect.y, rect.width, rect.height);
if (i >= 0) if (i >= 0)
return this._monitors[i]; return this._monitors[i];
else else
@@ -964,15 +952,14 @@ const Chrome = new Lang.Class({
for (let i = windows.length - 1; i > -1; i--) { for (let i = windows.length - 1; i > -1; i--) {
let window = windows[i]; let window = windows[i];
let metaWindow = window.meta_window; let layer = window.get_meta_window().get_layer();
let layer = metaWindow.get_layer();
// Skip minimized windows // Skip minimized windows
if (!window.showing_on_its_workspace()) if (!window.showing_on_its_workspace())
continue; continue;
if (layer == Meta.StackLayer.FULLSCREEN) { if (layer == Meta.StackLayer.FULLSCREEN) {
let monitor = this.findMonitorForWindow(metaWindow); let monitor = this.findMonitorForWindow(window);
if (monitor) if (monitor)
monitor.inFullscreen = true; monitor.inFullscreen = true;
} }
@@ -989,7 +976,7 @@ const Chrome = new Lang.Class({
} }
// Or whether it is monitor sized // Or whether it is monitor sized
let monitor = this.findMonitorForWindow(metaWindow); let monitor = this.findMonitorForWindow(window);
if (monitor && if (monitor &&
window.x <= monitor.x && window.x <= monitor.x &&
window.x + window.width >= monitor.x + monitor.width && window.x + window.width >= monitor.x + monitor.width &&

View File

@@ -49,8 +49,7 @@ const KeybindingMode = {
LOGIN_SCREEN: 1 << 4, LOGIN_SCREEN: 1 << 4,
MESSAGE_TRAY: 1 << 5, MESSAGE_TRAY: 1 << 5,
SYSTEM_MODAL: 1 << 6, SYSTEM_MODAL: 1 << 6,
LOOKING_GLASS: 1 << 7, LOOKING_GLASS: 1 << 7
ALL: ~0,
}; };
let componentManager = null; let componentManager = null;
@@ -110,6 +109,8 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME'); Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode(); sessionMode = new SessionMode.SessionMode();
Meta.prefs_override_preference_schema(sessionMode.buttonLayout[0], sessionMode.buttonLayout[1]);
shellDBusService = new ShellDBus.GnomeShell(); shellDBusService = new ShellDBus.GnomeShell();
shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler(); shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler();
@@ -161,13 +162,13 @@ function start() {
xdndHandler = new XdndHandler.XdndHandler(); xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager(); ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
overview = new Overview.Overview(); overview = new Overview.Overview();
wm = new WindowManager.WindowManager();
magnifier = new Magnifier.Magnifier(); magnifier = new Magnifier.Magnifier();
if (UnlockDialog.isSupported()) if (UnlockDialog.isSupported())
screenShield = new ScreenShield.ScreenShield(); screenShield = new ScreenShield.ScreenShield();
else else
screenShield = new ScreenShield.ScreenShieldFallback(); screenShield = new ScreenShield.ScreenShieldFallback();
panel = new Panel.Panel(); panel = new Panel.Panel();
wm = new WindowManager.WindowManager();
messageTray = new MessageTray.MessageTray(); messageTray = new MessageTray.MessageTray();
keyboard = new Keyboard.Keyboard(); keyboard = new Keyboard.Keyboard();
notificationDaemon = new NotificationDaemon.NotificationDaemon(); notificationDaemon = new NotificationDaemon.NotificationDaemon();
@@ -181,7 +182,7 @@ function start() {
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1); false, -1, 1);
global.display.connect('overlay-key', Lang.bind(overview, overview.toggle)); global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
sessionMode.connect('updated', _sessionUpdated); sessionMode.connect('update', _sessionUpdated);
_sessionUpdated(); _sessionUpdated();
// Provide the bus object for gnome-session to // Provide the bus object for gnome-session to

View File

@@ -1088,14 +1088,14 @@ const Source = new Lang.Class({
item = new PopupMenu.PopupMenuItem(_("Open")); item = new PopupMenu.PopupMenuItem(_("Open"));
item.connect('activate', Lang.bind(this, function() { item.connect('activate', Lang.bind(this, function() {
this.open(); this.open();
this.emit('done-displaying-content', true); this.emit('done-displaying-content');
})); }));
rightClickMenu.add(item.actor); rightClickMenu.add(item.actor);
item = new PopupMenu.PopupMenuItem(_("Remove")); item = new PopupMenu.PopupMenuItem(_("Remove"));
item.connect('activate', Lang.bind(this, function() { item.connect('activate', Lang.bind(this, function() {
this.destroy(); this.destroy();
this.emit('done-displaying-content', false); this.emit('done-displaying-content');
})); }));
rightClickMenu.add(item.actor); rightClickMenu.add(item.actor);
return rightClickMenu; return rightClickMenu;
@@ -1341,7 +1341,7 @@ const SummaryItem = new Lang.Class({
}, },
_notificationDoneDisplaying: function() { _notificationDoneDisplaying: function() {
this.source.emit('done-displaying-content', true); this.source.emit('done-displaying-content');
}, },
_notificationDestroyed: function(notification) { _notificationDestroyed: function(notification) {
@@ -1412,7 +1412,7 @@ const MessageTray = new Lang.Class({
actor.grab_key_focus(); actor.grab_key_focus();
})); }));
global.focus_manager.add_group(this.actor); global.focus_manager.add_group(this.actor);
this._summary = new St.BoxLayout({ style_class: 'message-tray-summary', this._summary = new St.BoxLayout({ name: 'summary-mode',
reactive: true, reactive: true,
track_hover: true, track_hover: true,
x_align: Clutter.ActorAlign.END, x_align: Clutter.ActorAlign.END,
@@ -1441,6 +1441,7 @@ const MessageTray = new Lang.Class({
this._clickedSummaryItem = null; this._clickedSummaryItem = null;
this._clickedSummaryItemMouseButton = -1; this._clickedSummaryItemMouseButton = -1;
this._clickedSummaryItemAllocationChangedId = 0; this._clickedSummaryItemAllocationChangedId = 0;
this._pointerBarrier = 0;
this._closeButton = makeCloseButton(); this._closeButton = makeCloseButton();
this._closeButton.hide(); this._closeButton.hide();
@@ -1485,7 +1486,6 @@ const MessageTray = new Lang.Class({
this._reNotifyAfterHideNotification = null; this._reNotifyAfterHideNotification = null;
this._inFullscreen = false; this._inFullscreen = false;
this._desktopClone = null; this._desktopClone = null;
this._inCtrlAltTab = false;
this._lightbox = new Lightbox.Lightbox(global.window_group, this._lightbox = new Lightbox.Lightbox(global.window_group,
{ inhibitEvents: true, { inhibitEvents: true,
@@ -1563,15 +1563,12 @@ const MessageTray = new Lang.Class({
}, },
_sessionUpdated: function() { _sessionUpdated: function() {
if ((Main.sessionMode.isLocked || Main.sessionMode.isGreeter) && this._inCtrlAltTab) { if (Main.sessionMode.isLocked || Main.sessionMode.isGreeter)
Main.ctrlAltTabManager.removeGroup(this._summary); Main.ctrlAltTabManager.removeGroup(this._summary);
this._inCtrlAltTab = false; else
} else if (!this._inCtrlAltTab) {
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic', Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic',
{ focusCallback: Lang.bind(this, this.toggleAndNavigate), { focusCallback: Lang.bind(this, this.toggleAndNavigate),
sortGroup: CtrlAltTab.SortGroup.BOTTOM }); sortGroup: CtrlAltTab.SortGroup.BOTTOM });
this._inCtrlAltTab = true;
}
this._updateState(); this._updateState();
}, },
@@ -2266,28 +2263,40 @@ const MessageTray = new Lang.Class({
_updateShowingNotification: function() { _updateShowingNotification: function() {
this._notification.acknowledged = true; this._notification.acknowledged = true;
Tweener.removeTweens(this._notificationWidget);
// We auto-expand notifications with CRITICAL urgency. // We auto-expand notifications with CRITICAL urgency.
if (this._notification.urgency == Urgency.CRITICAL) // We use Tweener.removeTweens() to remove a tween that was hiding the notification we are
// updating, in case that notification was in the process of being hidden. However,
// Tweener.removeTweens() would also remove a tween that was updating the position of the
// notification we are updating, in case that notification was already expanded and its height
// changed. Therefore we need to call this._expandNotification() for expanded notifications
// to make sure their position is updated.
if (this._notification.urgency == Urgency.CRITICAL || this._notification.expanded)
this._expandNotification(true); this._expandNotification(true);
// We tween all notifications to full opacity. This ensures that both new notifications and // We tween all notifications to full opacity. This ensures that both new notifications and
// notifications that might have been in the process of hiding get full opacity. // notifications that might have been in the process of hiding get full opacity.
// //
// We tween any notification showing in the banner mode to the appropriate height // We tween any notification showing in the banner mode to banner height
// (which is banner height or expanded height, depending on the notification state) // (this._notificationWidget.y = -this._notificationWidget.height).
// This ensures that both new notifications and notifications in the banner mode that might // This ensures that both new notifications and notifications in the banner mode that might
// have been in the process of hiding are shown with the correct height. // have been in the process of hiding are shown with the banner height.
// //
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated // We use this._showNotificationCompleted() onComplete callback to extend the time the updated
// notification is being shown. // notification is being shown.
//
// We don't set the y parameter for the tween for expanded notifications because
// this._expandNotification() will result in getting this._notificationWidget.y set to the appropriate
// fully expanded value.
let tweenParams = { opacity: 255, let tweenParams = { opacity: 255,
y: -this._notificationWidget.height,
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: this._showNotificationCompleted, onComplete: this._showNotificationCompleted,
onCompleteScope: this onCompleteScope: this
}; };
if (!this._notification.expanded)
tweenParams.y = -this._notificationWidget.height;
this._tween(this._notificationWidget, '_notificationState', State.SHOWN, tweenParams); this._tween(this._notificationWidget, '_notificationState', State.SHOWN, tweenParams);
}, },
@@ -2457,21 +2466,12 @@ const MessageTray = new Lang.Class({
}); });
}, },
_onSourceDoneDisplayingContent: function(source, closeTray) {
if (closeTray) {
this._escapeTray();
} else {
this._setClickedSummaryItem(null);
this._updateState();
}
},
_showSummaryBoxPointer: function() { _showSummaryBoxPointer: function() {
this._summaryBoxPointerItem = this._clickedSummaryItem; this._summaryBoxPointerItem = this._clickedSummaryItem;
this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated', this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated',
Lang.bind(this, this._onSummaryBoxPointerContentUpdated)); Lang.bind(this, this._onSummaryBoxPointerContentUpdated));
this._sourceDoneDisplayingId = this._summaryBoxPointerItem.source.connect('done-displaying-content', this._sourceDoneDisplayingId = this._summaryBoxPointerItem.source.connect('done-displaying-content',
Lang.bind(this, this._onSourceDoneDisplayingContent)); Lang.bind(this, this._escapeTray));
let hasRightClickMenu = this._summaryBoxPointerItem.rightClickMenu != null; let hasRightClickMenu = this._summaryBoxPointerItem.rightClickMenu != null;
if (this._clickedSummaryItemMouseButton == 1 || !hasRightClickMenu) { if (this._clickedSummaryItemMouseButton == 1 || !hasRightClickMenu) {

View File

@@ -23,6 +23,9 @@ const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode // Time for initial animation going into Overview mode
const ANIMATION_TIME = 0.25; const ANIMATION_TIME = 0.25;
// XXX -- grab this automatically. Hard to do.
const DASH_MAX_WIDTH = 96;
const DND_WINDOW_SWITCH_TIMEOUT = 1250; const DND_WINDOW_SWITCH_TIMEOUT = 1250;
const GLSL_DIM_EFFECT_DECLARATIONS = ''; const GLSL_DIM_EFFECT_DECLARATIONS = '';
@@ -30,9 +33,9 @@ const GLSL_DIM_EFFECT_CODE = '\
vec2 dist = cogl_tex_coord_in[0].xy - vec2(0.5, 0.5); \ vec2 dist = cogl_tex_coord_in[0].xy - vec2(0.5, 0.5); \
float elipse_radius = 0.5; \ float elipse_radius = 0.5; \
/* from https://bugzilla.gnome.org/show_bug.cgi?id=669798: \ /* from https://bugzilla.gnome.org/show_bug.cgi?id=669798: \
the alpha on the gradient goes from 250 at its darkest to 180 at its most transparent. */ \ the alpha on the gradient goes from 165 at its darkest to 98 at its most transparent. */ \
float y = 250.0 / 255.0; \ float y = 165.0 / 255.0; \
float x = 180.0 / 255.0; \ float x = 98.0 / 255.0; \
/* interpolate darkening value, based on distance from screen center */ \ /* interpolate darkening value, based on distance from screen center */ \
float val = min(length(dist), elipse_radius); \ float val = min(length(dist), elipse_radius); \
float a = mix(x, y, val / elipse_radius); \ float a = mix(x, y, val / elipse_radius); \
@@ -43,6 +46,18 @@ const GLSL_DIM_EFFECT_CODE = '\
cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \ cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
cogl_color_out.a = 1.0;'; cogl_color_out.a = 1.0;';
const SwipeScrollDirection = {
NONE: 0,
HORIZONTAL: 1,
VERTICAL: 2
};
const SwipeScrollResult = {
CANCEL: 0,
SWIPE: 1,
CLICK: 2
};
const ShellInfo = new Lang.Class({ const ShellInfo = new Lang.Class({
Name: 'ShellInfo', Name: 'ShellInfo',
@@ -102,7 +117,6 @@ const Overview = new Lang.Class({
_init: function() { _init: function() {
this._overviewCreated = false; this._overviewCreated = false;
this._initCalled = false;
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated(); this._sessionUpdated();
@@ -133,16 +147,26 @@ const Overview = new Lang.Class({
this._desktopFade = new St.Bin(); this._desktopFade = new St.Bin();
global.overlay_group.add_actor(this._desktopFade); global.overlay_group.add_actor(this._desktopFade);
this._spacing = 0;
/* Translators: This is the main view to select /* Translators: This is the main view to select
activities. See also note for "Activities" string. */ activities. See also note for "Activities" string. */
this._overview = new St.BoxLayout({ name: 'overview', this._group = new St.Widget({ name: 'overview',
accessible_name: _("Overview"), accessible_name: _("Overview"),
reactive: true, reactive: true });
vertical: true }); this._group._delegate = this;
this._overview._delegate = this; this._group.connect('style-changed',
Lang.bind(this, function() {
this._group = new St.BoxLayout({ name: 'overview-group' }); let node = this._group.get_theme_node();
let spacing = node.get_length('spacing');
if (spacing != this._spacing) {
this._spacing = spacing;
this._relayout();
}
}));
this._scrollDirection = SwipeScrollDirection.NONE;
this._scrollAdjustment = null;
this._capturedEventId = 0; this._capturedEventId = 0;
this._buttonPressId = 0; this._buttonPressId = 0;
@@ -158,11 +182,12 @@ const Overview = new Lang.Class({
// Dash elements, or mouseover handlers in the workspaces. // Dash elements, or mouseover handlers in the workspaces.
this._coverPane = new Clutter.Rectangle({ opacity: 0, this._coverPane = new Clutter.Rectangle({ opacity: 0,
reactive: true }); reactive: true });
this._overview.add_actor(this._coverPane); this._group.add_actor(this._coverPane);
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; })); this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
this._overview.hide();
global.overlay_group.add_actor(this._overview); this._group.hide();
global.overlay_group.add_actor(this._group);
this._coverPane.hide(); this._coverPane.hide();
@@ -174,16 +199,11 @@ const Overview = new Lang.Class({
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin)); Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd)); Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
global.screen.connect('restacked', Lang.bind(this, this._onRestacked));
this._windowSwitchTimeoutId = 0; this._windowSwitchTimeoutId = 0;
this._windowSwitchTimestamp = 0; this._windowSwitchTimestamp = 0;
this._lastActiveWorkspaceIndex = -1; this._lastActiveWorkspaceIndex = -1;
this._lastHoveredWindow = null; this._lastHoveredWindow = null;
this._needsFakePointerEvent = false; this._needsFakePointerEvent = false;
if (this._initCalled)
this.init();
}, },
_sessionUpdated: function() { _sessionUpdated: function() {
@@ -196,20 +216,11 @@ const Overview = new Lang.Class({
// signal handlers and so forth. So we create them after // signal handlers and so forth. So we create them after
// construction in this init() method. // construction in this init() method.
init: function() { init: function() {
this._initCalled = true;
if (this.isDummy) if (this.isDummy)
return; return;
this._shellInfo = new ShellInfo(); this._shellInfo = new ShellInfo();
// Add a clone of the panel to the overview so spacing and such is
// automatic
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel.actor }),
reactive: false,
opacity: 0 });
this._overview.add_actor(this._panelGhost);
this._searchEntry = new St.Entry({ name: 'searchEntry', this._searchEntry = new St.Entry({ name: 'searchEntry',
/* Translators: this is the text displayed /* Translators: this is the text displayed
in the search entry when no search is in the search entry when no search is
@@ -218,13 +229,16 @@ const Overview = new Lang.Class({
hint_text: _("Type to search..."), hint_text: _("Type to search..."),
track_hover: true, track_hover: true,
can_focus: true }); can_focus: true });
this._searchEntryBin = new St.Bin({ child: this._searchEntry, this._group.add_actor(this._searchEntry);
x_align: St.Align.MIDDLE });
this._overview.add_actor(this._searchEntryBin); this._dash = new Dash.Dash();
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
this._dash.showAppsButton);
this._group.add_actor(this._viewSelector.actor);
this._group.add_actor(this._dash.actor);
// TODO - recalculate everything when desktop size changes // TODO - recalculate everything when desktop size changes
this._dash = new Dash.Dash(); this._dash.actor.add_constraint(this._viewSelector.constrainHeight);
this._group.add_actor(this._dash.actor);
this.dashIconSize = this._dash.iconSize; this.dashIconSize = this._dash.iconSize;
this._dash.connect('icon-size-changed', this._dash.connect('icon-size-changed',
Lang.bind(this, function() { Lang.bind(this, function() {
@@ -235,23 +249,6 @@ const Overview = new Lang.Class({
// the left of the overview // the left of the overview
Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks-symbolic'); Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks-symbolic');
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
this._dash.showAppsButton);
this._group.add(this._viewSelector.actor, { x_fill: true,
expand: true });
// Add our same-line elements after the search entry
this._overview.add(this._group, { y_fill: true,
expand: true });
// Then account for message tray
this._messageTrayGhost = new St.Bin({ style_class: 'message-tray-summary',
reactive: false,
opacity: 0,
x_fill: true,
y_fill: true });
this._overview.add_actor(this._messageTrayGhost);
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout)); Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
this._relayout(); this._relayout();
}, },
@@ -344,11 +341,159 @@ const Overview = new Lang.Class({
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
}, },
addAction: function(action) { setScrollAdjustment: function(adjustment, direction) {
if (this.isDummy) if (this.isDummy)
return; return;
this._overview.add_action(action); this._scrollAdjustment = adjustment;
if (this._scrollAdjustment == null)
this._scrollDirection = SwipeScrollDirection.NONE;
else
this._scrollDirection = direction;
},
_onButtonPress: function(actor, event) {
if (this._scrollDirection == SwipeScrollDirection.NONE
|| event.get_button() != 1)
return;
let [stageX, stageY] = event.get_coords();
this._dragStartX = this._dragX = stageX;
this._dragStartY = this._dragY = stageY;
this._dragStartValue = this._scrollAdjustment.value;
this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
this._capturedEventId = global.stage.connect('captured-event',
Lang.bind(this, this._onCapturedEvent));
this.emit('swipe-scroll-begin');
},
_onCapturedEvent: function(actor, event) {
let stageX, stageY;
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
switch(event.type()) {
case Clutter.EventType.BUTTON_RELEASE:
[stageX, stageY] = event.get_coords();
// default to snapping back to the original value
let newValue = this._dragStartValue;
let minValue = this._scrollAdjustment.lower;
let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
let direction;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
direction = stageX > this._dragStartX ? -1 : 1;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
direction *= -1;
} else {
direction = stageY > this._dragStartY ? -1 : 1;
}
// We default to scroll a full page size; both the first
// and the last page may be smaller though, so we need to
// adjust difference in those cases.
let difference = direction * this._scrollAdjustment.page_size;
if (this._dragStartValue + difference > maxValue)
difference = maxValue - this._dragStartValue;
else if (this._dragStartValue + difference < minValue)
difference = minValue - this._dragStartValue;
// If the user has moved more than half the scroll
// difference, we want to "settle" to the new value
// even if the user stops dragging rather "throws" by
// releasing during the drag.
let distance = this._dragStartValue - this._scrollAdjustment.value;
let noStop = Math.abs(distance / difference) > 0.5;
// We detect if the user is stopped by comparing the
// timestamp of the button release with the timestamp of
// the last motion. Experimentally, a difference of 0 or 1
// millisecond indicates that the mouse is in motion, a
// larger difference indicates that the mouse is stopped.
if ((this._lastMotionTime > 0 &&
this._lastMotionTime > event.get_time() - 2) ||
noStop) {
if (this._dragStartValue + difference >= minValue &&
this._dragStartValue + difference <= maxValue)
newValue += difference;
}
let result;
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold) {
// no motion? It's a click!
result = SwipeScrollResult.CLICK;
this.emit('swipe-scroll-end', result);
} else {
if (newValue == this._dragStartValue)
result = SwipeScrollResult.CANCEL;
else
result = SwipeScrollResult.SWIPE;
// The event capture handler is disconnected
// while scrolling to the final position, so
// to avoid undesired prelights we raise
// the cover pane.
this._coverPane.raise_top();
this._coverPane.show();
Tweener.addTween(this._scrollAdjustment,
{ value: newValue,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onCompleteScope: this,
onComplete: function() {
this._coverPane.hide();
this.emit('swipe-scroll-end',
result);
}
});
}
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
return result != SwipeScrollResult.CLICK;
case Clutter.EventType.MOTION:
[stageX, stageY] = event.get_coords();
let dx = this._dragX - stageX;
let dy = this._dragY - stageY;
let primary = Main.layoutManager.primaryMonitor;
this._dragX = stageX;
this._dragY = stageY;
this._lastMotionTime = event.get_time();
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold)
return true;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
else
this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
} else {
this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
}
return true;
// Block enter/leave events to avoid prelights
// during swipe-scroll
case Clutter.EventType.ENTER:
case Clutter.EventType.LEAVE:
return true;
}
return false;
}, },
_getDesktopClone: function() { _getDesktopClone: function() {
@@ -374,27 +519,41 @@ const Overview = new Lang.Class({
this.hide(); this.hide();
let primary = Main.layoutManager.primaryMonitor; let primary = Main.layoutManager.primaryMonitor;
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
let contentY = Main.panel.actor.height; let contentY = Main.panel.actor.height;
let contentHeight = primary.height - contentY - Main.messageTray.actor.height; let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
this._overview.set_position(primary.x, primary.y); this._group.set_position(primary.x, primary.y);
this._overview.set_size(primary.width, primary.height); this._group.set_size(primary.width, primary.height);
this._coverPane.set_position(0, contentY); this._coverPane.set_position(0, contentY);
this._coverPane.set_size(primary.width, contentHeight); this._coverPane.set_size(primary.width, contentHeight);
},
_onRestacked: function() { let searchWidth = this._searchEntry.get_width();
let stack = global.get_window_actors(); let searchHeight = this._searchEntry.get_height();
let stackIndices = {}; let searchX = (primary.width - searchWidth) / 2;
let searchY = contentY + this._spacing;
for (let i = 0; i < stack.length; i++) { let dashWidth = DASH_MAX_WIDTH;
// Use the stable sequence for an integer to use as a hash key let dashY = searchY + searchHeight + this._spacing;
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i; let dashX;
if (rtl) {
this._dash.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
dashX = primary.width;
} else {
dashX = 0;
} }
this.emit('windows-restacked', stackIndices); let viewX = rtl ? 0 : dashWidth + this._spacing;
let viewY = searchY + searchHeight + this._spacing;
let viewWidth = primary.width - dashWidth - this._spacing;
let viewHeight = contentHeight - this._spacing - viewY;
this._searchEntry.set_position(searchX, searchY);
this._dash.actor.set_position(dashX, dashY);
this._viewSelector.actor.set_position(viewX, viewY);
this._viewSelector.actor.set_size(viewWidth, viewHeight);
}, },
//// Public methods //// //// Public methods ////
@@ -431,11 +590,15 @@ const Overview = new Lang.Class({
return; return;
if (this._shown) if (this._shown)
return; return;
this._shown = true; // Do this manually instead of using _syncInputMode, to handle failure
this._syncInputMode(); if (!Main.pushModal(this._group, { keybindingMode: Main.KeybindingMode.OVERVIEW }))
if (!this._modal)
return; return;
this._modal = true;
this._animateVisible(); this._animateVisible();
this._shown = true;
this._buttonPressId = this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
}, },
fadeInDesktop: function() { fadeInDesktop: function() {
@@ -478,12 +641,12 @@ const Overview = new Lang.Class({
// Disable unredirection while in the overview // Disable unredirection while in the overview
Meta.disable_unredirect_for_screen(global.screen); Meta.disable_unredirect_for_screen(global.screen);
global.window_group.hide(); global.window_group.hide();
this._overview.show(); this._group.show();
this._background.show(); this._background.show();
this._viewSelector.show(); this._viewSelector.show();
this._overview.opacity = 0; this._group.opacity = 0;
Tweener.addTween(this._overview, Tweener.addTween(this._group,
{ opacity: 255, { opacity: 255,
transition: 'easeOutQuad', transition: 'easeOutQuad',
time: ANIMATION_TIME, time: ANIMATION_TIME,
@@ -535,6 +698,10 @@ const Overview = new Lang.Class({
this._shown = false; this._shown = false;
this._syncInputMode(); this._syncInputMode();
if (this._buttonPressId > 0)
this._group.disconnect(this._buttonPressId);
this._buttonPressId = 0;
}, },
// hideTemporarily: // hideTemporarily:
@@ -558,7 +725,7 @@ const Overview = new Lang.Class({
if (this.isDummy) if (this.isDummy)
return; return;
if (this.visible) if (this._shown)
this.hide(); this.hide();
else else
this.show(); this.show();
@@ -575,7 +742,7 @@ const Overview = new Lang.Class({
if (this._shown) { if (this._shown) {
if (!this._modal) { if (!this._modal) {
if (Main.pushModal(this._overview, if (Main.pushModal(this._group,
{ keybindingMode: Main.KeybindingMode.OVERVIEW })) { keybindingMode: Main.KeybindingMode.OVERVIEW }))
this._modal = true; this._modal = true;
else else
@@ -583,13 +750,13 @@ const Overview = new Lang.Class({
} }
} else if (this._shownTemporarily) { } else if (this._shownTemporarily) {
if (this._modal) { if (this._modal) {
Main.popModal(this._overview); Main.popModal(this._group);
this._modal = false; this._modal = false;
} }
global.stage_input_mode = Shell.StageInputMode.FULLSCREEN; global.stage_input_mode = Shell.StageInputMode.FULLSCREEN;
} else { } else {
if (this._modal) { if (this._modal) {
Main.popModal(this._overview); Main.popModal(this._group);
this._modal = false; this._modal = false;
} }
else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN)
@@ -607,7 +774,7 @@ const Overview = new Lang.Class({
this._viewSelector.zoomFromOverview(); this._viewSelector.zoomFromOverview();
// Make other elements fade out. // Make other elements fade out.
Tweener.addTween(this._overview, Tweener.addTween(this._group,
{ opacity: 0, { opacity: 0,
transition: 'easeOutQuad', transition: 'easeOutQuad',
time: ANIMATION_TIME, time: ANIMATION_TIME,
@@ -649,7 +816,7 @@ const Overview = new Lang.Class({
this._viewSelector.hide(); this._viewSelector.hide();
this._desktopFade.hide(); this._desktopFade.hide();
this._background.hide(); this._background.hide();
this._overview.hide(); this._group.hide();
this.visible = false; this.visible = false;
this.animationInProgress = false; this.animationInProgress = false;

View File

@@ -599,12 +599,11 @@ const AppMenuButton = new Lang.Class({
menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group); menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
} else { } else {
if (this.menu.isDummyQuitMenu) if (this.menu && !(this.menu instanceof PopupMenu.RemoteMenu))
return; return;
// fallback to older menu // fallback to older menu
menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0); menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
menu.isDummyQuitMenu = true;
menu.addAction(_("Quit"), Lang.bind(this, function() { menu.addAction(_("Quit"), Lang.bind(this, function() {
this._targetApp.request_quit(); this._targetApp.request_quit();
})); }));
@@ -617,12 +616,15 @@ const AppMenuButton = new Lang.Class({
Signals.addSignalMethods(AppMenuButton.prototype); Signals.addSignalMethods(AppMenuButton.prototype);
// Activities button. Because everything else in the top bar is a
// PanelMenu.Button, it simplifies some things to make this be one too.
// We just hack it up to not actually have a menu attached to it.
const ActivitiesButton = new Lang.Class({ const ActivitiesButton = new Lang.Class({
Name: 'ActivitiesButton', Name: 'ActivitiesButton',
Extends: PanelMenu.Button, Extends: PanelMenu.Button,
_init: function() { _init: function() {
this.parent(0.0, null, true); this.parent(0.0);
this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON; this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON;
let container = new Shell.GenericContainer(); let container = new Shell.GenericContainer();
@@ -642,27 +644,27 @@ const ActivitiesButton = new Lang.Class({
this.hotCorner = new Layout.HotCorner(); this.hotCorner = new Layout.HotCorner();
container.add_actor(this.hotCorner.actor); container.add_actor(this.hotCorner.actor);
// Hack up our menu...
this.menu.open = Lang.bind(this, this._onMenuOpenRequest);
this.menu.close = Lang.bind(this, this._onMenuCloseRequest);
this.menu.toggle = Lang.bind(this, this._onMenuToggleRequest);
this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease)); this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease)); this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
Main.overview.connect('showing', Lang.bind(this, function() { Main.overview.connect('showing', Lang.bind(this, function() {
this.actor.add_style_pseudo_class('overview'); this.actor.add_style_pseudo_class('overview');
this._escapeMenuGrab();
this.actor.add_accessible_state (Atk.StateType.CHECKED); this.actor.add_accessible_state (Atk.StateType.CHECKED);
})); }));
Main.overview.connect('hiding', Lang.bind(this, function() { Main.overview.connect('hiding', Lang.bind(this, function() {
this.actor.remove_style_pseudo_class('overview'); this.actor.remove_style_pseudo_class('overview');
this._escapeMenuGrab();
this.actor.remove_accessible_state (Atk.StateType.CHECKED); this.actor.remove_accessible_state (Atk.StateType.CHECKED);
})); }));
this._xdndTimeOut = 0; this._xdndTimeOut = 0;
// Since the hot corner uses stage coordinates, Clutter won't
// queue relayouts for us when the panel moves. Queue a relayout
// when that happens.
Main.layoutManager.connect('panel-box-changed', Lang.bind(this, function() {
container.queue_relayout();
}));
}, },
_containerGetPreferredWidth: function(actor, forHeight, alloc) { _containerGetPreferredWidth: function(actor, forHeight, alloc) {
@@ -708,6 +710,11 @@ const ActivitiesButton = new Lang.Class({
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
}, },
_escapeMenuGrab: function() {
if (this.menu.isOpen)
this.menu.close();
},
_onCapturedEvent: function(actor, event) { _onCapturedEvent: function(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS) { if (event.type() == Clutter.EventType.BUTTON_PRESS) {
if (!this.hotCorner.shouldToggleOverviewOnClick()) if (!this.hotCorner.shouldToggleOverviewOnClick())
@@ -716,13 +723,33 @@ const ActivitiesButton = new Lang.Class({
return false; return false;
}, },
_onMenuOpenRequest: function() {
this.menu.isOpen = true;
this.menu.emit('open-state-changed', true);
},
_onMenuCloseRequest: function() {
this.menu.isOpen = false;
this.menu.emit('open-state-changed', false);
},
_onMenuToggleRequest: function() {
this.menu.isOpen = !this.menu.isOpen;
this.menu.emit('open-state-changed', this.menu.isOpen);
},
_onButtonRelease: function() { _onButtonRelease: function() {
Main.overview.toggle(); if (this.menu.isOpen) {
this.menu.close();
Main.overview.toggle();
}
}, },
_onKeyRelease: function(actor, event) { _onKeyRelease: function(actor, event) {
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) { if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
if (this.menu.isOpen)
this.menu.close();
Main.overview.toggle(); Main.overview.toggle();
} }
}, },

View File

@@ -112,7 +112,7 @@ const Button = new Lang.Class({
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress)); this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
if (dontCreateMenu) if (dontCreateMenu)
this.menu = new PopupMenu.PopupDummyMenu(this.actor); this.menu = null;
else else
this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0)); this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));

View File

@@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
@@ -11,10 +12,8 @@ const St = imports.gi.St;
const Atk = imports.gi.Atk; const Atk = imports.gi.Atk;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Separator = imports.ui.separator;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */ const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
@@ -405,8 +404,29 @@ const PopupSeparatorMenuItem = new Lang.Class({
this.parent({ reactive: false, this.parent({ reactive: false,
can_focus: false}); can_focus: false});
this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' }); this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
this.addActor(this._separator.actor, { span: -1, expand: true }); this.addActor(this._drawingArea, { span: -1, expand: true });
this._drawingArea.connect('repaint', Lang.bind(this, this._onRepaint));
},
_onRepaint: function(area) {
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let margin = themeNode.get_length('-margin-horizontal');
let gradientHeight = themeNode.get_length('-gradient-height');
let startColor = themeNode.get_color('-gradient-start');
let endColor = themeNode.get_color('-gradient-end');
let gradientWidth = (width - margin * 2);
let gradientOffset = (height - gradientHeight) / 2;
let pattern = new Cairo.LinearGradient(margin, gradientOffset, width - margin, gradientOffset + gradientHeight);
pattern.addColorStopRGBA(0, startColor.red / 255, startColor.green / 255, startColor.blue / 255, startColor.alpha / 255);
pattern.addColorStopRGBA(0.5, endColor.red / 255, endColor.green / 255, endColor.blue / 255, endColor.alpha / 255);
pattern.addColorStopRGBA(1, startColor.red / 255, startColor.green / 255, startColor.blue / 255, startColor.alpha / 255);
cr.setSource(pattern);
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
cr.fill();
} }
}); });
@@ -1184,6 +1204,7 @@ const PopupMenu = new Lang.Class({
this.actor = this._boxPointer.actor; this.actor = this._boxPointer.actor;
this.actor._delegate = this; this.actor._delegate = this;
this.actor.style_class = 'popup-menu-boxpointer'; this.actor.style_class = 'popup-menu-boxpointer';
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._boxWrapper = new Shell.GenericContainer(); this._boxWrapper = new Shell.GenericContainer();
this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth)); this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
@@ -1213,6 +1234,15 @@ const PopupMenu = new Lang.Class({
this.box.allocate(box, flags); this.box.allocate(box, flags);
}, },
_onKeyPressEvent: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape) {
this.close(BoxPointer.PopupAnimation.FULL);
return true;
}
return false;
},
setArrowOrigin: function(origin) { setArrowOrigin: function(origin) {
this._boxPointer.setArrowOrigin(origin); this._boxPointer.setArrowOrigin(origin);
}, },
@@ -1253,28 +1283,6 @@ const PopupMenu = new Lang.Class({
} }
}); });
const PopupDummyMenu = new Lang.Class({
Name: 'PopupDummyMenu',
_init: function(sourceActor) {
this.sourceActor = sourceActor;
this.actor = sourceActor;
this.actor._delegate = this;
},
isChildMenu: function() {
return false;
},
open: function() { this.emit('open-state-changed', true); },
close: function() { this.emit('open-state-changed', false); },
toggle: function() {},
destroy: function() {
this.emit('destroy');
},
});
Signals.addSignalMethods(PopupDummyMenu.prototype);
const PopupSubMenu = new Lang.Class({ const PopupSubMenu = new Lang.Class({
Name: 'PopupSubMenu', Name: 'PopupSubMenu',
Extends: PopupMenuBase, Extends: PopupMenuBase,
@@ -1529,6 +1537,7 @@ const PopupComboMenu = new Lang.Class({
this.actor = this.box; this.actor = this.box;
this.actor._delegate = this; this.actor._delegate = this;
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn)); this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
sourceActor.connect('style-changed', sourceActor.connect('style-changed',
Lang.bind(this, this._onSourceActorStyleChanged)); Lang.bind(this, this._onSourceActorStyleChanged));
@@ -1536,6 +1545,15 @@ const PopupComboMenu = new Lang.Class({
global.focus_manager.add_group(this.actor); global.focus_manager.add_group(this.actor);
}, },
_onKeyPressEvent: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape) {
this.close(BoxPointer.PopupAnimation.FULL);
return true;
}
return false;
},
_onKeyFocusIn: function(actor) { _onKeyFocusIn: function(actor) {
let items = this._getMenuItems(); let items = this._getMenuItems();
let activeItem = items[this._activeItemPos]; let activeItem = items[this._activeItemPos];
@@ -2026,8 +2044,17 @@ const PopupMenuManager = new Lang.Class({
_init: function(owner) { _init: function(owner) {
this._owner = owner; this._owner = owner;
this._grabHelper = new GrabHelper.GrabHelper(owner.actor); this.grabbed = false;
this._eventCaptureId = 0;
this._enterEventId = 0;
this._leaveEventId = 0;
this._keyFocusNotifyId = 0;
this._activeMenu = null;
this._menus = []; this._menus = [];
this._menuStack = [];
this._preGrabInputMode = null;
this._grabbedFromKeynav = false;
}, },
addMenu: function(menu, position) { addMenu: function(menu, position) {
@@ -2046,8 +2073,6 @@ const PopupMenuManager = new Lang.Class({
let source = menu.sourceActor; let source = menu.sourceActor;
if (source) { if (source) {
if (!menu.blockSourceEvents)
this._grabHelper.addActor(source);
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); })); menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); })); menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
} }
@@ -2060,7 +2085,7 @@ const PopupMenuManager = new Lang.Class({
removeMenu: function(menu) { removeMenu: function(menu) {
if (menu == this._activeMenu) if (menu == this._activeMenu)
this._closeMenu(menu); this._closeMenu();
let position = this._findMenu(menu); let position = this._findMenu(menu);
if (position == -1) // not a menu we manage if (position == -1) // not a menu we manage
@@ -2077,29 +2102,79 @@ const PopupMenuManager = new Lang.Class({
if (menudata.focusInId) if (menudata.focusInId)
menu.sourceActor.disconnect(menudata.focusInId); menu.sourceActor.disconnect(menudata.focusInId);
if (menu.sourceActor)
this._grabHelper.removeActor(menu.sourceActor);
this._menus.splice(position, 1); this._menus.splice(position, 1);
}, },
get activeMenu() { _grab: function() {
let actor = this._grabHelper.currentGrab.actor; Main.pushModal(this._owner.actor);
if (actor)
return actor._delegate; this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
else // captured-event doesn't see enter/leave events
return null; this._enterEventId = global.stage.connect('enter-event', Lang.bind(this, this._onEventCapture));
this._leaveEventId = global.stage.connect('leave-event', Lang.bind(this, this._onEventCapture));
this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
this.grabbed = true;
}, },
ignoreRelease: function() { _ungrab: function() {
return this._grabHelper.ignoreRelease(); global.stage.disconnect(this._eventCaptureId);
this._eventCaptureId = 0;
global.stage.disconnect(this._enterEventId);
this._enterEventId = 0;
global.stage.disconnect(this._leaveEventId);
this._leaveEventId = 0;
global.stage.disconnect(this._keyFocusNotifyId);
this._keyFocusNotifyId = 0;
this.grabbed = false;
Main.popModal(this._owner.actor);
}, },
_onMenuOpenState: function(menu, open) { _onMenuOpenState: function(menu, open) {
if (open) { if (open) {
this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor, if (this._activeMenu && this._activeMenu.isChildMenu(menu)) {
onUngrab: Lang.bind(this, this._closeMenu, menu) }); this._menuStack.push(this._activeMenu);
menu.actor.grab_key_focus();
}
this._activeMenu = menu;
} else { } else {
this._grabHelper.ungrab({ actor: menu.actor }); if (this._menuStack.length > 0) {
this._activeMenu = this._menuStack.pop();
if (menu.sourceActor)
menu.sourceActor.grab_key_focus();
this._didPop = true;
}
}
// Check what the focus was before calling pushModal/popModal
let focus = global.stage.key_focus;
let hadFocus = focus && this._activeMenuContains(focus);
if (open) {
if (!this.grabbed) {
this._preGrabInputMode = global.stage_input_mode;
this._grabbedFromKeynav = hadFocus;
this._grab();
}
if (hadFocus)
focus.grab_key_focus();
else
menu.actor.grab_key_focus();
} else if (menu == this._activeMenu) {
if (this.grabbed)
this._ungrab();
this._activeMenu = null;
if (this._grabbedFromKeynav) {
if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED)
global.stage_input_mode = Shell.StageInputMode.FOCUSED;
if (hadFocus && menu.sourceActor)
menu.sourceActor.grab_key_focus();
else if (focus)
focus.grab_key_focus();
}
} }
}, },
@@ -2111,38 +2186,87 @@ const PopupMenuManager = new Lang.Class({
this.removeMenu(childMenu); this.removeMenu(childMenu);
}, },
// change the currently-open menu without dropping grab
_changeMenu: function(newMenu) { _changeMenu: function(newMenu) {
let oldMenu = this.activeMenu; if (this._activeMenu) {
if (oldMenu) { // _onOpenMenuState will drop the grab if it sees
// this._activeMenu being closed; so clear _activeMenu
// before closing it to keep that from happening
let oldMenu = this._activeMenu;
this._activeMenu = null;
for (let i = this._menuStack.length - 1; i >= 0; i--)
this._menuStack[i].close(BoxPointer.PopupAnimation.FADE);
oldMenu.close(BoxPointer.PopupAnimation.FADE); oldMenu.close(BoxPointer.PopupAnimation.FADE);
newMenu.open(BoxPointer.PopupAnimation.FADE); newMenu.open(BoxPointer.PopupAnimation.FADE);
} else { } else
newMenu.open(BoxPointer.PopupAnimation.FULL); newMenu.open(BoxPointer.PopupAnimation.FULL);
}
}, },
_onMenuSourceEnter: function(menu) { _onMenuSourceEnter: function(menu) {
if (!this._grabHelper.grabbed) if (!this.grabbed || menu == this._activeMenu)
return false; return false;
if (this._grabHelper.isActorGrabbed(menu.actor)) if (this._activeMenu && this._activeMenu.isChildMenu(menu))
return false; return false;
let isChildMenu = this._grabHelper.grabStack.some(function(grab) { if (this._menuStack.indexOf(menu) != -1)
let existingMenu = grab.actor._delegate; return false;
return existingMenu.isChildMenu(menu);
}); if (this._menuStack.length > 0 && this._menuStack[0].isChildMenu(menu))
if (isChildMenu)
return false; return false;
this._changeMenu(menu); this._changeMenu(menu);
return false; return false;
}, },
_onKeyFocusChanged: function() {
if (!this.grabbed || !this._activeMenu)
return;
let focus = global.stage.key_focus;
if (focus) {
if (this._activeMenuContains(focus))
return;
if (this._menuStack.length > 0)
return;
if (focus._delegate && focus._delegate.menu &&
this._findMenu(focus._delegate.menu) != -1)
return;
}
this._closeMenu();
},
_onMenuDestroy: function(menu) { _onMenuDestroy: function(menu) {
this.removeMenu(menu); this.removeMenu(menu);
}, },
_activeMenuContains: function(actor) {
return this._activeMenu != null
&& (this._activeMenu.actor.contains(actor) ||
(this._activeMenu.sourceActor && this._activeMenu.sourceActor.contains(actor)));
},
_eventIsOnActiveMenu: function(event) {
return this._activeMenuContains(event.get_source());
},
_shouldBlockEvent: function(event) {
let src = event.get_source();
if (this._activeMenu != null && this._activeMenu.actor.contains(src))
return false;
for (let i = 0; i < this._menus.length; i++) {
let menu = this._menus[i].menu;
if (menu.sourceActor && !menu.blockSourceEvents && menu.sourceActor.contains(src)) {
return false;
}
}
return true;
},
_findMenu: function(item) { _findMenu: function(item) {
for (let i = 0; i < this._menus.length; i++) { for (let i = 0; i < this._menus.length; i++) {
let menudata = this._menus[i]; let menudata = this._menus[i];
@@ -2152,11 +2276,41 @@ const PopupMenuManager = new Lang.Class({
return -1; return -1;
}, },
_closeMenu: function(isUser, menu) { _onEventCapture: function(actor, event) {
// If this isn't a user action, we called close() if (!this.grabbed)
// on the BoxPointer ourselves, so we shouldn't return false;
// reanimate.
if (isUser) if (this._owner.menuEventFilter &&
menu.close(BoxPointer.PopupAnimation.FULL); this._owner.menuEventFilter(event))
return true;
if (this._didPop) {
this._didPop = false;
return true;
}
let activeMenuContains = this._eventIsOnActiveMenu(event);
let eventType = event.type();
if (eventType == Clutter.EventType.BUTTON_RELEASE) {
if (activeMenuContains) {
return false;
} else {
this._closeMenu();
return true;
}
} else if (eventType == Clutter.EventType.BUTTON_PRESS && !activeMenuContains) {
this._closeMenu();
return true;
} else if (!this._shouldBlockEvent(event)) {
return false;
}
return true;
},
_closeMenu: function() {
if (this._activeMenu != null)
this._activeMenu.close(BoxPointer.PopupAnimation.FULL);
} }
}); });

View File

@@ -29,96 +29,93 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
</method> </method>
</interface>; </interface>;
const SearchProvider2Iface = <interface name="org.gnome.Shell.SearchProvider2">
<method name="GetInitialResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetSubsearchResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetResultMetas">
<arg type="as" direction="in" />
<arg type="aa{sv}" direction="out" />
</method>
<method name="ActivateResult">
<arg type="s" direction="in" />
<arg type="as" direction="in" />
<arg type="u" direction="in" />
</method>
<method name="LaunchSearch">
<arg type="as" direction="in" />
<arg type="u" direction="in" />
</method>
</interface>;
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface); var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
function loadRemoteSearchProviders(addProviderCallback) { function loadRemoteSearchProviders(addProviderCallback) {
let data = { loadedProviders: [], let loadState = { loadedProviders: [],
objectPaths: {}, objectPaths: {},
addProviderCallback: addProviderCallback }; numLoading: 0,
FileUtils.collectFromDatadirsAsync('search-providers', addProviderCallback: addProviderCallback };
{ loadedCallback: remoteProvidersLoaded,
processFile: loadRemoteSearchProvider,
data: data
});
}
function loadRemoteSearchProvider(file, info, data) { let dataDirs = GLib.get_system_data_dirs();
let keyfile = new GLib.KeyFile(); for (let i = 0; i < dataDirs.length; i++) {
let path = file.get_path(); let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
let dir = Gio.file_new_for_path(path);
try { dir.query_info_async('standard:type', Gio.FileQueryInfoFlags.NONE,
keyfile.load_from_file(path, 0); GLib.PRIORITY_DEFAULT, null,
} catch(e) { function(object, res) {
return; let exists = false;
try {
object.query_info_finish(res);
exists = true;
} catch (e) {
}
if (!exists)
return;
loadState.numLoading++;
loadRemoteSearchProvidersFromDir(dir, loadState);
});
} }
};
if (!keyfile.has_group(KEY_FILE_GROUP)) function loadRemoteSearchProvidersFromDir(dir, loadState) {
return; let dirPath = dir.get_path();
FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
for (let i = 0; i < files.length; i++) {
let keyfile = new GLib.KeyFile();
let path = GLib.build_filenamev([dirPath, files[i].get_name()]);
let remoteProvider; try {
try { keyfile.load_from_file(path, 0);
let group = KEY_FILE_GROUP; } catch(e) {
let busName = keyfile.get_string(group, 'BusName'); continue;
let objectPath = keyfile.get_string(group, 'ObjectPath'); }
if (data.objectPaths[objectPath]) if (!keyfile.has_group(KEY_FILE_GROUP))
return; continue;
let appInfo = null; let remoteProvider;
try { try {
let desktopId = keyfile.get_string(group, 'DesktopId'); let group = KEY_FILE_GROUP;
appInfo = Gio.DesktopAppInfo.new(desktopId); let busName = keyfile.get_string(group, 'BusName');
} catch (e) { let objectPath = keyfile.get_string(group, 'ObjectPath');
log('Ignoring search provider ' + path + ': missing DesktopId');
return; if (loadState.objectPaths[objectPath])
continue;
let appInfo = null;
try {
let desktopId = keyfile.get_string(group, 'DesktopId');
appInfo = Gio.DesktopAppInfo.new(desktopId);
} catch (e) {
log('Ignoring search provider ' + path + ': missing DesktopId');
continue;
}
remoteProvider = new RemoteSearchProvider(appInfo,
busName,
objectPath);
loadState.objectPaths[objectPath] = remoteProvider;
loadState.loadedProviders.push(remoteProvider);
} catch(e) {
log('Failed to add search provider %s: %s'.format(path, e.toString()));
continue;
}
} }
let version = '1'; remoteProvidersDirLoaded(loadState);
try { }));
version = keyfile.get_string(group, 'Version');
} catch (e) {
// ignore error
}
if (version >= 2) };
remoteProvider = new RemoteSearchProvider2(appInfo, busName, objectPath);
else
remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath);
data.objectPaths[objectPath] = remoteProvider; function remoteProvidersDirLoaded(loadState) {
data.loadedProviders.push(remoteProvider); loadState.numLoading--;
} catch(e) { if (loadState.numLoading > 0)
log('Failed to add search provider %s: %s'.format(path, e.toString())); return;
}
}
function remoteProvidersLoaded(loadState) {
let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA }); let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
let sortOrder = searchSettings.get_strv('sort-order'); let sortOrder = searchSettings.get_strv('sort-order');
let numSorted = sortOrder.length; let numSorted = sortOrder.length;
@@ -167,18 +164,13 @@ function remoteProvidersLoaded(loadState) {
const RemoteSearchProvider = new Lang.Class({ const RemoteSearchProvider = new Lang.Class({
Name: 'RemoteSearchProvider', Name: 'RemoteSearchProvider',
Extends: Search.SearchProvider,
_init: function(appInfo, dbusName, dbusPath, proxyType) { _init: function(appInfo, dbusName, dbusPath) {
if (!proxyType) this._proxy = new SearchProviderProxy(Gio.DBus.session,
proxyType = SearchProviderProxy; dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
this.proxy = new proxyType(Gio.DBus.session,
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
this.appInfo = appInfo;
this.id = appInfo.get_id();
this.isRemoteProvider = true;
this.parent(appInfo.get_name().toUpperCase(), appInfo, true);
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
}, },
@@ -198,7 +190,9 @@ const RemoteSearchProvider = new Lang.Class({
width, height, rowStride, size); width, height, rowStride, size);
} }
return null; // Ugh, but we want to fall back to something ...
return new St.Icon({ icon_name: 'text-x-generic',
icon_size: size });
}, },
_getResultsFinished: function(results, error) { _getResultsFinished: function(results, error) {
@@ -211,9 +205,9 @@ const RemoteSearchProvider = new Lang.Class({
this._cancellable.cancel(); this._cancellable.cancel();
this._cancellable.reset(); this._cancellable.reset();
try { try {
this.proxy.GetInitialResultSetRemote(terms, this._proxy.GetInitialResultSetRemote(terms,
Lang.bind(this, this._getResultsFinished), Lang.bind(this, this._getResultsFinished),
this._cancellable); this._cancellable);
} catch(e) { } catch(e) {
log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString())); log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
this.searchSystem.pushResults(this, []); this.searchSystem.pushResults(this, []);
@@ -224,9 +218,9 @@ const RemoteSearchProvider = new Lang.Class({
this._cancellable.cancel(); this._cancellable.cancel();
this._cancellable.reset(); this._cancellable.reset();
try { try {
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms, this._proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
Lang.bind(this, this._getResultsFinished), Lang.bind(this, this._getResultsFinished),
this._cancellable); this._cancellable);
} catch(e) { } catch(e) {
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString())); log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
this.searchSystem.pushResults(this, []); this.searchSystem.pushResults(this, []);
@@ -255,9 +249,9 @@ const RemoteSearchProvider = new Lang.Class({
this._cancellable.cancel(); this._cancellable.cancel();
this._cancellable.reset(); this._cancellable.reset();
try { try {
this.proxy.GetResultMetasRemote(ids, this._proxy.GetResultMetasRemote(ids,
Lang.bind(this, this._getResultMetasFinished, callback), Lang.bind(this, this._getResultMetasFinished, callback),
this._cancellable); this._cancellable);
} catch(e) { } catch(e) {
log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString())); log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
callback([]); callback([]);
@@ -265,32 +259,8 @@ const RemoteSearchProvider = new Lang.Class({
}, },
activateResult: function(id) { activateResult: function(id) {
this.proxy.ActivateResultRemote(id); this._proxy.ActivateResultRemote(id);
},
launchSearch: function(terms) {
// the provider is not compatible with the new version of the interface, launch
// the app itself but warn so we can catch the error in logs
log('Search provider ' + this.appInfo.get_id() + ' does not implement LaunchSearch');
this.appInfo.launch([], global.create_app_launch_context());
} }
}); });
const RemoteSearchProvider2 = new Lang.Class({
Name: 'RemoteSearchProvider2',
Extends: RemoteSearchProvider,
_init: function(appInfo, dbusName, dbusPath) {
this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy);
this.canLaunchSearch = true;
},
activateResult: function(id, terms) {
this.proxy.ActivateResultRemote(id, terms, global.get_current_time());
},
launchSearch: function(terms) {
this.proxy.LaunchSearchRemote(terms, global.get_current_time());
}
});

View File

@@ -308,7 +308,6 @@ const NotificationsBox = new Lang.Class({
obj.item.disconnect(obj.contentUpdatedId); obj.item.disconnect(obj.contentUpdatedId);
obj.source.disconnect(obj.sourceDestroyId); obj.source.disconnect(obj.sourceDestroyId);
obj.source.disconnect(obj.sourceCountChangedId); obj.source.disconnect(obj.sourceCountChangedId);
obj.source.disconnect(obj.sourceTitleChangedId);
}, },
}); });

View File

@@ -1,10 +1,176 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell;
const Util = imports.misc.util;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers'; const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
// Not currently referenced by the search API, but
// this enumeration can be useful for provider
// implementations.
const MatchType = {
NONE: 0,
SUBSTRING: 1,
PREFIX: 2
};
const SearchResultDisplay = new Lang.Class({
Name: 'SearchResultDisplay',
_init: function(provider) {
this.provider = provider;
this.actor = null;
},
/**
* renderResults:
* @results: List of identifier strings
* @terms: List of search term strings
*
* Display the given search matches which resulted
* from the given terms. It's expected that not
* all results will fit in the space for the container
* actor; in this case, show as many as makes sense
* for your result type.
*
* The terms are useful for search match highlighting.
*/
renderResults: function(results, terms) {
throw new Error('Not implemented');
},
/**
* clear:
* Remove all results from this display.
*/
clear: function() {
this.actor.destroy_all_children();
},
/**
* getVisibleResultCount:
*
* Returns: The number of actors visible.
*/
getVisibleResultCount: function() {
throw new Error('Not implemented');
},
});
/**
* SearchProvider:
*
* Subclass this object to add a new result type
* to the search system, then call registerProvider()
* in SearchSystem with an instance.
* Search is asynchronous and uses the
* getInitialResultSet()/getSubsearchResultSet() methods.
*/
const SearchProvider = new Lang.Class({
Name: 'SearchProvider',
_init: function(title, appInfo, isRemoteProvider) {
this.title = title;
this.appInfo = appInfo;
this.searchSystem = null;
this.isRemoteProvider = !!isRemoteProvider;
},
/**
* getInitialResultSet:
* @terms: Array of search terms, treated as logical AND
*
* Called when the user first begins a search (most likely
* therefore a single term of length one or two), or when
* a new term is added.
*
* Should "return" an array of result identifier strings representing
* items which match the given search terms. This
* is expected to be a substring match on the metadata for a given
* item. Ordering of returned results is up to the discretion of the provider,
* but you should follow these heruistics:
*
* * Put items where the term matches multiple criteria (e.g. name and
* description) before single matches
* * Put items which match on a prefix before non-prefix substring matches
*
* We say "return" above, but in order to make the query asynchronous, use
* this.searchSystem.pushResults();. The return value should be ignored.
*
* This function should be fast; do not perform unindexed full-text searches
* or network queries.
*/
getInitialResultSet: function(terms) {
throw new Error('Not implemented');
},
/**
* getSubsearchResultSet:
* @previousResults: Array of item identifiers
* @newTerms: Updated search terms
*
* Called when a search is performed which is a "subsearch" of
* the previous search; i.e. when every search term has exactly
* one corresponding term in the previous search which is a prefix
* of the new term.
*
* This allows search providers to only search through the previous
* result set, rather than possibly performing a full re-query.
*
* Similar to getInitialResultSet, the return value for this will
* be ignored; use this.searchSystem.pushResults();.
*/
getSubsearchResultSet: function(previousResults, newTerms) {
throw new Error('Not implemented');
},
/**
* getResultMetas:
* @ids: Result identifier strings
*
* Call callback with array of objects with 'id', 'name', (both strings) and
* 'createIcon' (function(size) returning a Clutter.Texture) properties
* with the same number of members as @ids
*/
getResultMetas: function(ids, callback) {
throw new Error('Not implemented');
},
/**
* createResultActor:
* @resultMeta: Object with result metadata
* @terms: Array of search terms, should be used for highlighting
*
* Search providers may optionally override this to render a
* particular serch result in a custom fashion. The default
* implementation will show the icon next to the name.
*
* The actor should be an instance of St.Widget, with the style class
* 'search-result-content'.
*/
createResultActor: function(resultMeta, terms) {
return null;
},
/**
* activateResult:
* @id: Result identifier string
*
* Called when the user chooses a given result.
*/
activateResult: function(id) {
throw new Error('Not implemented');
}
});
Signals.addSignalMethods(SearchProvider.prototype);
const SearchSystem = new Lang.Class({ const SearchSystem = new Lang.Class({
Name: 'SearchSystem', Name: 'SearchSystem',
@@ -96,7 +262,7 @@ const SearchSystem = new Lang.Class({
results.push([provider, []]); results.push([provider, []]);
provider.getSubsearchResultSet(previousResults, terms); provider.getSubsearchResultSet(previousResults, terms);
} catch (error) { } catch (error) {
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message); log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
} }
} }
} else { } else {
@@ -106,7 +272,7 @@ const SearchSystem = new Lang.Class({
results.push([provider, []]); results.push([provider, []]);
provider.getInitialResultSet(terms); provider.getInitialResultSet(terms);
} catch (error) { } catch (error) {
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message); log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
} }
} }
} }

View File

@@ -11,11 +11,10 @@ const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const Separator = imports.ui.separator;
const Search = imports.ui.search; const Search = imports.ui.search;
const MAX_LIST_SEARCH_RESULTS_ROWS = 3; const MAX_SEARCH_RESULTS_ROWS = 1;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const SearchResult = new Lang.Class({ const SearchResult = new Lang.Class({
Name: 'SearchResult', Name: 'SearchResult',
@@ -23,104 +22,34 @@ const SearchResult = new Lang.Class({
_init: function(provider, metaInfo, terms) { _init: function(provider, metaInfo, terms) {
this.provider = provider; this.provider = provider;
this.metaInfo = metaInfo; this.metaInfo = metaInfo;
this.terms = terms; this.actor = new St.Button({ style_class: 'search-result',
reactive: true,
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START, x_align: St.Align.START,
y_fill: true }); y_fill: true });
this.actor._delegate = this; this.actor._delegate = this;
this.actor.connect('clicked', Lang.bind(this, this.activate)); this._dragActorSource = null;
},
activate: function() {
this.provider.activateResult(this.metaInfo.id, this.terms);
Main.overview.toggle();
},
setSelected: function(selected) {
if (selected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
}
});
const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
_init: function(provider, metaInfo, terms) {
this.parent(provider, metaInfo, terms);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
if (icon) {
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let title = new St.Label({ style_class: 'list-search-result-title',
text: this.metaInfo['name'] })
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
// TODO: should highlight terms in the description here
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description',
text: '"' + this.metaInfo['description'] + '"' });
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
}
}
});
const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo, terms) {
this.parent(provider, metaInfo, terms);
this.actor.style_class = 'grid-search-result';
let content = provider.createResultActor(metaInfo, terms); let content = provider.createResultActor(metaInfo, terms);
let dragSource = null;
if (content == null) { if (content == null) {
content = new St.Bin(); content = new St.Bin({ style_class: 'search-result-content',
reactive: true,
can_focus: true,
track_hover: true,
accessible_role: Atk.Role.PUSH_BUTTON });
let icon = new IconGrid.BaseIcon(this.metaInfo['name'], let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] }); { createIcon: this.metaInfo['createIcon'] });
content.set_child(icon.actor); content.set_child(icon.actor);
this._dragActorSource = icon.icon;
content.label_actor = icon.label; content.label_actor = icon.label;
dragSource = icon.icon;
} else { } else {
if (content._delegate && content._delegate.getDragActorSource) if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource(); this._dragActorSource = content._delegate.getDragActorSource();
} }
this._content = content;
this.actor.set_child(content); this.actor.set_child(content);
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
let draggable = DND.makeDraggable(this.actor); let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin', draggable.connect('drag-begin',
Lang.bind(this, function() { Lang.bind(this, function() {
@@ -134,18 +63,32 @@ const GridSearchResult = new Lang.Class({
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.endItemDrag(this); Main.overview.endItemDrag(this);
})); }));
},
if (!dragSource) setSelected: function(selected) {
// not exactly right, but alignment problems are hard to notice if (selected)
dragSource = content; this._content.add_style_pseudo_class('selected');
this._dragActorSource = dragSource; else
this._content.remove_style_pseudo_class('selected');
},
activate: function() {
this.provider.activateResult(this.metaInfo.id);
Main.overview.toggle();
},
_onResultClicked: function(actor) {
this.activate();
}, },
getDragActorSource: function() { getDragActorSource: function() {
return this._dragActorSource; if (this._dragActorSource)
return this._dragActorSource;
// not exactly right, but alignment problems are hard to notice
return this._content;
}, },
getDragActor: function() { getDragActor: function(stageX, stageY) {
return this.metaInfo['createIcon'](Main.overview.dashIconSize); return this.metaInfo['createIcon'](Main.overview.dashIconSize);
}, },
@@ -153,93 +96,34 @@ const GridSearchResult = new Lang.Class({
if (this.provider.dragActivateResult) if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id, params); this.provider.dragActivateResult(this.metaInfo.id, params);
else else
this.provider.activateResult(this.metaInfo.id, this.terms); this.provider.activateResult(this.metaInfo.id, params);
} }
}); });
const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
_init: function(provider) {
this.provider = provider;
this.actor = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('clicked', Lang.bind(this,
function() {
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this.actor.add(this.providerIcon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this.actor.add_actor(this._content);
this._notDisplayedResult = [];
this._terms = [];
this._pendingClear = false;
},
getResultsForDisplay: function() {
let alreadyVisible = this._pendingClear ? 0 : this.getVisibleResultCount();
let canDisplay = MAX_LIST_SEARCH_RESULTS_ROWS - alreadyVisible;
let newResults = this._notDisplayedResult.splice(0, canDisplay);
return newResults;
},
getVisibleResultCount: function() {
return this._content.get_n_children();
},
hasMoreResults: function() {
return this._notDisplayedResult.length > 0;
},
setResults: function(results, terms) {
// copy the lists
this._notDisplayedResult = results.slice(0);
this._terms = terms.slice(0);
this._pendingClear = true;
},
renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new ListSearchResult(this.provider, metas[i], this._terms);
this._content.add_actor(display.actor);
}
},
clear: function () {
this._content.destroy_all_children();
this._pendingClear = false;
},
getFirstResult: function() {
if (this.getVisibleResultCount() > 0)
return this._content.get_child_at_index(0)._delegate;
else
return null;
}
});
const GridSearchResults = new Lang.Class({ const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults', Name: 'GridSearchResults',
Extends: Search.SearchResultDisplay,
_init: function(provider) { _init: function(provider, grid) {
this.provider = provider; this.parent(provider);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS, this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START }); xAlign: St.Align.START });
this.actor = new St.Bin({ x_align: St.Align.MIDDLE }); this.actor = new St.Bin({ x_align: St.Align.START });
this.actor.set_child(this._grid.actor); this.actor.set_child(this._grid.actor);
this._width = 0;
this.actor.connect('notify::width', Lang.bind(this, function() {
this._width = this.actor.width;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
let results = this.getResultsForDisplay();
if (results.length == 0)
return;
provider.getResultMetas(results, Lang.bind(this, this.renderResults));
}));
}));
this._notDisplayedResult = []; this._notDisplayedResult = [];
this._terms = []; this._terms = [];
this._pendingClear = false; this._pendingClear = false;
@@ -247,21 +131,18 @@ const GridSearchResults = new Lang.Class({
getResultsForDisplay: function() { getResultsForDisplay: function() {
let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount(); let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount();
let canDisplay = this._grid.childrenInRow(this.actor.width) * this._grid.getRowLimit() let canDisplay = this._grid.childrenInRow(this._width) * this._grid.getRowLimit()
- alreadyVisible; - alreadyVisible;
let newResults = this._notDisplayedResult.splice(0, canDisplay); let numResults = Math.min(this._notDisplayedResult.length, canDisplay);
return newResults;
return this._notDisplayedResult.splice(0, numResults);
}, },
getVisibleResultCount: function() { getVisibleResultCount: function() {
return this._grid.visibleItemsCount(); return this._grid.visibleItemsCount();
}, },
hasMoreResults: function() {
return this._notDisplayedResult.length > 0;
},
setResults: function(results, terms) { setResults: function(results, terms) {
// copy the lists // copy the lists
this._notDisplayedResult = results.slice(0); this._notDisplayedResult = results.slice(0);
@@ -271,7 +152,7 @@ const GridSearchResults = new Lang.Class({
renderResults: function(metas) { renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) { for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i], this._terms); let display = new SearchResult(this.provider, metas[i], this._terms);
this._grid.addItem(display.actor); this._grid.addItem(display.actor);
} }
}, },
@@ -302,20 +183,26 @@ const SearchResults = new Lang.Class({
this._content = new St.BoxLayout({ name: 'searchResultsContent', this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true }); vertical: true });
this._scrollView = new St.ScrollView({ x_fill: true, let scrollView = new St.ScrollView({ x_fill: true,
y_fill: false, y_fill: false,
style_class: 'vfade' }); style_class: 'vfade' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.add_actor(this._content); 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);
this.actor.add(this._scrollView, { x_fill: true, this.actor.add(scrollView, { x_fill: true,
y_fill: true, y_fill: true,
expand: true, expand: true,
x_align: St.Align.START, x_align: St.Align.START,
y_align: St.Align.START }); y_align: St.Align.START });
this.actor.connect('notify::mapped', Lang.bind(this,
function() {
if (!this.actor.mapped)
return;
let adjustment = scrollView.vscroll.adjustment;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(adjustment, direction);
}));
this._statusText = new St.Label({ style_class: 'search-statustext' }); this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE, this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
@@ -332,37 +219,22 @@ const SearchResults = new Lang.Class({
this._defaultResult = null; this._defaultResult = null;
}, },
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
createProviderMeta: function(provider) { createProviderMeta: function(provider) {
let providerBox = new St.BoxLayout({ style_class: 'search-section', let providerBox = new St.BoxLayout({ style_class: 'search-section',
vertical: true }); vertical: true });
let providerIcon = null; let title = new St.Label({ style_class: 'search-section-header',
let resultDisplay = null; text: provider.title });
providerBox.add(title, { x_fill: false, x_align: St.Align.START });
if (provider.appInfo) { let resultDisplayBin = new St.Bin({ style_class: 'search-section-results',
resultDisplay = new ListSearchResults(provider);
providerIcon = resultDisplay.providerIcon;
} else {
resultDisplay = new GridSearchResults(provider);
}
let resultDisplayBin = new St.Bin({ child: resultDisplay.actor,
x_fill: true, x_fill: true,
y_fill: true }); y_fill: true });
providerBox.add(resultDisplayBin, { expand: true }); providerBox.add(resultDisplayBin, { expand: true });
let resultDisplay = new GridSearchResults(provider);
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' }); resultDisplayBin.set_child(resultDisplay.actor);
providerBox.add(separator.actor);
this._providerMeta.push({ provider: provider, this._providerMeta.push({ provider: provider,
actor: providerBox, actor: providerBox,
icon: providerIcon,
resultDisplay: resultDisplay }); resultDisplay: resultDisplay });
this._content.add(providerBox); this._content.add(providerBox);
}, },
@@ -469,11 +341,6 @@ const SearchResults = new Lang.Class({
meta.resultDisplay.setResults(providerResults, terms); meta.resultDisplay.setResults(providerResults, terms);
let results = meta.resultDisplay.getResultsForDisplay(); let results = meta.resultDisplay.getResultsForDisplay();
if (meta.icon)
meta.icon.moreIcon.visible =
meta.resultDisplay.hasMoreResults() &&
provider.canLaunchSearch;
provider.getResultMetas(results, Lang.bind(this, function(metas) { provider.getResultMetas(results, Lang.bind(this, function(metas) {
this._clearDisplayForProvider(provider); this._clearDisplayForProvider(provider);
meta.actor.show(); meta.actor.show();
@@ -519,37 +386,10 @@ const SearchResults = new Lang.Class({
let from = this._defaultResult ? this._defaultResult.actor : null; let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false); this.actor.navigate_focus(from, direction, false);
} if (this._defaultResult) {
}); // The default result appears focused, so navigate directly to the
// next result.
const ProviderIcon = new Lang.Class({ this.actor.navigate_focus(global.stage.key_focus, direction, false);
Name: 'ProviderIcon', }
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
_init: function(provider) {
this.provider = provider;
this.parent({ style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
} }
}); });

View File

@@ -1,34 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Cairo = imports.cairo;
const Lang = imports.lang;
const St = imports.gi.St;
const HorizontalSeparator = new Lang.Class({
Name: 'HorizontalSeparator',
_init: function (params) {
this.actor = new St.DrawingArea(params);
this.actor.connect('repaint', Lang.bind(this, this._onRepaint));
},
_onRepaint: function(area) {
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let margin = themeNode.get_length('-margin-horizontal');
let gradientHeight = themeNode.get_length('-gradient-height');
let startColor = themeNode.get_color('-gradient-start');
let endColor = themeNode.get_color('-gradient-end');
let gradientWidth = (width - margin * 2);
let gradientOffset = (height - gradientHeight) / 2;
let pattern = new Cairo.LinearGradient(margin, gradientOffset, width - margin, gradientOffset + gradientHeight);
pattern.addColorStopRGBA(0, startColor.red / 255, startColor.green / 255, startColor.blue / 255, startColor.alpha / 255);
pattern.addColorStopRGBA(0.5, endColor.red / 255, endColor.green / 255, endColor.blue / 255, endColor.alpha / 255);
pattern.addColorStopRGBA(1, startColor.red / 255, startColor.green / 255, startColor.blue / 255, startColor.alpha / 255);
cr.setSource(pattern);
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
cr.fill();
}
});

View File

@@ -1,12 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
@@ -14,12 +10,10 @@ const DEFAULT_MODE = 'restrictive';
const _modes = { const _modes = {
'restrictive': { 'restrictive': {
parentMode: null,
hasOverview: false, hasOverview: false,
showCalendarEvents: false, showCalendarEvents: false,
allowSettings: false, allowSettings: false,
allowExtensions: false, allowExtensions: false,
enabledExtensions: [],
hasRunDialog: false, hasRunDialog: false,
hasWorkspaces: false, hasWorkspaces: false,
hasWindows: false, hasWindows: false,
@@ -27,6 +21,7 @@ const _modes = {
isLocked: false, isLocked: false,
isGreeter: false, isGreeter: false,
isPrimary: false, isPrimary: false,
buttonLayout: ['button-layout', 'org.gnome.shell.overrides'],
unlockDialog: null, unlockDialog: null,
components: [], components: [],
panel: { panel: {
@@ -107,51 +102,37 @@ const _modes = {
right: ['a11y', 'keyboard', 'volume', 'bluetooth', right: ['a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'userMenu'] 'network', 'battery', 'userMenu']
} }
},
'foo': {
hasOverview: true,
showCalendarEvents: true,
allowSettings: true,
allowExtensions: true,
hasRunDialog: true,
hasWorkspaces: true,
hasWindows: true,
hasNotifications: true,
isLocked: false,
isPrimary: true,
buttonLayout: ['button-layout', 'org.gnome.shell-foo.overrides'],
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
components: ['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'recorder', 'autorunManager', 'automountManager'],
panel: {
left: ['activities', 'appMenu'],
center: ['dateMenu'],
right: ['a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'userMenu']
}
} }
}; };
function _getModes(modesLoadedCallback) {
FileUtils.collectFromDatadirsAsync('modes',
{ processFile: _loadMode,
loadedCallback: modesLoadedCallback,
data: _modes });
}
function _loadMode(file, info, loadedData) {
let name = info.get_name();
let suffix = name.indexOf('.json');
let modeName = suffix == -1 ? name : name.slice(name, suffix);
if (loadedData.hasOwnProperty(modeName))
return;
let fileContent, success, tag, newMode;
try {
[success, fileContent, tag] = file.load_contents(null);
newMode = JSON.parse(fileContent);
} catch(e) {
return;
}
loadedData[modeName] = {};
let propBlacklist = ['unlockDialog'];
for (let prop in loadedData[DEFAULT_MODE]) {
if (newMode[prop] !== undefined &&
propBlacklist.indexOf(prop) == -1)
loadedData[modeName][prop]= newMode[prop];
}
loadedData[modeName]['isPrimary'] = true;
}
function listModes() { function listModes() {
_getModes(function(modes) { let modes = Object.getOwnPropertyNames(_modes);
let names = Object.getOwnPropertyNames(modes); for (let i = 0; i < modes.length; i++)
for (let i = 0; i < names.length; i++) if (_modes[modes[i]].isPrimary)
if (_modes[names[i]].isPrimary) print(modes[i]);
print(names[i]);
Mainloop.quit('listModes');
});
Mainloop.run('listModes');
} }
const SessionMode = new Lang.Class({ const SessionMode = new Lang.Class({
@@ -159,18 +140,10 @@ const SessionMode = new Lang.Class({
_init: function() { _init: function() {
global.connect('notify::session-mode', Lang.bind(this, this._sync)); global.connect('notify::session-mode', Lang.bind(this, this._sync));
this._modes = _modes; let mode = _modes[global.session_mode].isPrimary ? global.session_mode
this._modeStack = [DEFAULT_MODE]; : 'user';
this._modeStack = [mode];
this._sync(); this._sync();
_getModes(Lang.bind(this, function(modes) {
this._modes = modes;
let primary = modes[global.session_mode] &&
modes[global.session_mode].isPrimary;
let mode = primary ? global.session_mode : 'user';
this._modeStack = [mode];
this._sync();
}));
}, },
pushMode: function(mode) { pushMode: function(mode) {
@@ -197,14 +170,8 @@ const SessionMode = new Lang.Class({
}, },
_sync: function() { _sync: function() {
let params = this._modes[this.currentMode]; let params = _modes[this.currentMode];
let defaults; params = Params.parse(params, _modes[DEFAULT_MODE]);
if (params.parentMode)
defaults = Params.parse(this._modes[params.parentMode],
this._modes[DEFAULT_MODE]);
else
defaults = this._modes[DEFAULT_MODE];
params = Params.parse(params, defaults);
// A simplified version of Lang.copyProperties, handles // A simplified version of Lang.copyProperties, handles
// undefined as a special case for "no change / inherit from previous mode" // undefined as a special case for "no change / inherit from previous mode"

View File

@@ -46,7 +46,6 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<arg type="i" direction="in" name="width"/> <arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/> <arg type="i" direction="in" name="height"/>
</method> </method>
<property name="Mode" type="s" access="read" />
<property name="OverviewActive" type="b" access="readwrite" /> <property name="OverviewActive" type="b" access="readwrite" />
<property name="ShellVersion" type="s" access="read" /> <property name="ShellVersion" type="s" access="read" />
</interface>; </interface>;
@@ -187,8 +186,6 @@ const GnomeShell = new Lang.Class({
flashspot.fire(); flashspot.fire();
}, },
Mode: global.session_mode,
get OverviewActive() { get OverviewActive() {
return Main.overview.visible; return Main.overview.visible;
}, },

View File

@@ -19,8 +19,6 @@ const ShellEntry = imports.ui.shellEntry;
const LIST_ITEM_ICON_SIZE = 48; const LIST_ITEM_ICON_SIZE = 48;
const REMEMBER_MOUNT_PASSWORD_KEY = 'remember-mount-password';
/* ------ Common Utils ------- */ /* ------ Common Utils ------- */
function _setLabelText(label, text) { function _setLabelText(label, text) {
if (text) { if (text) {
@@ -389,8 +387,7 @@ const ShellMountPasswordDialog = new Lang.Class({
if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) { if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
this._rememberChoice = new CheckBox.CheckBox(); this._rememberChoice = new CheckBox.CheckBox();
this._rememberChoice.getLabelActor().text = _("Remember Password"); this._rememberChoice.getLabelActor().text = _("Remember Password");
this._rememberChoice.actor.checked = this._rememberChoice.actor.checked = true;
global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY);
this._messageBox.add(this._rememberChoice.actor); this._messageBox.add(this._rememberChoice.actor);
} else { } else {
this._rememberChoice = null; this._rememberChoice = null;
@@ -422,8 +419,6 @@ const ShellMountPasswordDialog = new Lang.Class({
}, },
_onEntryActivate: function() { _onEntryActivate: function() {
global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY,
this._rememberChoice && this._rememberChoice.actor.checked);
this.emit('response', 1, this.emit('response', 1,
this._passwordEntry.get_text(), this._passwordEntry.get_text(),
this._rememberChoice && this._rememberChoice &&

View File

@@ -80,7 +80,7 @@ const Indicator = new Lang.Class({
this._applet.connect('notify::show-full-menu', Lang.bind(this, this._updateFullMenu)); this._applet.connect('notify::show-full-menu', Lang.bind(this, this._updateFullMenu));
this._updateFullMenu(); this._updateFullMenu();
this.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop'); this.menu.addSettingsAction(_("Bluetooth Settings"), 'bluetooth-properties.desktop');
this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest)); this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest));
this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest)); this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest));

View File

@@ -1,11 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop; const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang; const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
@@ -23,7 +21,6 @@ try {
const Main = imports.ui.main; const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const SwitcherPopup = imports.ui.switcherPopup;
const Util = imports.misc.util; const Util = imports.misc.util;
const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources'; const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
@@ -50,7 +47,6 @@ const IBusManager = new Lang.Class({
this._engines = {}; this._engines = {};
this._ready = false; this._ready = false;
this._registerPropertiesId = 0; this._registerPropertiesId = 0;
this._currentEngineName = null;
this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS, this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS,
Gio.BusNameWatcherFlags.NONE, Gio.BusNameWatcherFlags.NONE,
@@ -70,10 +66,6 @@ const IBusManager = new Lang.Class({
this._engines = {}; this._engines = {};
this._ready = false; this._ready = false;
this._registerPropertiesId = 0; this._registerPropertiesId = 0;
this._currentEngineName = null;
if (this._readyCallback)
this._readyCallback(false);
}, },
_onNameAppeared: function() { _onNameAppeared: function() {
@@ -97,10 +89,12 @@ const IBusManager = new Lang.Class({
let name = enginesList[i].get_name(); let name = enginesList[i].get_name();
this._engines[name] = enginesList[i]; this._engines[name] = enginesList[i];
} }
this._updateReadiness();
} else { } else {
this._clear(); this._clear();
return;
} }
this._updateReadiness();
}, },
_initPanelService: function(ibus, result) { _initPanelService: function(ibus, result) {
@@ -111,31 +105,27 @@ const IBusManager = new Lang.Class({
this._candidatePopup.setPanelService(this._panelService); this._candidatePopup.setPanelService(this._panelService);
// Need to set this to get 'global-engine-changed' emitions // Need to set this to get 'global-engine-changed' emitions
this._ibus.set_watch_ibus_signal(true); this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged)); this._ibus.connect('global-engine-changed', Lang.bind(this, this._resetProperties));
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty)); this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
// If an engine is already active we need to get its properties this._resetProperties();
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
let engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
this._engineChanged(this._ibus, engine.get_name());
}));
this._updateReadiness();
} else { } else {
this._clear(); this._clear();
return;
} }
this._updateReadiness();
}, },
_updateReadiness: function() { _updateReadiness: function() {
this._ready = (Object.keys(this._engines).length > 0 && this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null); this._panelService != null);
if (this._readyCallback) if (this._ready && this._readyCallback)
this._readyCallback(this._ready); this._readyCallback();
}, },
_engineChanged: function(bus, engineName) { _resetProperties: function() {
this._currentEngineName = engineName; this.emit('properties-registered', null);
if (this._registerPropertiesId != 0) if (this._registerPropertiesId != 0)
return; return;
@@ -148,18 +138,25 @@ const IBusManager = new Lang.Class({
this._panelService.disconnect(this._registerPropertiesId); this._panelService.disconnect(this._registerPropertiesId);
this._registerPropertiesId = 0; this._registerPropertiesId = 0;
this.emit('properties-registered', this._currentEngineName, props); this.emit('properties-registered', props);
})); }));
}, },
_updateProperty: function(panel, prop) { _updateProperty: function(panel, prop) {
this.emit('property-updated', this._currentEngineName, prop); this.emit('property-updated', prop);
}, },
activateProperty: function(key, state) { activateProperty: function(key, state) {
this._panelService.property_activate(key, state); this._panelService.property_activate(key, state);
}, },
hasProperties: function(id) {
if (id == 'anthy')
return true;
return false;
},
getEngineDesc: function(id) { getEngineDesc: function(id) {
if (!IBus || !this._ready) if (!IBus || !this._ready)
return null; return null;
@@ -184,127 +181,16 @@ const LayoutMenuItem = new Lang.Class({
} }
}); });
const InputSource = new Lang.Class({
Name: 'InputSource',
_init: function(type, id, displayName, shortName, index) {
this.type = type;
this.id = id;
this.displayName = displayName;
this._shortName = shortName;
this.index = index;
this._menuItem = new LayoutMenuItem(this.displayName, this._shortName);
this._menuItem.connect('activate', Lang.bind(this, this.activate));
this._indicatorLabel = new St.Label({ text: this._shortName });
this.properties = null;
},
destroy: function() {
this._menuItem.destroy();
this._indicatorLabel.destroy();
},
get shortName() {
return this._shortName;
},
set shortName(v) {
this._shortName = v;
this._menuItem.indicator.set_text(v);
this._indicatorLabel.set_text(v);
},
get menuItem() {
return this._menuItem;
},
get indicatorLabel() {
return this._indicatorLabel;
},
activate: function() {
this.emit('activate');
},
});
Signals.addSignalMethods(InputSource.prototype);
const InputSourcePopup = new Lang.Class({
Name: 'InputSourcePopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function(items, action, actionBackward) {
this.parent(items);
this._action = action;
this._actionBackward = actionBackward;
},
_createSwitcher: function() {
this._switcherList = new InputSourceSwitcher(this._items);
return true;
},
_initialSelection: function(backward, binding) {
if (binding == 'switch-input-source') {
if (backward)
this._selectedIndex = this._items.length - 1;
} else if (binding == 'switch-input-source-backward') {
if (!backward)
this._selectedIndex = this._items.length - 1;
}
this._select(this._selectedIndex);
},
_keyPressHandler: function(keysym, backwards, action) {
if (action == this._action)
this._select(backwards ? this._previous() : this._next());
else if (action == this._actionBackward)
this._select(backwards ? this._next() : this._previous());
else if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)
this._select(this._next());
},
_finish : function() {
this.parent();
this._items[this._selectedIndex].activate();
},
});
const InputSourceSwitcher = new Lang.Class({
Name: 'InputSourceSwitcher',
Extends: SwitcherPopup.SwitcherList,
_init: function(items) {
this.parent(true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
},
_addIcon: function(item) {
let box = new St.BoxLayout({ vertical: true });
let bin = new St.Bin({ style_class: 'input-source-switcher-symbol' });
let symbol = new St.Label({ text: item.shortName });
bin.set_child(symbol);
box.add(bin, { x_fill: false, y_fill: false } );
let text = new St.Label({ text: item.displayName });
box.add(text, { x_fill: false });
this.addItem(box, text);
}
});
const InputSourceIndicator = new Lang.Class({ const InputSourceIndicator = new Lang.Class({
Name: 'InputSourceIndicator', Name: 'InputSourceIndicator',
Extends: PanelMenu.Button, Extends: PanelMenu.Button,
_propertiesWhitelist: [
'InputMode',
'TypingMode',
'DictMode'
],
_init: function() { _init: function() {
this.parent(0.0, _("Keyboard")); this.parent(0.0, _("Keyboard"));
@@ -315,36 +201,14 @@ const InputSourceIndicator = new Lang.Class({
this.actor.add_actor(this._container); this.actor.add_actor(this._container);
this.actor.add_style_class_name('panel-status-button'); this.actor.add_style_class_name('panel-status-button');
// All valid input sources currently in the gsettings this._labelActors = {};
// KEY_INPUT_SOURCES list indexed by their index there this._layoutItems = {};
this._inputSources = {};
// All valid input sources currently in the gsettings
// KEY_INPUT_SOURCES list of type INPUT_SOURCE_TYPE_IBUS
// indexed by the IBus ID
this._ibusSources = {};
this._currentSource = null;
// All valid input sources currently in the gsettings
// KEY_INPUT_SOURCES list ordered by most recently used
this._mruSources = [];
this._keybindingAction =
Main.wm.addKeybinding('switch-input-source',
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES,
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,
Main.KeybindingMode.ALL,
Lang.bind(this, this._switchInputSource));
this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA }); this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged)); this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged)); this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged));
this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
this._xkbInfo = new GnomeDesktop.XkbInfo(); this._xkbInfo = new GnomeDesktop.XkbInfo();
this._propSeparator = new PopupMenu.PopupSeparatorMenuItem(); this._propSeparator = new PopupMenu.PopupSeparatorMenuItem();
@@ -353,8 +217,9 @@ const InputSourceIndicator = new Lang.Class({
this.menu.addMenuItem(this._propSection); this.menu.addMenuItem(this._propSection);
this._propSection.actor.hide(); this._propSection.actor.hide();
this._ibusReady = false; this._properties = null;
this._ibusManager = new IBusManager(Lang.bind(this, this._ibusReadyCallback));
this._ibusManager = new IBusManager(Lang.bind(this, this._inputSourcesChanged));
this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered)); this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered));
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated)); this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
this._inputSourcesChanged(); this._inputSourcesChanged();
@@ -376,29 +241,18 @@ const InputSourceIndicator = new Lang.Class({
this._showLayoutItem.actor.visible = Main.sessionMode.allowSettings; this._showLayoutItem.actor.visible = Main.sessionMode.allowSettings;
}, },
_ibusReadyCallback: function(ready) {
if (this._ibusReady == ready)
return;
this._ibusReady = ready;
this._mruSources = [];
this._inputSourcesChanged();
},
_switchInputSource: function(display, screen, window, binding) {
let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward);
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!popup.show(backwards, binding.get_name(), binding.get_mask()))
popup.destroy();
},
_currentInputSourceChanged: function() { _currentInputSourceChanged: function() {
let nVisibleSources = Object.keys(this._inputSources).length; let nVisibleSources = Object.keys(this._layoutItems).length;
let newSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE); let newCurrentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
let newSource = this._inputSources[newSourceIndex]; let newLayoutItem = this._layoutItems[newCurrentSourceIndex];
let hasProperties;
if (!newSource || (nVisibleSources < 2 && !newSource.properties)) { if (newLayoutItem)
hasProperties = this._ibusManager.hasProperties(newLayoutItem.ibusEngineId);
else
hasProperties = false;
if (!newLayoutItem || (nVisibleSources < 2 && !hasProperties)) {
// This source index might be invalid if we weren't able // This source index might be invalid if we weren't able
// to build a menu item for it, so we hide ourselves since // to build a menu item for it, so we hide ourselves since
// we can't fix it here. *shrug* // we can't fix it here. *shrug*
@@ -412,121 +266,106 @@ const InputSourceIndicator = new Lang.Class({
this.actor.show(); this.actor.show();
let oldSource; if (this._layoutItems[this._currentSourceIndex]) {
[oldSource, this._currentSource] = [this._currentSource, newSource]; this._layoutItems[this._currentSourceIndex].setShowDot(false);
this._container.set_skip_paint(this._labelActors[this._currentSourceIndex], true);
if (oldSource) {
oldSource.menuItem.setShowDot(false);
this._container.set_skip_paint(oldSource.indicatorLabel, true);
} }
newSource.menuItem.setShowDot(true); newLayoutItem.setShowDot(true);
this._container.set_skip_paint(newSource.indicatorLabel, false);
this._buildPropSection(newSource.properties); let newLabelActor = this._labelActors[newCurrentSourceIndex];
this._container.set_skip_paint(newLabelActor, false);
for (let i = 1; i < this._mruSources.length; ++i) if (hasProperties)
if (this._mruSources[i] == newSource) { newLabelActor.set_text(newLayoutItem.indicator.get_text());
let currentSource = this._mruSources.splice(i, 1);
this._mruSources = currentSource.concat(this._mruSources); this._currentSourceIndex = newCurrentSourceIndex;
break;
}
}, },
_inputSourcesChanged: function() { _inputSourcesChanged: function() {
let sources = this._settings.get_value(KEY_INPUT_SOURCES); let sources = this._settings.get_value(KEY_INPUT_SOURCES);
let nSources = sources.n_children(); let nSources = sources.n_children();
for (let i in this._inputSources) for (let i in this._layoutItems)
this._inputSources[i].destroy(); this._layoutItems[i].destroy();
this._inputSources = {}; for (let i in this._labelActors)
this._ibusSources = {}; this._labelActors[i].destroy();
let inputSourcesByShortName = {}; this._layoutItems = {};
this._labelActors = {};
let infos = [];
let infosByShortName = {};
for (let i = 0; i < nSources; i++) { for (let i = 0; i < nSources; i++) {
let displayName; let info = { exists: false };
let shortName;
let [type, id] = sources.get_child_value(i).deep_unpack(); let [type, id] = sources.get_child_value(i).deep_unpack();
let exists = false;
if (type == INPUT_SOURCE_TYPE_XKB) { if (type == INPUT_SOURCE_TYPE_XKB) {
[exists, displayName, shortName, , ] = [info.exists, info.displayName, info.shortName, , ] =
this._xkbInfo.get_layout_info(id); this._xkbInfo.get_layout_info(id);
} else if (type == INPUT_SOURCE_TYPE_IBUS) { } else if (type == INPUT_SOURCE_TYPE_IBUS) {
let engineDesc = this._ibusManager.getEngineDesc(id); let engineDesc = this._ibusManager.getEngineDesc(id);
if (engineDesc) { if (engineDesc) {
let language = IBus.get_language_name(engineDesc.get_language()); let language = IBus.get_language_name(engineDesc.get_language());
exists = true;
displayName = language + ' (' + engineDesc.get_longname() + ')'; info.exists = true;
shortName = this._makeEngineShortName(engineDesc); info.displayName = language + ' (' + engineDesc.get_longname() + ')';
info.shortName = this._makeEngineShortName(engineDesc);
info.ibusEngineId = id;
} }
} }
if (!exists) if (!info.exists)
continue; continue;
let is = new InputSource(type, id, displayName, shortName, i); info.sourceIndex = i;
is.connect('activate', Lang.bind(this, function() { if (!(info.shortName in infosByShortName))
this._settings.set_value(KEY_CURRENT_INPUT_SOURCE, infosByShortName[info.shortName] = [];
GLib.Variant.new_uint32(is.index)); infosByShortName[info.shortName].push(info);
})); infos.push(info);
if (!(is.shortName in inputSourcesByShortName))
inputSourcesByShortName[is.shortName] = [];
inputSourcesByShortName[is.shortName].push(is);
this._inputSources[is.index] = is;
if (is.type == INPUT_SOURCE_TYPE_IBUS)
this._ibusSources[is.id] = is;
} }
let menuIndex = 0; for (let i = 0; i < infos.length; i++) {
for (let i in this._inputSources) { let info = infos[i];
let is = this._inputSources[i]; if (infosByShortName[info.shortName].length > 1) {
if (inputSourcesByShortName[is.shortName].length > 1) { let sub = infosByShortName[info.shortName].indexOf(info) + 1;
let sub = inputSourcesByShortName[is.shortName].indexOf(is) + 1; info.shortName += String.fromCharCode(0x2080 + sub);
is.shortName += String.fromCharCode(0x2080 + sub);
} }
this.menu.addMenuItem(is.menuItem, menuIndex++); let item = new LayoutMenuItem(info.displayName, info.shortName);
item.ibusEngineId = info.ibusEngineId;
this._layoutItems[info.sourceIndex] = item;
this.menu.addMenuItem(item, i);
item.connect('activate', Lang.bind(this, function() {
this._settings.set_value(KEY_CURRENT_INPUT_SOURCE,
GLib.Variant.new_uint32(info.sourceIndex));
}));
this._container.add_actor(is.indicatorLabel); let shortLabel = new St.Label({ text: info.shortName });
this._container.set_skip_paint(is.indicatorLabel, true); this._labelActors[info.sourceIndex] = shortLabel;
this._container.add_actor(shortLabel);
this._container.set_skip_paint(shortLabel, true);
} }
let sourcesList = [];
for (let i in this._inputSources)
sourcesList.push(this._inputSources[i]);
let mruSources = [];
for (let i = 0; i < this._mruSources.length; i++) {
for (let j = 0; j < sourcesList.length; j++)
if (this._mruSources[i].type == sourcesList[j].type &&
this._mruSources[i].id == sourcesList[j].id) {
mruSources = mruSources.concat(sourcesList.splice(j, 1));
break;
}
}
this._mruSources = mruSources.concat(sourcesList);
this._currentInputSourceChanged(); this._currentInputSourceChanged();
}, },
_showLayout: function() { _showLayout: function() {
Main.overview.hide(); Main.overview.hide();
let source = this._currentSource; let sources = this._settings.get_value(KEY_INPUT_SOURCES);
let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
let [type, id] = sources.get_child_value(current).deep_unpack();
let xkbLayout = ''; let xkbLayout = '';
let xkbVariant = ''; let xkbVariant = '';
if (source.type == INPUT_SOURCE_TYPE_XKB) { if (type == INPUT_SOURCE_TYPE_XKB) {
[, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(source.id); [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
} else if (source.type == INPUT_SOURCE_TYPE_IBUS) { } else if (type == INPUT_SOURCE_TYPE_IBUS) {
let engineDesc = this._ibusManager.getEngineDesc(source.id); let engineDesc = this._ibusManager.getEngineDesc(id);
if (engineDesc) { if (engineDesc) {
xkbLayout = engineDesc.get_layout(); xkbLayout = engineDesc.get_layout();
xkbVariant = ''; xkbVariant = '';
@@ -555,25 +394,26 @@ const InputSourceIndicator = new Lang.Class({
return String.fromCharCode(0x2328); // keyboard glyph return String.fromCharCode(0x2328); // keyboard glyph
}, },
_ibusPropertiesRegistered: function(im, engineName, props) { _propertyWhitelisted: function(prop) {
let source = this._ibusSources[engineName]; for (let i = 0; i < this._propertiesWhitelist.length; ++i) {
if (!source) let key = prop.get_key();
return; if (key.substr(0, this._propertiesWhitelist[i].length) == this._propertiesWhitelist[i])
return true;
source.properties = props; }
return false;
if (source == this._currentSource)
this._currentInputSourceChanged();
}, },
_ibusPropertyUpdated: function(im, engineName, prop) { _ibusPropertiesRegistered: function(im, props) {
let source = this._ibusSources[engineName]; this._properties = props;
if (!source) this._buildPropSection();
},
_ibusPropertyUpdated: function(im, prop) {
if (!this._propertyWhitelisted(prop))
return; return;
if (this._updateSubProperty(source.properties, prop) && if (this._updateSubProperty(this._properties, prop))
source == this._currentSource) this._buildPropSection();
this._currentInputSourceChanged();
}, },
_updateSubProperty: function(props, prop) { _updateSubProperty: function(props, prop) {
@@ -593,12 +433,25 @@ const InputSourceIndicator = new Lang.Class({
return false; return false;
}, },
_buildPropSection: function(properties) { _updateIndicatorLabel: function(text) {
let layoutItem = this._layoutItems[this._currentSourceIndex];
let hasProperties;
if (layoutItem)
hasProperties = this._ibusManager.hasProperties(layoutItem.ibusEngineId);
else
hasProperties = false;
if (hasProperties)
this._labelActors[this._currentSourceIndex].set_text(text);
},
_buildPropSection: function() {
this._propSeparator.actor.hide(); this._propSeparator.actor.hide();
this._propSection.actor.hide(); this._propSection.actor.hide();
this._propSection.removeAll(); this._propSection.removeAll();
this._buildPropSubMenu(this._propSection, properties); this._buildPropSubMenu(this._propSection, this._properties);
if (!this._propSection.isEmpty()) { if (!this._propSection.isEmpty()) {
this._propSection.actor.show(); this._propSection.actor.show();
@@ -615,7 +468,8 @@ const InputSourceIndicator = new Lang.Class({
for (let i = 0; (p = props.get(i)) != null; ++i) { for (let i = 0; (p = props.get(i)) != null; ++i) {
let prop = p; let prop = p;
if (!prop.get_visible()) if (!this._propertyWhitelisted(prop) ||
!prop.get_visible())
continue; continue;
if (prop.get_key() == 'InputMode') { if (prop.get_key() == 'InputMode') {
@@ -626,17 +480,15 @@ const InputSourceIndicator = new Lang.Class({
text = prop.get_label().get_text(); text = prop.get_label().get_text();
if (text && text.length > 0 && text.length < 3) if (text && text.length > 0 && text.length < 3)
this._currentSource.indicatorLabel.set_text(text); this._updateIndicatorLabel(text);
} }
let item; let item;
switch (prop.get_prop_type()) { let type = prop.get_prop_type();
case IBus.PropType.MENU: if (type == IBus.PropType.MENU) {
item = new PopupMenu.PopupSubMenuMenuItem(prop.get_label().get_text()); item = new PopupMenu.PopupSubMenuMenuItem(prop.get_label().get_text());
this._buildPropSubMenu(item.menu, prop.get_sub_props()); this._buildPropSubMenu(item.menu, prop.get_sub_props());
break; } else if (type == IBus.PropType.RADIO) {
case IBus.PropType.RADIO:
item = new PopupMenu.PopupMenuItem(prop.get_label().get_text()); item = new PopupMenu.PopupMenuItem(prop.get_label().get_text());
item.prop = prop; item.prop = prop;
radioGroup.push(item); radioGroup.push(item);
@@ -661,39 +513,7 @@ const InputSourceIndicator = new Lang.Class({
} }
} }
})); }));
break; } else {
case IBus.PropType.TOGGLE:
item = new PopupMenu.PopupSwitchMenuItem(prop.get_label().get_text(), prop.get_state() == IBus.PropState.CHECKED);
item.prop = prop;
item.connect('toggled', Lang.bind(this, function() {
if (item.state) {
item.prop.set_state(IBus.PropState.CHECKED);
this._ibusManager.activateProperty(item.prop.get_key(),
IBus.PropState.CHECKED);
} else {
item.prop.set_state(IBus.PropState.UNCHECKED);
this._ibusManager.activateProperty(item.prop.get_key(),
IBus.PropState.UNCHECKED);
}
}));
break;
case IBus.PropType.NORMAL:
item = new PopupMenu.PopupMenuItem(prop.get_label().get_text());
item.prop = prop;
item.connect('activate', Lang.bind(this, function() {
this._ibusManager.activateProperty(item.prop.get_key(),
IBus.PropState.CHECKED);
}));
break;
case IBus.PropType.SEPARATOR:
item = new PopupMenu.PopupSeparatorMenuItem();
break;
default:
log ('IBus property %s has invalid type %d'.format(prop.get_key(), type));
continue; continue;
} }
@@ -708,9 +528,8 @@ const InputSourceIndicator = new Lang.Class({
// for those we don't actually display. // for those we don't actually display.
let max_min_width = 0, max_natural_width = 0; let max_min_width = 0, max_natural_width = 0;
for (let i in this._inputSources) { for (let i in this._labelActors) {
let is = this._inputSources[i]; let [min_width, natural_width] = this._labelActors[i].get_preferred_width(for_height);
let [min_width, natural_width] = is.indicatorLabel.get_preferred_width(for_height);
max_min_width = Math.max(max_min_width, min_width); max_min_width = Math.max(max_min_width, min_width);
max_natural_width = Math.max(max_natural_width, natural_width); max_natural_width = Math.max(max_natural_width, natural_width);
} }
@@ -722,9 +541,8 @@ const InputSourceIndicator = new Lang.Class({
_containerGetPreferredHeight: function(container, for_width, alloc) { _containerGetPreferredHeight: function(container, for_width, alloc) {
let max_min_height = 0, max_natural_height = 0; let max_min_height = 0, max_natural_height = 0;
for (let i in this._inputSources) { for (let i in this._labelActors) {
let is = this._inputSources[i]; let [min_height, natural_height] = this._labelActors[i].get_preferred_height(for_width);
let [min_height, natural_height] = is.indicatorLabel.get_preferred_height(for_width);
max_min_height = Math.max(max_min_height, min_height); max_min_height = Math.max(max_min_height, min_height);
max_natural_height = Math.max(max_natural_height, natural_height); max_natural_height = Math.max(max_natural_height, natural_height);
} }
@@ -740,9 +558,7 @@ const InputSourceIndicator = new Lang.Class({
box.y2 -= box.y1; box.y2 -= box.y1;
box.y1 = 0; box.y1 = 0;
for (let i in this._inputSources) { for (let i in this._labelActors)
let is = this._inputSources[i]; this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
is.indicatorLabel.allocate_align_fill(box, 0.5, 0, false, false, flags);
}
} }
}); });

View File

@@ -16,7 +16,6 @@ const Indicator = new Lang.Class({
_init: function() { _init: function() {
this.parent(null, _("Volume, network, battery")); this.parent(null, _("Volume, network, battery"));
this._box.style_class = 'lock-screen-status-button-box';
this._volume = Main.panel.statusArea.volume; this._volume = Main.panel.statusArea.volume;
if (this._volume) { if (this._volume) {

View File

@@ -574,11 +574,7 @@ const NMDevice = new Lang.Class({
this.emit('network-lost'); this.emit('network-lost');
} }
/* Emit a notification if activation fails, but don't do it if (newstate == NetworkManager.DeviceState.FAILED) {
if the reason is no secrets, as that indicates the user
cancelled the agent dialog */
if (newstate == NetworkManager.DeviceState.FAILED &&
reason != NetworkManager.DeviceStateReason.NO_SECRETS) {
this.emit('activation-failed', reason); this.emit('activation-failed', reason);
} }
@@ -611,11 +607,12 @@ const NMDevice = new Lang.Class({
} }
}); });
const NMDeviceSimple = new Lang.Class({ const NMDeviceWired = new Lang.Class({
Name: 'NMDeviceSimple', Name: 'NMDeviceWired',
Extends: NMDevice, Extends: NMDevice,
_init: function(client, device, connections) { _init: function(client, device, connections) {
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED; this.category = NMConnectionCategory.WIRED;
this.parent(client, device, connections); this.parent(client, device, connections);
@@ -630,18 +627,6 @@ const NMDeviceSimple = new Lang.Class({
// we can do it here because addConnection and removeConnection // we can do it here because addConnection and removeConnection
// both call _createSection at some point // both call _createSection at some point
this.section.actor.visible = this._connections.length > 1; this.section.actor.visible = this._connections.length > 1;
}
});
const NMDeviceWired = new Lang.Class({
Name: 'NMDeviceWired',
Extends: NMDeviceSimple,
_init: function(client, device, connections) {
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED;
this.parent(client, device, connections);
}, },
_createAutomaticConnection: function() { _createAutomaticConnection: function() {
@@ -1555,8 +1540,7 @@ const NMVPNSection = new Lang.Class({
}, },
_connectionStateChanged: function(vpnConnection, newstate, reason) { _connectionStateChanged: function(vpnConnection, newstate, reason) {
if (newstate == NetworkManager.VPNConnectionState.FAILED && if (newstate == NetworkManager.VPNConnectionState.FAILED) {
reason != NetworkManager.VPNConnectionStateReason.NO_SECRETS) {
// FIXME: if we ever want to show something based on reason, // FIXME: if we ever want to show something based on reason,
// we need to convert from NetworkManager.VPNConnectionStateReason // we need to convert from NetworkManager.VPNConnectionStateReason
// to NetworkManager.DeviceStateReason // to NetworkManager.DeviceStateReason
@@ -1651,7 +1635,6 @@ const NMApplet = new Lang.Class({
this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless; this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem; this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth; this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth;
this._dtypes[NetworkManager.DeviceType.INFINIBAND] = NMDeviceSimple;
// TODO: WiMax support // TODO: WiMax support
// Connection types // Connection types
@@ -1663,7 +1646,6 @@ const NMApplet = new Lang.Class({
this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN; this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN; this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN; this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED;
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN; this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
this._settings = NMClient.RemoteSettings.new(null); this._settings = NMClient.RemoteSettings.new(null);

View File

@@ -2,7 +2,6 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Lang = imports.lang; const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Gvc = imports.gi.Gvc; const Gvc = imports.gi.Gvc;
const St = imports.gi.St; const St = imports.gi.St;
@@ -33,8 +32,6 @@ const VolumeMenu = new Lang.Class({
_init: function(control) { _init: function(control) {
this.parent(); this.parent();
this.hasHeadphones = false;
this._control = control; this._control = control;
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged)); 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-sink-changed', Lang.bind(this, this._readOutput));
@@ -101,47 +98,20 @@ const VolumeMenu = new Lang.Class({
} }
}, },
_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() { _readOutput: function() {
if (this._outputVolumeId) { if (this._outputVolumeId) {
this._output.disconnect(this._outputVolumeId); this._output.disconnect(this._outputVolumeId);
this._output.disconnect(this._outputMutedId); this._output.disconnect(this._outputMutedId);
this._output.disconnect(this._outputPortId);
this._outputVolumeId = 0; this._outputVolumeId = 0;
this._outputMutedId = 0; this._outputMutedId = 0;
this._outputPortId = 0;
} }
this._output = this._control.get_default_sink(); this._output = this._control.get_default_sink();
if (this._output) { if (this._output) {
this._outputMutedId = this._output.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_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._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._mutedChanged(null, null, '_output');
this._volumeChanged(null, null, '_output');
this._portChanged();
} else { } else {
this.hasHeadphones = false;
this._outputSlider.setValue(0); this._outputSlider.setValue(0);
this.emit('icon-changed', 'audio-volume-muted-symbolic'); this.emit('icon-changed', 'audio-volume-muted-symbolic');
} }
@@ -257,12 +227,6 @@ const Indicator = new Lang.Class({
this.setIcon(icon); this.setIcon(icon);
this._syncVisibility(); this._syncVisibility();
})); }));
this._volumeMenu.connect('headphones-changed', Lang.bind(this, function() {
this._syncVisibility();
}));
this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' }));
this._headphoneIcon.visible = false;
this.menu.addMenuItem(this._volumeMenu); this.menu.addMenuItem(this._volumeMenu);
@@ -275,7 +239,6 @@ const Indicator = new Lang.Class({
_syncVisibility: function() { _syncVisibility: function() {
this.actor.visible = this._hasPulseAudio; this.actor.visible = this._hasPulseAudio;
this.mainIcon.visible = this._hasPulseAudio; this.mainIcon.visible = this._hasPulseAudio;
this._headphoneIcon.visible = this._hasPulseAudio && this._volumeMenu.hasHeadphones;
}, },
_onScrollEvent: function(actor, event) { _onScrollEvent: function(actor, event) {

View File

@@ -1,641 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
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 Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const POPUP_DELAY_TIMEOUT = 150; // milliseconds
const POPUP_SCROLL_TIME = 0.10; // seconds
const POPUP_FADE_OUT_TIME = 0.1; // seconds
const DISABLE_HOVER_TIMEOUT = 500; // milliseconds
function mod(a, b) {
return (a + b) % b;
}
function primaryModifier(mask) {
if (mask == 0)
return 0;
let primary = 1;
while (mask > 1) {
mask >>= 1;
primary <<= 1;
}
return primary;
}
const SwitcherPopup = new Lang.Class({
Name: 'SwitcherPopup',
Abstract: true,
_init: function(items) {
this._switcherList = null;
this._items = items || [];
this._selectedIndex = 0;
this.actor = new Shell.GenericContainer({ style_class: 'switcher-popup',
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));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
Main.uiGroup.add_actor(this.actor);
this._haveModal = false;
this._modifierMask = 0;
this._motionTimeoutId = 0;
this._initialDelayTimeoutId = 0;
// Initially disable hover so we ignore the enter-event if
// the switcher appears underneath the current pointer location
this._disableHover();
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let primary = Main.layoutManager.primaryMonitor;
alloc.min_size = primary.width;
alloc.natural_size = primary.width;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let primary = Main.layoutManager.primaryMonitor;
alloc.min_size = primary.height;
alloc.natural_size = primary.height;
},
_allocate: function(actor, box, flags) {
let childBox = new Clutter.ActorBox();
let primary = Main.layoutManager.primaryMonitor;
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
let vPadding = this.actor.get_theme_node().get_vertical_padding();
let hPadding = leftPadding + rightPadding;
// Allocate the switcherList
// We select a size based on an icon size that does not overflow the screen
let [childMinHeight, childNaturalHeight] = this._switcherList.actor.get_preferred_height(primary.width - hPadding);
let [childMinWidth, childNaturalWidth] = this._switcherList.actor.get_preferred_width(childNaturalHeight);
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
childBox.x2 = Math.min(primary.x + primary.width - rightPadding, childBox.x1 + childNaturalWidth);
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._switcherList.actor.allocate(childBox, flags);
},
_createSwitcher: function() {
throw new Error('Not implemented');
},
_initialSelection: function(backward, binding) {
throw new Error('Not implemented');
},
show: function(backward, binding, mask) {
if (!this._createSwitcher())
return false;
if (!Main.pushModal(this.actor)) {
// Probably someone else has a pointer grab, try again with keyboard only
if (!Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED })) {
return false;
}
}
this._haveModal = true;
this._modifierMask = primaryModifier(mask);
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
this.actor.add_actor(this._switcherList.actor);
this._switcherList.connect('item-activated', Lang.bind(this, this._itemActivated));
this._switcherList.connect('item-entered', Lang.bind(this, this._itemEntered));
// Need to force an allocation so we can figure out whether we
// need to scroll when selecting
this.actor.opacity = 0;
this.actor.show();
this.actor.get_allocation_box();
if (this._items.length > 1)
this._selectedIndex = 1;
else
this._selectedIndex = 0;
this._initialSelection(backward, binding);
// There's a race condition; if the user released Alt before
// we got the grab, then we won't be notified. (See
// https://bugzilla.gnome.org/show_bug.cgi?id=596695 for
// details.) So we check now. (Have to do this after updating
// selection.)
let [x, y, mods] = global.get_pointer();
if (!(mods & this._modifierMask)) {
this._finish(global.get_current_time());
return false;
}
// We delay showing the popup so that fast Alt+Tab users aren't
// disturbed by the popup briefly flashing.
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
Lang.bind(this, function () {
this.actor.opacity = 255;
this._initialDelayTimeoutId = 0;
}));
return true;
},
_next: function() {
return mod(this._selectedIndex + 1, this._items.length);
},
_previous: function() {
return mod(this._selectedIndex - 1, this._items.length);
},
_keyPressHandler: function(keysym, backwards, action) {
throw new Error('Not implemented');
},
_keyPressEvent: function(actor, event) {
let keysym = event.get_key_symbol();
let event_state = event.get_state();
let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
let action = global.display.get_keybinding_action(event.get_key_code(), event_state);
this._disableHover();
if (keysym == Clutter.Escape)
this.destroy();
else
this._keyPressHandler(keysym, backwards, action);
return true;
},
_keyReleaseEvent: function(actor, event) {
let [x, y, mods] = global.get_pointer();
let state = mods & this._modifierMask;
if (state == 0)
this._finish(event.get_time());
return true;
},
_clickedOutside: function(actor, event) {
this.destroy();
},
_scrollHandler: function(direction) {
if (direction == Clutter.ScrollDirection.UP)
this._select(this._previous());
else if (direction == Clutter.ScrollDirection.DOWN)
this._select(this._next());
},
_scrollEvent: function(actor, event) {
this._scrollHandler(event.get_scroll_direction());
},
_itemActivatedHandler: function(n) {
this._select(n);
},
_itemActivated: function(switcher, n) {
this._itemActivatedHandler(n);
this._finish(global.get_current_time());
},
_itemEnteredHandler: function(n) {
this._select(n);
},
_itemEntered: function(switcher, n) {
if (!this.mouseActive)
return;
this._itemEnteredHandler(n);
},
_disableHover: function() {
this.mouseActive = false;
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut));
},
_mouseTimedOut: function() {
this._motionTimeoutId = 0;
this.mouseActive = true;
},
_popModal: function() {
if (this._haveModal) {
Main.popModal(this.actor);
this._haveModal = false;
}
},
destroy: function() {
this._popModal();
if (this.actor.visible) {
Tweener.addTween(this.actor,
{ opacity: 0,
time: POPUP_FADE_OUT_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this.actor.destroy();
})
});
} else
this.actor.destroy();
},
_finish: function(timestamp) {
this.destroy();
},
_onDestroy: function() {
this._popModal();
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
if (this._initialDelayTimeoutId != 0)
Mainloop.source_remove(this._initialDelayTimeoutId);
},
_select: function(num) {
this._selectedIndex = num;
this._switcherList.highlight(num);
}
});
const SwitcherList = new Lang.Class({
Name: 'SwitcherList',
_init : function(squareItems) {
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocateTop));
// Here we use a GenericContainer so that we can force all the
// children except the separator to have the same width.
this._list = new Shell.GenericContainer({ style_class: 'switcher-list-item-container' });
this._list.spacing = 0;
this._list.connect('style-changed', Lang.bind(this, function() {
this._list.spacing = this._list.get_theme_node().get_length('spacing');
}));
this._list.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._list.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._list.connect('allocate', Lang.bind(this, this._allocate));
this._scrollView = new St.ScrollView({ style_class: 'hfade',
enable_mouse_scrolling: false });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
let scrollBox = new St.BoxLayout();
scrollBox.add_actor(this._list);
this._scrollView.add_actor(scrollBox);
this.actor.add_actor(this._scrollView);
// Those arrows indicate whether scrolling in one direction is possible
this._leftArrow = new St.DrawingArea({ style_class: 'switcher-arrow',
pseudo_class: 'highlighted' });
this._leftArrow.connect('repaint', Lang.bind(this,
function() { drawArrow(this._leftArrow, St.Side.LEFT); }));
this._rightArrow = new St.DrawingArea({ style_class: 'switcher-arrow',
pseudo_class: 'highlighted' });
this._rightArrow.connect('repaint', Lang.bind(this,
function() { drawArrow(this._rightArrow, St.Side.RIGHT); }));
this.actor.add_actor(this._leftArrow);
this.actor.add_actor(this._rightArrow);
this._items = [];
this._highlighted = -1;
this._separator = null;
this._squareItems = squareItems;
this._minSize = 0;
this._scrollableRight = true;
this._scrollableLeft = false;
},
_allocateTop: function(actor, box, flags) {
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let childBox = new Clutter.ActorBox();
let scrollable = this._minSize > box.x2 - box.x1;
box.y1 -= this.actor.get_theme_node().get_padding(St.Side.TOP);
box.y2 += this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
this._scrollView.allocate(box, flags);
let arrowWidth = Math.floor(leftPadding / 3);
let arrowHeight = arrowWidth * 2;
childBox.x1 = leftPadding / 2;
childBox.y1 = this.actor.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._leftArrow.allocate(childBox, flags);
this._leftArrow.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
arrowWidth = Math.floor(rightPadding / 3);
arrowHeight = arrowWidth * 2;
childBox.x1 = this.actor.width - arrowWidth - rightPadding / 2;
childBox.y1 = this.actor.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._rightArrow.allocate(childBox, flags);
this._rightArrow.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
},
addItem : function(item, label) {
let bbox = new St.Button({ style_class: 'item-box',
reactive: true });
bbox.set_child(item);
this._list.add_actor(bbox);
let n = this._items.length;
bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); }));
bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); }));
bbox.label_actor = label;
this._items.push(bbox);
return bbox;
},
_onItemClicked: function (index) {
this._itemActivated(index);
},
_onItemEnter: function (index) {
this._itemEntered(index);
},
addSeparator: function () {
let box = new St.Bin({ style_class: 'separator' });
this._separator = box;
this._list.add_actor(box);
},
highlight: function(index, justOutline) {
if (this._highlighted != -1) {
this._items[this._highlighted].remove_style_pseudo_class('outlined');
this._items[this._highlighted].remove_style_pseudo_class('selected');
}
this._highlighted = index;
if (this._highlighted != -1) {
if (justOutline)
this._items[this._highlighted].add_style_pseudo_class('outlined');
else
this._items[this._highlighted].add_style_pseudo_class('selected');
}
let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let [absItemX, absItemY] = this._items[index].get_transformed_position();
let [result, posX, posY] = this.actor.transform_stage_point(absItemX, 0);
let [containerWidth, containerHeight] = this.actor.get_transformed_size();
if (posX + this._items[index].get_width() > containerWidth)
this._scrollToRight();
else if (this._items[index].allocation.x1 - value < 0)
this._scrollToLeft();
},
_scrollToLeft : function() {
let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let item = this._items[this._highlighted];
if (item.allocation.x1 < value)
value = Math.min(0, item.allocation.x1);
else if (item.allocation.x2 > value + pageSize)
value = Math.max(upper, item.allocation.x2 - pageSize);
this._scrollableRight = true;
Tweener.addTween(adjustment,
{ value: value,
time: POPUP_SCROLL_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function () {
if (this._highlighted == 0) {
this._scrollableLeft = false;
this.actor.queue_relayout();
}
})
});
},
_scrollToRight : function() {
let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let item = this._items[this._highlighted];
if (item.allocation.x1 < value)
value = Math.max(0, item.allocation.x1);
else if (item.allocation.x2 > value + pageSize)
value = Math.min(upper, item.allocation.x2 - pageSize);
this._scrollableLeft = true;
Tweener.addTween(adjustment,
{ value: value,
time: POPUP_SCROLL_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function () {
if (this._highlighted == this._items.length - 1) {
this._scrollableRight = false;
this.actor.queue_relayout();
}
})
});
},
_itemActivated: function(n) {
this.emit('item-activated', n);
},
_itemEntered: function(n) {
this.emit('item-entered', n);
},
_maxChildWidth: function (forHeight) {
let maxChildMin = 0;
let maxChildNat = 0;
for (let i = 0; i < this._items.length; i++) {
let [childMin, childNat] = this._items[i].get_preferred_width(forHeight);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
if (this._squareItems) {
let [childMin, childNat] = this._items[i].get_preferred_height(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
}
}
return [maxChildMin, maxChildNat];
},
_getPreferredWidth: function (actor, forHeight, alloc) {
let [maxChildMin, maxChildNat] = this._maxChildWidth(forHeight);
let separatorWidth = 0;
if (this._separator) {
let [sepMin, sepNat] = this._separator.get_preferred_width(forHeight);
separatorWidth = sepNat + this._list.spacing;
}
let totalSpacing = this._list.spacing * (this._items.length - 1);
alloc.min_size = this._items.length * maxChildMin + separatorWidth + totalSpacing;
alloc.natural_size = alloc.min_size;
this._minSize = alloc.min_size;
},
_getPreferredHeight: function (actor, forWidth, alloc) {
let maxChildMin = 0;
let maxChildNat = 0;
for (let i = 0; i < this._items.length; i++) {
let [childMin, childNat] = this._items[i].get_preferred_height(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
}
if (this._squareItems) {
let [childMin, childNat] = this._maxChildWidth(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = maxChildMin;
}
alloc.min_size = maxChildMin;
alloc.natural_size = maxChildNat;
},
_allocate: function (actor, box, flags) {
let childHeight = box.y2 - box.y1;
let [maxChildMin, maxChildNat] = this._maxChildWidth(childHeight);
let totalSpacing = this._list.spacing * (this._items.length - 1);
let separatorWidth = 0;
if (this._separator) {
let [sepMin, sepNat] = this._separator.get_preferred_width(childHeight);
separatorWidth = sepNat;
totalSpacing += this._list.spacing;
}
let childWidth = Math.floor(Math.max(0, box.x2 - box.x1 - totalSpacing - separatorWidth) / this._items.length);
let x = 0;
let children = this._list.get_children();
let childBox = new Clutter.ActorBox();
let primary = Main.layoutManager.primaryMonitor;
let parentRightPadding = this.actor.get_parent().get_theme_node().get_padding(St.Side.RIGHT);
for (let i = 0; i < children.length; i++) {
if (this._items.indexOf(children[i]) != -1) {
let [childMin, childNat] = children[i].get_preferred_height(childWidth);
let vSpacing = (childHeight - childNat) / 2;
childBox.x1 = x;
childBox.y1 = vSpacing;
childBox.x2 = x + childWidth;
childBox.y2 = childBox.y1 + childNat;
children[i].allocate(childBox, flags);
x += this._list.spacing + childWidth;
} else if (children[i] == this._separator) {
// We want the separator to be more compact than the rest.
childBox.x1 = x;
childBox.y1 = 0;
childBox.x2 = x + separatorWidth;
childBox.y2 = childHeight;
children[i].allocate(childBox, flags);
x += this._list.spacing + separatorWidth;
} else {
// Something else, eg, AppSwitcher's arrows;
// we don't allocate it.
}
}
}
});
Signals.addSignalMethods(SwitcherList.prototype);
function drawArrow(area, side) {
let themeNode = area.get_theme_node();
let borderColor = themeNode.get_border_color(side);
let bodyColor = themeNode.get_foreground_color();
let [width, height] = area.get_surface_size ();
let cr = area.get_context();
cr.setLineWidth(1.0);
Clutter.cairo_set_source_color(cr, borderColor);
switch (side) {
case St.Side.TOP:
cr.moveTo(0, height);
cr.lineTo(Math.floor(width * 0.5), 0);
cr.lineTo(width, height);
break;
case St.Side.BOTTOM:
cr.moveTo(width, 0);
cr.lineTo(Math.floor(width * 0.5), height);
cr.lineTo(0, 0);
break;
case St.Side.LEFT:
cr.moveTo(width, height);
cr.lineTo(0, Math.floor(height * 0.5));
cr.lineTo(width, 0);
break;
case St.Side.RIGHT:
cr.moveTo(0, 0);
cr.lineTo(width, Math.floor(height * 0.5));
cr.lineTo(0, height);
break;
}
cr.strokePreserve();
Clutter.cairo_set_source_color(cr, bodyColor);
cr.fill();
}

View File

@@ -593,7 +593,6 @@ const UserMenuButton = new Lang.Class({
this.setSensitive(!Main.sessionMode.isLocked); this.setSensitive(!Main.sessionMode.isLocked);
this._updatePresenceIcon(); this._updatePresenceIcon();
this._updateUserName();
}, },
_onDestroy: function() { _onDestroy: function() {

View File

@@ -39,11 +39,17 @@ const ViewSelector = new Lang.Class({
Name: 'ViewSelector', Name: 'ViewSelector',
_init : function(searchEntry, showAppsButton) { _init : function(searchEntry, showAppsButton) {
this.actor = new Shell.Stack({ name: 'viewSelector' }); this.actor = new St.BoxLayout({ name: 'viewSelector',
vertical: true });
this._showAppsButton = showAppsButton; this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled)); this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
this._pageArea = new Shell.Stack();
this.actor.add(this._pageArea, { x_fill: true,
y_fill: true,
expand: true });
this._activePage = null; this._activePage = null;
this.active = false; this.active = false;
@@ -132,6 +138,17 @@ const ViewSelector = new Lang.Class({
} }
})); }));
// Public constraints which may be used to tie actors' height or
// vertical position to the current tab's content; as the content's
// height and position depend on the view selector's style properties
// (e.g. font size, padding, spacing, ...) it would be extremely hard
// and ugly to get these from the outside. While it would be possible
// to use position and height properties directly, outside code would
// need to ensure that the content is properly allocated before
// accessing the properties.
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
coordinate: Clutter.BindCoordinate.HEIGHT });
Main.wm.addKeybinding('toggle-application-view', Main.wm.addKeybinding('toggle-application-view',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
@@ -185,7 +202,7 @@ const ViewSelector = new Lang.Class({
this._a11yFocusPage(page); this._a11yFocusPage(page);
}) })
});; });;
this.actor.add_actor(page); this._pageArea.add_actor(page);
return page; return page;
}, },
@@ -232,11 +249,6 @@ const ViewSelector = new Lang.Class({
}, },
_onStageKeyPress: function(actor, event) { _onStageKeyPress: function(actor, event) {
// Ignore events while anything but the overview has
// pushed a modal (system modals, looking glass, ...)
if (Main.modalCount > 1)
return false;
let modifiers = event.get_state(); let modifiers = event.get_state();
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();

View File

@@ -10,6 +10,7 @@ const IconGrid = imports.ui.iconGrid;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const Panel = imports.ui.panel; const Panel = imports.ui.panel;
const Search = imports.ui.search;
// we could make these gsettings // we could make these gsettings
const FISH_NAME = 'wanda'; const FISH_NAME = 'wanda';
@@ -70,7 +71,8 @@ const WandaIconBin = new Lang.Class({
Name: 'WandaIconBin', Name: 'WandaIconBin',
_init: function(fish, label, params) { _init: function(fish, label, params) {
this.actor = new St.Bin({ reactive: true, this.actor = new St.Bin({ style_class: 'search-result-content',
reactive: true,
track_hover: true }); track_hover: true });
this.icon = new WandaIcon(fish, label, params); this.icon = new WandaIcon(fish, label, params);
@@ -131,9 +133,10 @@ function capitalize(str) {
const WandaSearchProvider = new Lang.Class({ const WandaSearchProvider = new Lang.Class({
Name: 'WandaSearchProvider', Name: 'WandaSearchProvider',
Extends: Search.SearchProvider,
_init: function() { _init: function() {
this.id = 'wanda'; this.parent(_("Your favorite Easter Egg"));
}, },
getResultMetas: function(fish, callback) { getResultMetas: function(fish, callback) {
@@ -159,7 +162,7 @@ const WandaSearchProvider = new Lang.Class({
this.getInitialResultSet(terms); this.getInitialResultSet(terms);
}, },
activateResult: function(fish) { activateResult: function(fish, params) {
if (this._dialog) if (this._dialog)
this._dialog.destroy(); this._dialog.destroy();
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND); this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);

View File

@@ -136,24 +136,18 @@ const WindowManager = new Lang.Class({
Main.KeybindingMode.NORMAL | Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW, Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher)); Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-applications', this.setCustomKeybindingHandler('switch-windows',
Main.KeybindingMode.NORMAL, Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-group', this.setCustomKeybindingHandler('switch-group',
Main.KeybindingMode.NORMAL, Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-applications-backward', this.setCustomKeybindingHandler('switch-windows-backward',
Main.KeybindingMode.NORMAL, Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-group-backward', this.setCustomKeybindingHandler('switch-group-backward',
Main.KeybindingMode.NORMAL, Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-windows',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('switch-windows-backward',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('switch-panels', this.setCustomKeybindingHandler('switch-panels',
Main.KeybindingMode.NORMAL | Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW | Main.KeybindingMode.OVERVIEW |
@@ -161,13 +155,6 @@ const WindowManager = new Lang.Class({
Main.KeybindingMode.UNLOCK_SCREEN | Main.KeybindingMode.UNLOCK_SCREEN |
Main.KeybindingMode.LOGIN_SCREEN, Main.KeybindingMode.LOGIN_SCREEN,
Lang.bind(this, this._startA11ySwitcher)); Lang.bind(this, this._startA11ySwitcher));
this.setCustomKeybindingHandler('switch-panels-backward',
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', this.addKeybinding('open-application-menu',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
@@ -191,10 +178,8 @@ const WindowManager = new Lang.Class({
}, },
addKeybinding: function(name, settings, flags, modes, handler) { addKeybinding: function(name, settings, flags, modes, handler) {
let action = global.display.add_keybinding(name, settings, flags, handler); if (global.display.add_keybinding(name, settings, flags, handler))
if (action != Meta.KeyBindingAction.NONE)
this.allowKeybinding(name, modes); this.allowKeybinding(name, modes);
return action;
}, },
removeKeybinding: function(name) { removeKeybinding: function(name) {
@@ -221,9 +206,7 @@ const WindowManager = new Lang.Class({
_shouldAnimateActor: function(actor) { _shouldAnimateActor: function(actor) {
if (!this._shouldAnimate()) if (!this._shouldAnimate())
return false; return false;
let windowType = actor.meta_window.get_window_type(); return actor.meta_window.get_window_type() == Meta.WindowType.NORMAL;
return windowType == Meta.WindowType.NORMAL ||
windowType == Meta.WindowType.MODAL_DIALOG;
}, },
_removeEffect : function(list, actor) { _removeEffect : function(list, actor) {
@@ -249,17 +232,16 @@ const WindowManager = new Lang.Class({
*/ */
this._minimizing.push(actor); this._minimizing.push(actor);
let monitor = Main.layoutManager.findMonitorForWindow(actor.meta_window); let primary = Main.layoutManager.primaryMonitor;
let xDest = monitor.x; let xDest = primary.x;
let yDest = monitor.y;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
xDest += monitor.width; xDest += primary.width;
Tweener.addTween(actor, Tweener.addTween(actor,
{ scale_x: 0.0, { scale_x: 0.0,
scale_y: 0.0, scale_y: 0.0,
x: xDest, x: xDest,
y: yDest, y: 0,
time: WINDOW_ANIMATION_TIME, time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone, onComplete: this._minimizeWindowDone,
@@ -374,56 +356,57 @@ const WindowManager = new Lang.Class({
actor._windowType = type; actor._windowType = type;
})); }));
if (actor.meta_window.is_attached_dialog()) {
this._checkDimming(actor.get_meta_window().get_transient_for());
if (this._shouldAnimate()) {
actor.set_scale(1.0, 0.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_y: 1,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
return;
}
shellwm.completed_map(actor);
return;
}
if (!this._shouldAnimateActor(actor)) { if (!this._shouldAnimateActor(actor)) {
shellwm.completed_map(actor); shellwm.completed_map(actor);
return; return;
} }
if (actor.meta_window.is_attached_dialog()) { actor.opacity = 0;
/* Scale the window from the center of the parent */ actor.show();
this._checkDimming(actor.get_meta_window().get_transient_for());
actor.set_scale(1.0, 0.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor, /* Fade window in */
{ scale_y: 1, this._mapping.push(actor);
time: WINDOW_ANIMATION_TIME, Tweener.addTween(actor,
transition: "easeOutQuad", { opacity: 255,
onComplete: this._mapWindowDone, time: WINDOW_ANIMATION_TIME,
onCompleteScope: this, transition: 'easeOutQuad',
onCompleteParams: [shellwm, actor], onComplete: this._mapWindowDone,
onOverwrite: this._mapWindowOverwrite, onCompleteScope: this,
onOverwriteScope: this, onCompleteParams: [shellwm, actor],
onOverwriteParams: [shellwm, actor] onOverwrite: this._mapWindowOverwrite,
}); onOverwriteScope: this,
} else { onOverwriteParams: [shellwm, actor]
/* Fade window in */ });
actor.opacity = 0;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ opacity: 255,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
}
}, },
_mapWindowDone : function(shellwm, actor) { _mapWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) { if (this._removeEffect(this._mapping, actor)) {
Tweener.removeTweens(actor); Tweener.removeTweens(actor);
actor.opacity = 255; actor.opacity = 255;
actor.scale_y = 1;
shellwm.completed_map(actor); shellwm.completed_map(actor);
} }
}, },
@@ -445,21 +428,18 @@ const WindowManager = new Lang.Class({
return win != window; return win != window;
}); });
} }
if (!this._shouldAnimateActor(actor)) {
shellwm.completed_destroy(actor);
return;
}
this._destroying.push(actor);
if (window.is_attached_dialog()) { if (window.is_attached_dialog()) {
let parent = window.get_transient_for(); let parent = window.get_transient_for();
this._checkDimming(parent, window); this._checkDimming(parent, window);
if (!this._shouldAnimate()) {
shellwm.completed_destroy(actor);
return;
}
actor.set_scale(1.0, 1.0); actor.set_scale(1.0, 1.0);
actor.scale_gravity = Clutter.Gravity.CENTER; actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show(); actor.show();
this._destroying.push(actor);
actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () { actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
Tweener.removeTweens(actor); Tweener.removeTweens(actor);
@@ -630,20 +610,7 @@ const WindowManager = new Lang.Class({
if (this._workspaceSwitcherPopup != null) if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy(); this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.AppSwitcherPopup(); let tabPopup = new AltTab.AltTabPopup();
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
_startWindowSwitcher : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.WindowSwitcherPopup();
let modifiers = binding.get_modifiers(); let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
@@ -654,7 +621,7 @@ const WindowManager = new Lang.Class({
_startA11ySwitcher : function(display, screen, window, binding) { _startA11ySwitcher : function(display, screen, window, binding) {
let modifiers = binding.get_modifiers(); let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask()); Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
}, },
_openAppMenu : function(display, screen, window, event, binding) { _openAppMenu : function(display, screen, window, event, binding) {

View File

@@ -30,9 +30,6 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100; 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 // 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, // 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, // when weighted with the values as below, are worse than the previous layout's,
@@ -124,8 +121,6 @@ const WindowClone = new Lang.Class({
this.actor._delegate = this; this.actor._delegate = this;
this._slot = [0, 0, 0, 0];
this._dragSlot = [0, 0, 0, 0];
this._stackAbove = null; this._stackAbove = null;
this._sizeChangedId = this.realWindow.connect('size-changed', this._sizeChangedId = this.realWindow.connect('size-changed',
@@ -161,15 +156,22 @@ const WindowClone = new Lang.Class({
this._selected = false; this._selected = false;
}, },
set slot(slot) {
this._slot = slot;
},
get slot() { get slot() {
if (this.inDrag) let x, y, w, h;
return this._dragSlot;
else if (this.inDrag) {
return this._slot; x = this.dragOrigX;
y = this.dragOrigY;
w = this.actor.width * this.dragOrigScale;
h = this.actor.height * this.dragOrigScale;
} else {
x = this.actor.x;
y = this.actor.y;
w = this.actor.width * this.actor.scale_x;
h = this.actor.height * this.actor.scale_y;
}
return [x, y, w, h];
}, },
setStackAbove: function (actor) { setStackAbove: function (actor) {
@@ -387,7 +389,6 @@ const WindowClone = new Lang.Class({
if (this._zooming) if (this._zooming)
this._zoomEnd(); this._zoomEnd();
this._dragSlot = this._slot;
[this.dragOrigX, this.dragOrigY] = this.actor.get_position(); [this.dragOrigX, this.dragOrigY] = this.actor.get_position();
this.dragOrigScale = this.actor.scale_x; this.dragOrigScale = this.actor.scale_x;
this.inDrag = true; this.inDrag = true;
@@ -441,8 +442,6 @@ const WindowOverlay = new Lang.Class({
this._parentActor = parentActor; this._parentActor = parentActor;
this._hidden = false; this._hidden = false;
this._settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
this.borderSize = 0; this.borderSize = 0;
this.border = new St.Bin({ style_class: 'window-clone-border' }); this.border = new St.Bin({ style_class: 'window-clone-border' });
@@ -454,7 +453,11 @@ const WindowOverlay = new Lang.Class({
this._updateCaptionId = metaWindow.connect('notify::title', this._updateCaptionId = metaWindow.connect('notify::title',
Lang.bind(this, function(w) { Lang.bind(this, function(w) {
this.title.text = w.title; this.title.text = w.title;
this.relayout(false); // we need this for the next call to get_preferred_width
// to return useful results
this.title.set_size(-1, -1);
this._repositionSelf();
})); }));
let button = new St.Button({ style_class: 'window-close' }); let button = new St.Button({ style_class: 'window-close' });
@@ -529,13 +532,27 @@ const WindowOverlay = new Lang.Class({
return [this.borderSize, this.borderSize]; return [this.borderSize, this.borderSize];
}, },
relayout: function(animate) { _repositionSelf: function() {
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot; let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
this.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight, false);
},
/**
* @cloneX: x position of windowClone
* @cloneY: y position of windowClone
* @cloneWidth: width of windowClone
* @cloneHeight height of windowClone
*/
// These parameters are not the values retrieved with
// get_transformed_position() and get_transformed_size(),
// as windowClone might be moving.
// See Workspace._showWindowOverlay
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, animate) {
let button = this.closeButton; let button = this.closeButton;
let title = this.title; let title = this.title;
let layout = this._settings.get_string(BUTTON_LAYOUT_KEY); let settings = new Gio.Settings({ schema: Main.sessionMode.buttonLayout[1] });
let layout = settings.get_string(Main.sessionMode.buttonLayout[0]);
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
let split = layout.split(":"); let split = layout.split(":");
@@ -557,16 +574,8 @@ const WindowOverlay = new Lang.Class({
else else
button.set_position(Math.floor(buttonX), Math.floor(buttonY)); button.set_position(Math.floor(buttonX), Math.floor(buttonY));
// Clutter.Actor.get_preferred_width() will return the fixed width if one
// is set, so we need to reset the width by calling set_width(-1), to forward
// the call down to StLabel.
// We also need to save and restore the current width, otherwise the animation
// starts from the wrong point.
let prevTitleWidth = title.width;
title.set_width(-1);
let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1); let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1);
let titleWidth = Math.max(titleMinWidth, Math.min(titleNatWidth, cloneWidth)); let titleWidth = Math.max(titleMinWidth, Math.min(titleNatWidth, cloneWidth));
title.width = prevTitleWidth;
let titleX = cloneX + (cloneWidth - titleWidth) / 2; let titleX = cloneX + (cloneWidth - titleWidth) / 2;
let titleY = cloneY + cloneHeight + title._spacing; let titleY = cloneY + cloneHeight + title._spacing;
@@ -1172,8 +1181,8 @@ const Workspace = new Lang.Class({
let slot = slots[i]; let slot = slots[i];
let clone = clones[i]; let clone = clones[i];
let metaWindow = clone.metaWindow; let metaWindow = clone.metaWindow;
let overlay = clone.overlay; let mainIndex = this._lookupIndex(metaWindow);
clone.slotId = i; let overlay = this._windowOverlays[mainIndex];
// Positioning a window currently being dragged must be avoided; // Positioning a window currently being dragged must be avoided;
// we'll just leave a blank spot in the layout for it. // we'll just leave a blank spot in the layout for it.
@@ -1181,7 +1190,6 @@ const Workspace = new Lang.Class({
continue; continue;
let [x, y, scale] = slot; let [x, y, scale] = slot;
clone.slot = [x, y, clone.actor.width * scale, clone.actor.height * scale];
if (overlay && initialPositioning) if (overlay && initialPositioning)
overlay.hide(); overlay.hide();
@@ -1213,7 +1221,7 @@ const Workspace = new Lang.Class({
Tweener.removeTweens(clone.actor); Tweener.removeTweens(clone.actor);
clone.actor.set_position(x, y); clone.actor.set_position(x, y);
clone.actor.set_scale(scale, scale); clone.actor.set_scale(scale, scale);
clone.overlay.relayout(false); this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
} }
} }
@@ -1248,7 +1256,15 @@ const Workspace = new Lang.Class({
}) })
}); });
clone.overlay.relayout(true); this._updateWindowOverlayPositions(clone, overlay, x, y, scale, true);
},
_updateWindowOverlayPositions: function(clone, overlay, x, y, scale, animate) {
if (!overlay)
return;
let [cloneWidth, cloneHeight] = clone.actor.get_size();
overlay.updatePositions(x, y, cloneWidth * scale, cloneHeight * scale, animate);
}, },
_showWindowOverlay: function(clone, overlay, fade) { _showWindowOverlay: function(clone, overlay, fade) {
@@ -1383,10 +1399,9 @@ const Workspace = new Lang.Class({
let scale = win._overviewHint.scale; let scale = win._overviewHint.scale;
delete win._overviewHint; delete win._overviewHint;
clone.slot = [x, y, clone.actor.width * scale, clone.actor.height * scale];
clone.actor.set_position (x, y); clone.actor.set_position (x, y);
clone.actor.set_scale (scale, scale); clone.actor.set_scale (scale, scale);
clone.overlay.relayout(false); this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
} else { } else {
// Position new windows at the top corner of the workspace rather // Position new windows at the top corner of the workspace rather
// than where they were placed for real to avoid the window // than where they were placed for real to avoid the window
@@ -1551,7 +1566,6 @@ const Workspace = new Lang.Class({
_addWindowClone : function(win) { _addWindowClone : function(win) {
let clone = new WindowClone(win, this); let clone = new WindowClone(win, this);
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup); let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
clone.overlay = overlay;
clone.connect('selected', clone.connect('selected',
Lang.bind(this, this._onCloneSelected)); Lang.bind(this, this._onCloneSelected));

View File

@@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
@@ -28,8 +27,6 @@ const WORKSPACE_CUT_SIZE = 10;
const WORKSPACE_KEEP_ALIVE_TIME = 100; const WORKSPACE_KEEP_ALIVE_TIME = 100;
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
const WindowClone = new Lang.Class({ const WindowClone = new Lang.Class({
Name: 'WindowClone', Name: 'WindowClone',
@@ -544,12 +541,6 @@ const ThumbnailsBox = new Lang.Class({
this.actor.connect('button-press-event', function() { return true; }); this.actor.connect('button-press-event', function() { return true; });
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease)); this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
Main.overview.connect('showing',
Lang.bind(this, this._createThumbnails));
Main.overview.connect('hidden',
Lang.bind(this, this._destroyThumbnails));
Main.overview.connect('item-drag-begin', Main.overview.connect('item-drag-begin',
Lang.bind(this, this._onDragBegin)); Lang.bind(this, this._onDragBegin));
@@ -563,16 +554,6 @@ const ThumbnailsBox = new Lang.Class({
Lang.bind(this, this._onDragEnd)); Lang.bind(this, this._onDragEnd));
Main.overview.connect('window-drag-cancelled', Main.overview.connect('window-drag-cancelled',
Lang.bind(this, this._onDragCancelled)); Lang.bind(this, this._onDragCancelled));
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._settings.connect('changed::dynamic-workspaces',
Lang.bind(this, this._updateSwitcherVisibility));
},
_updateSwitcherVisibility: function() {
this.actor.visible =
this._settings.get_boolean('dynamic-workspaces') ||
global.screen.n_workspaces > 1;
}, },
_onButtonRelease: function(actor, event) { _onButtonRelease: function(actor, event) {
@@ -738,16 +719,10 @@ const ThumbnailsBox = new Lang.Class({
} }
}, },
_createThumbnails: function() { show: function() {
this._switchWorkspaceNotifyId = this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace', global.window_manager.connect('switch-workspace',
Lang.bind(this, this._activeWorkspaceChanged)); Lang.bind(this, this._activeWorkspaceChanged));
this._nWorkspacesNotifyId =
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
this._syncStackingId =
Main.overview.connect('windows-restacked',
Lang.bind(this, this._syncStacking));
this._targetScale = 0; this._targetScale = 0;
this._scale = 0; this._scale = 0;
@@ -769,54 +744,19 @@ const ThumbnailsBox = new Lang.Class({
}; };
this.addThumbnails(0, global.screen.n_workspaces); this.addThumbnails(0, global.screen.n_workspaces);
this._updateSwitcherVisibility();
}, },
_destroyThumbnails: function() { hide: function() {
if (this._switchWorkspaceNotifyId > 0) { if (this._switchWorkspaceNotifyId > 0) {
global.window_manager.disconnect(this._switchWorkspaceNotifyId); global.window_manager.disconnect(this._switchWorkspaceNotifyId);
this._switchWorkspaceNotifyId = 0; this._switchWorkspaceNotifyId = 0;
} }
if (this._nWorkspacesNotifyId > 0) {
global.screen.disconnect(this._nWorkspacesNotifyId);
this._nWorkspacesNotifyId = 0;
}
if (this._syncStackingId > 0) {
Main.overview.disconnect(this._syncStackingId);
this._syncStackingId = 0;
}
for (let w = 0; w < this._thumbnails.length; w++) for (let w = 0; w < this._thumbnails.length; w++)
this._thumbnails[w].destroy(); this._thumbnails[w].destroy();
this._thumbnails = []; this._thumbnails = [];
}, },
_workspacesChanged: function() {
let oldNumWorkspaces = this._thumbnails.length;
let newNumWorkspaces = global.screen.n_workspaces;
let active = global.screen.get_active_workspace_index();
if (newNumWorkspaces > oldNumWorkspaces) {
this.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
} else {
let removedIndex;
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
if (this._thumbnails[w].metaWorkspace != metaWorkspace) {
removedIndex = w;
break;
}
}
this.removeThumbnails(removedIndex, removedNum);
}
this._updateSwitcherVisibility();
},
addThumbnails: function(start, count) { addThumbnails: function(start, count) {
for (let k = start; k < start + count; k++) { for (let k = start; k < start + count; k++) {
let metaWorkspace = global.screen.get_workspace_by_index(k); let metaWorkspace = global.screen.get_workspace_by_index(k);
@@ -862,7 +802,7 @@ const ThumbnailsBox = new Lang.Class({
this._queueUpdateStates(); this._queueUpdateStates();
}, },
_syncStacking: function(overview, stackIndices) { syncStacking: function(stackIndices) {
for (let i = 0; i < this._thumbnails.length; i++) for (let i = 0; i < this._thumbnails.length; i++)
this._thumbnails[i].syncStacking(stackIndices); this._thumbnails[i].syncStacking(stackIndices);
}, },
@@ -1217,16 +1157,5 @@ const ThumbnailsBox = new Lang.Class({
}, },
onCompleteScope: this onCompleteScope: this
}); });
},
_onScrollEvent: function (actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
break;
case Clutter.ScrollDirection.DOWN:
Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
break;
}
} }
}); });

View File

@@ -2,7 +2,6 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
@@ -69,7 +68,7 @@ const WorkspacesView = new Lang.Class({
// Add workspace actors // Add workspace actors
for (let w = 0; w < global.screen.n_workspaces; w++) for (let w = 0; w < global.screen.n_workspaces; w++)
this.actor.add_actor(this._workspaces[w].actor); this._workspaces[w].actor.reparent(this.actor);
this._workspaces[activeWorkspaceIndex].actor.raise_top(); this._workspaces[activeWorkspaceIndex].actor.raise_top();
this._extraWorkspaces = []; this._extraWorkspaces = [];
@@ -129,10 +128,11 @@ const WorkspacesView = new Lang.Class({
continue; continue;
let ws = new Workspace.Workspace(null, i); let ws = new Workspace.Workspace(null, i);
ws.setGeometry(monitors[i].x, let overviewSpacing = Main.overview._spacing;
monitors[i].y, ws.setGeometry(monitors[i].x + overviewSpacing/2,
monitors[i].width, monitors[i].y + overviewSpacing/2,
monitors[i].height); monitors[i].width - overviewSpacing,
monitors[i].height - overviewSpacing);
global.overlay_group.add_actor(ws.actor); global.overlay_group.add_actor(ws.actor);
this._extraWorkspaces.push(ws); this._extraWorkspaces.push(ws);
} }
@@ -208,11 +208,11 @@ const WorkspacesView = new Lang.Class({
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE); this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
}, },
_scrollToActive: function() { _scrollToActive: function(showAnimation) {
let active = global.screen.get_active_workspace_index(); let active = global.screen.get_active_workspace_index();
this._updateWorkspaceActors(true); this._updateWorkspaceActors(showAnimation);
this._updateScrollAdjustment(active); this._updateScrollAdjustment(active, showAnimation);
}, },
// Update workspace actors parameters // Update workspace actors parameters
@@ -270,21 +270,26 @@ const WorkspacesView = new Lang.Class({
} }
}, },
_updateScrollAdjustment: function(index) { _updateScrollAdjustment: function(index, showAnimation) {
if (this._scrolling) if (this._scrolling)
return; return;
this._animatingScroll = true; this._animatingScroll = true;
Tweener.addTween(this.scrollAdjustment, { if (showAnimation) {
value: index, Tweener.addTween(this.scrollAdjustment, {
time: WORKSPACE_SWITCH_TIME, value: index,
transition: 'easeOutQuad', time: WORKSPACE_SWITCH_TIME,
onComplete: Lang.bind(this, transition: 'easeOutQuad',
function() { onComplete: Lang.bind(this,
this._animatingScroll = false; function() {
}) this._animatingScroll = false;
}); })
});
} else {
this.scrollAdjustment.value = index;
this._animatingScroll = false;
}
}, },
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) { updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
@@ -311,7 +316,7 @@ const WorkspacesView = new Lang.Class({
if (this._scrolling) if (this._scrolling)
return; return;
this._scrollToActive(); this._scrollToActive(true);
}, },
_onDestroy: function() { _onDestroy: function() {
@@ -385,11 +390,24 @@ const WorkspacesView = new Lang.Class({
this._scrolling = true; this._scrolling = true;
}, },
endSwipeScroll: function() { endSwipeScroll: function(result) {
this._scrolling = false; this._scrolling = false;
if (result == Overview.SwipeScrollResult.CLICK) {
let [x, y, mod] = global.get_pointer();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
x, y);
// Only switch to the workspace when there's no application
// windows open. The problem is that it's too easy to miss
// an app window and get the wrong one focused.
let active = global.screen.get_active_workspace_index();
if (this._workspaces[active].isEmpty() &&
this.actor.contains(actor))
Main.overview.hide();
}
// Make sure title captions etc are shown as necessary // Make sure title captions etc are shown as necessary
this._scrollToActive();
this._updateVisibility(); this._updateVisibility();
}, },
@@ -437,51 +455,14 @@ const WorkspacesDisplay = new Lang.Class({
Name: 'WorkspacesDisplay', Name: 'WorkspacesDisplay',
_init: function() { _init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'workspaces-display' }); this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight)); this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate)); this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
this.actor.connect('parent-set', Lang.bind(this, this._parentSet)); this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
this.actor.set_clip_to_allocation(true); this.actor.set_clip_to_allocation(true);
this._spacing = 0;
this.actor.connect('style-changed', Lang.bind(this,
function() {
let node = this.actor.get_theme_node();
let spacing = node.get_length('spacing');
if (spacing != this._spacing) {
this._spacing = spacing;
this._updateWorkspacesGeometry();
}
}));
let clickAction = new Clutter.ClickAction()
clickAction.connect('clicked', Lang.bind(this, function(action) {
// Only switch to the workspace when there's no application
// windows open. The problem is that it's too easy to miss
// an app window and get the wrong one focused.
if (action.get_button() == 1 &&
this._getPrimaryView().getActiveWorkspace().isEmpty())
Main.overview.hide();
}));
Main.overview.addAction(clickAction);
this.actor.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
let panAction = new Clutter.PanAction();
panAction.connect('pan', Lang.bind(this, this._onPan));
panAction.connect('gesture-begin', Lang.bind(this, function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
return true;
}));
panAction.connect('gesture-end', Lang.bind(this, function() {
clickAction.release();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll();
}));
Main.overview.addAction(panAction);
this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
let controls = new St.Bin({ style_class: 'workspace-controls', let controls = new St.Bin({ style_class: 'workspace-controls',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT, request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
y_align: St.Align.START, y_align: St.Align.START,
@@ -493,14 +474,15 @@ const WorkspacesDisplay = new Lang.Class({
controls.track_hover = true; controls.track_hover = true;
controls.connect('notify::hover', controls.connect('notify::hover',
Lang.bind(this, this._onControlsHoverChanged)); Lang.bind(this, this._onControlsHoverChanged));
controls.connect('scroll-event',
Lang.bind(this, this._onScrollEvent));
this._primaryIndex = Main.layoutManager.primaryIndex; this._primaryIndex = Main.layoutManager.primaryIndex;
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox(); this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
controls.add_actor(this._thumbnailsBox.actor); controls.add_actor(this._thumbnailsBox.actor);
this._workspacesViews = []; this._workspacesViews = null;
this._workspaces = [];
this._primaryScrollAdjustment = null; this._primaryScrollAdjustment = null;
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA }); this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
@@ -546,13 +528,16 @@ const WorkspacesDisplay = new Lang.Class({
this._notifyOpacityId = 0; this._notifyOpacityId = 0;
this._swipeScrollBeginId = 0; this._swipeScrollBeginId = 0;
this._swipeScrollEndId = 0; this._swipeScrollEndId = 0;
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._settings.connect('changed::dynamic-workspaces',
Lang.bind(this, this._updateSwitcherVisibility));
}, },
_onPan: function(action) { _updateSwitcherVisibility: function() {
let [dist, dx, dy] = action.get_motion_delta(0); this._thumbnailsBox.actor.visible =
let adjustment = this._scrollAdjustment; this._settings.get_boolean('dynamic-workspaces') ||
adjustment.value -= (dy / this.actor.height) * adjustment.page_size; global.screen.n_workspaces > 1;
return false;
}, },
show: function() { show: function() {
@@ -574,11 +559,13 @@ const WorkspacesDisplay = new Lang.Class({
this._updateZoom(); this._updateZoom();
this._controls.show(); this._controls.show();
this._thumbnailsBox.show();
this._updateSwitcherVisibility();
this._updateWorkspacesViews(); this._updateWorkspacesViews();
this._restackedNotifyId = this._restackedNotifyId =
Main.overview.connect('windows-restacked', global.screen.connect('restacked',
Lang.bind(this, this._onRestacked)); Lang.bind(this, this._onRestacked));
if (this._itemDragBeginId == 0) if (this._itemDragBeginId == 0)
@@ -599,6 +586,8 @@ const WorkspacesDisplay = new Lang.Class({
if (this._windowDragEndId == 0) if (this._windowDragEndId == 0)
this._windowDragEndId = Main.overview.connect('window-drag-end', this._windowDragEndId = Main.overview.connect('window-drag-end',
Lang.bind(this, this._dragEnd)); Lang.bind(this, this._dragEnd));
this._onRestacked();
}, },
zoomFromOverview: function() { zoomFromOverview: function() {
@@ -609,12 +598,13 @@ const WorkspacesDisplay = new Lang.Class({
hide: function() { hide: function() {
this._controls.hide(); this._controls.hide();
this._thumbnailsBox.hide();
if (!this._alwaysZoomOut) if (!this._alwaysZoomOut)
this.zoomFraction = 0; this.zoomFraction = 0;
if (this._restackedNotifyId > 0){ if (this._restackedNotifyId > 0){
Main.overview.disconnect(this._restackedNotifyId); global.screen.disconnect(this._restackedNotifyId);
this._restackedNotifyId = 0; this._restackedNotifyId = 0;
} }
if (this._itemDragBeginId > 0) { if (this._itemDragBeginId > 0) {
@@ -644,7 +634,7 @@ const WorkspacesDisplay = new Lang.Class({
for (let i = 0; i < this._workspacesViews.length; i++) for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy(); this._workspacesViews[i].destroy();
this._workspacesViews = []; this._workspacesViews = null;
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
for (let w = 0; w < this._workspaces[i].length; w++) { for (let w = 0; w < this._workspaces[i].length; w++) {
@@ -653,6 +643,33 @@ const WorkspacesDisplay = new Lang.Class({
} }
}, },
_setupSwipeScrolling: function() {
if (this._swipeScrollBeginId)
Main.overview.disconnect(this._swipeScrollBeginId);
this._swipeScrollBeginId = 0;
if (this._swipeScrollEndId)
Main.overview.disconnect(this._swipeScrollEndId);
this._swipeScrollEndId = 0;
if (!this.actor.mapped)
return;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(this._scrollAdjustment,
direction);
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
Lang.bind(this, function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
}));
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
Lang.bind(this, function(overview, result) {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll(result);
}));
},
_workspacesOnlyOnPrimaryChanged: function() { _workspacesOnlyOnPrimaryChanged: function() {
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary'); this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
@@ -663,12 +680,14 @@ const WorkspacesDisplay = new Lang.Class({
}, },
_updateWorkspacesViews: function() { _updateWorkspacesViews: function() {
for (let i = 0; i < this._workspacesViews.length; i++) if (this._workspacesViews)
this._workspacesViews[i].destroy(); for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy();
for (let i = 0; i < this._workspaces.length; i++) if (this._workspaces)
for (let w = 0; w < this._workspaces[i].length; w++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i][w].destroy(); for (let w = 0; w < this._workspaces[i].length; w++)
this._workspaces[i][w].destroy();
this._workspacesViews = []; this._workspacesViews = [];
this._workspaces = []; this._workspaces = [];
@@ -690,6 +709,7 @@ const WorkspacesDisplay = new Lang.Class({
this._scrollAdjustment = view.scrollAdjustment; this._scrollAdjustment = view.scrollAdjustment;
this._scrollAdjustment.connect('notify::value', this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._scrollValueChanged)); Lang.bind(this, this._scrollValueChanged));
this._setupSwipeScrolling();
} }
this._workspacesViews.push(view); this._workspacesViews.push(view);
} }
@@ -716,7 +736,7 @@ const WorkspacesDisplay = new Lang.Class({
}, },
_getPrimaryView: function() { _getPrimaryView: function() {
if (!this._workspacesViews.length) if (!this._workspacesViews)
return null; return null;
if (this._workspacesOnlyOnPrimary) if (this._workspacesOnlyOnPrimary)
return this._workspacesViews[0]; return this._workspacesViews[0];
@@ -825,7 +845,7 @@ const WorkspacesDisplay = new Lang.Class({
}, },
_updateWorkspacesGeometry: function() { _updateWorkspacesGeometry: function() {
if (!this._workspacesViews.length) if (!this._workspacesViews)
return; return;
let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1; let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
@@ -846,8 +866,9 @@ const WorkspacesDisplay = new Lang.Class({
let clipX = rtl ? x + controlsVisible : x; let clipX = rtl ? x + controlsVisible : x;
let clipY = y + (fullHeight - clipHeight) / 2; let clipY = y + (fullHeight - clipHeight) / 2;
let overviewSpacing = Main.overview._spacing;
let widthAdjust = this._zoomOut ? controlsNatural : controlsVisible; let widthAdjust = this._zoomOut ? controlsNatural : controlsVisible;
widthAdjust += this._spacing; widthAdjust += overviewSpacing;
width -= widthAdjust; width -= widthAdjust;
if (rtl) if (rtl)
x += widthAdjust; x += widthAdjust;
@@ -865,25 +886,35 @@ const WorkspacesDisplay = new Lang.Class({
monitors[i].y, monitors[i].y,
monitors[i].width, monitors[i].width,
monitors[i].height); monitors[i].height);
this._workspacesViews[m].setGeometry(monitors[i].x, this._workspacesViews[m].setGeometry(monitors[i].x + overviewSpacing/2,
monitors[i].y, monitors[i].y + overviewSpacing/2,
monitors[i].width, monitors[i].width - overviewSpacing,
monitors[i].height); monitors[i].height - overviewSpacing);
m++; m++;
} }
} }
}, },
_onRestacked: function(overview, stackIndices) { _onRestacked: function() {
let stack = global.get_window_actors();
let stackIndices = {};
for (let i = 0; i < stack.length; i++) {
// Use the stable sequence for an integer to use as a hash key
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
}
for (let i = 0; i < this._workspacesViews.length; i++) for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].syncStacking(stackIndices); this._workspacesViews[i].syncStacking(stackIndices);
this._thumbnailsBox.syncStacking(stackIndices);
}, },
_workspacesChanged: function() { _workspacesChanged: function() {
this._updateAlwaysZoom(); this._updateAlwaysZoom();
this._updateZoom(); this._updateZoom();
if (!this._workspacesViews.length) if (this._workspacesViews == null)
return; return;
let oldNumWorkspaces = this._workspaces[0].length; let oldNumWorkspaces = this._workspaces[0].length;
@@ -907,6 +938,8 @@ const WorkspacesDisplay = new Lang.Class({
} }
m++; m++;
} }
this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
} else { } else {
// Assume workspaces are only removed sequentially // Assume workspaces are only removed sequentially
// (e.g. 2,3,4 - not 2,4,7) // (e.g. 2,3,4 - not 2,4,7)
@@ -929,11 +962,14 @@ const WorkspacesDisplay = new Lang.Class({
lostWorkspaces[l].destroy(); lostWorkspaces[l].destroy();
} }
} }
this._thumbnailsBox.removeThumbnails(removedIndex, removedNum);
} }
for (let i = 0; i < this._workspacesViews.length; i++) for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces, this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces,
newNumWorkspaces); newNumWorkspaces);
this._updateSwitcherVisibility();
}, },
_updateZoom : function() { _updateZoom : function() {
@@ -945,7 +981,7 @@ const WorkspacesDisplay = new Lang.Class({
this._zoomOut = shouldZoom; this._zoomOut = shouldZoom;
this._updateWorkspacesGeometry(); this._updateWorkspacesGeometry();
if (!this._workspacesViews.length) if (!this._workspacesViews)
return; return;
Tweener.addTween(this, Tweener.addTween(this,
@@ -996,6 +1032,17 @@ const WorkspacesDisplay = new Lang.Class({
// might as well avoid it. // might as well avoid it.
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
Lang.bind(this, this._updateZoom)); Lang.bind(this, this._updateZoom));
},
_onScrollEvent: function (actor, event) {
switch ( event.get_scroll_direction() ) {
case Clutter.ScrollDirection.UP:
Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
break;
case Clutter.ScrollDirection.DOWN:
Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
break;
}
} }
}); });
Signals.addSignalMethods(WorkspacesDisplay.prototype); Signals.addSignalMethods(WorkspacesDisplay.prototype);

View File

@@ -17,7 +17,6 @@ js/ui/components/networkAgent.js
js/ui/components/polkitAgent.js js/ui/components/polkitAgent.js
js/ui/components/recorder.js js/ui/components/recorder.js
js/ui/components/telepathyClient.js js/ui/components/telepathyClient.js
js/ui/ctrlAltTab.js
js/ui/dash.js js/ui/dash.js
js/ui/dateMenu.js js/ui/dateMenu.js
js/ui/endSessionDialog.js js/ui/endSessionDialog.js

790
po/ar.po

File diff suppressed because it is too large Load Diff

371
po/as.po
View File

@@ -9,10 +9,10 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-12-09 13:03+0000\n" "POT-Creation-Date: 2012-11-26 14:01+0000\n"
"PO-Revision-Date: 2012-12-10 18:23+0530\n" "PO-Revision-Date: 2012-11-27 14:40+0530\n"
"Last-Translator: Nilamdyuti Goswami <ngoswami@redhat.com>\n" "Last-Translator: Nilamdyuti Goswami <ngoswami@redhat.com>\n"
"Language-Team: Assamese <kde-i18n-doc@kde.org>\n" "Language-Team: as_IN <kde-i18n-doc@kde.org>\n"
"Language: as_IN\n" "Language: as_IN\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -173,89 +173,68 @@ msgid "Whether the users full name is shown in the user menu or not."
msgstr "ব্যৱহাৰকাৰী মেনুত ব্যৱহাৰকাৰীসকলৰ সম্পূৰ্ণ নাম দেখুৱা হয় নে নহয়।" msgstr "ব্যৱহাৰকাৰী মেনুত ব্যৱহাৰকাৰীসকলৰ সম্পূৰ্ণ নাম দেখুৱা হয় নে নহয়।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17 #: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid ""
"Whether to remember password for mounting encrypted or remote filesystems"
msgstr ""
"ইনক্ৰিপ্টেড অথবা দূৰৱৰ্তী ফাইলচিস্টেমসমূহ মাউন্ট কৰাৰ বাবে পাছৱাৰ্ড মনত ৰখা "
"হব নে"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid ""
"The shell will request a password when an encrypted device or a remote "
"filesystem is mounted. If the password can be saved for future use a "
"'Remember Password' checkbox will be present. This key sets the default "
"state of the checkbox."
msgstr ""
"শ্বেলে এটা পাছৱাৰ্ড অনুৰোধ কৰিব যেতিয়া এটা ইনক্ৰিপ্টেড ডিভাইচ অথবা এটা "
"দূৰৱৰ্তী "
"ফাইলচিস্টেম মাউন্ট কৰা হয়। যদি পাছৱাৰ্ডক ভৱিষ্যত ব্যৱহাৰৰ বাবে সংৰক্ষণ কৰিব "
"পাৰি "
"তেন্তে এটা 'পাছৱাৰ্ড মনত ৰাখক' চেকবাকচ উপস্থিত থাকিব। এই কি'য়ে চেকবাকচৰ "
"অবিকল্পিত অৱস্থা সংহতি কৰে।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
msgstr "কেলেন্ডাৰত সপ্তাহৰ তাৰিখ দেখুৱাওক" msgstr "কেলেন্ডাৰত সপ্তাহৰ তাৰিখ দেখুৱাওক"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20 #: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid "If true, display the ISO week date in the calendar." msgid "If true, display the ISO week date in the calendar."
msgstr "যদি সত্য, ISO সপ্তাহ তাৰিখক কেলেণ্ডাৰত দেখুৱাওক।" msgstr "যদি সত্য, ISO সপ্তাহ তাৰিখক কেলেণ্ডাৰত দেখুৱাওক।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21 #: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Keybinding to open the application menu" msgid "Keybinding to open the application menu"
msgstr "এপ্লিকেচন মেনু খোলিবলে Keybinding" msgstr "এপ্লিকেচন মেনু খোলিবলে Keybinding"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22 #: ../data/org.gnome.shell.gschema.xml.in.in.h:20
msgid "Keybinding to open the application menu." msgid "Keybinding to open the application menu."
msgstr "এপ্লিকেচন মেনু খোলিবলে Keybinding।" msgstr "এপ্লিকেচন মেনু খোলিবলে Keybinding।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23 #: ../data/org.gnome.shell.gschema.xml.in.in.h:21
msgid "Keybinding to open the \"Show Applications\" view" msgid "Keybinding to open the \"Show Applications\" view"
msgstr "\"এপ্লিকেচনসমূহ দেখুৱাওক\" দৰ্শন খোলিবলে কি'বাইণ্ডিং" msgstr "\"এপ্লিকেচনসমূহ দেখুৱাওক\" দৰ্শন খোলিবলে কি'বাইণ্ডিং"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24 #: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "" msgid ""
"Keybinding to open the \"Show Applications\" view of the Activities Overview." "Keybinding to open the \"Show Applications\" view of the Activities Overview."
msgstr "" msgstr ""
"কাৰ্য্যসমূহ অভাৰভিউৰ \"এপ্লিকেচনসমূহ দেখুৱাওক\" দৰ্শন খোলিবলে কি'বাইণ্ডিং।" "কাৰ্য্যসমূহ অভাৰভিউৰ \"এপ্লিকেচনসমূহ দেখুৱাওক\" দৰ্শন খোলিবলে কি'বাইণ্ডিং।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25 #: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "Keybinding to toggle the visibility of the message tray" msgid "Keybinding to toggle the visibility of the message tray"
msgstr "বাৰ্তা ট্ৰেৰ দৃশ্যমানতা টগ'ল কৰিবলে Keybinding" msgstr "বাৰ্তা ট্ৰেৰ দৃশ্যমানতা টগ'ল কৰিবলে Keybinding"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26 #: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "Keybinding to toggle the visibility of the message tray." msgid "Keybinding to toggle the visibility of the message tray."
msgstr "বাৰ্তা ট্ৰেৰ দৃশ্যমানতা টগ'ল কৰিবলে Keybinding।" msgstr "বাৰ্তা ট্ৰেৰ দৃশ্যমানতা টগ'ল কৰিবলে Keybinding।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27 #: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "Keybinding to focus the active notification" msgid "Keybinding to focus the active notification"
msgstr "সক্ৰিয় অধিসূচনা ফকাচ কৰিবলে কি'বাইণ্ডিং" msgstr "সক্ৰিয় অধিসূচনা ফকাচ কৰিবলে কি'বাইণ্ডিং"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28 #: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid "Keybinding to focus the active notification." msgid "Keybinding to focus the active notification."
msgstr "সক্ৰিয় অধিসূচনা ফকাচ কৰিবলে কি'বাইণ্ডিং।" msgstr "সক্ৰিয় অধিসূচনা ফকাচ কৰিবলে কি'বাইণ্ডিং।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29 #: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "Keybinding to toggle the screen recorder" msgid "Keybinding to toggle the screen recorder"
msgstr "পৰ্দা ৰেকৰ্ডাৰ অদল বদল কৰিবলে Keybinding" msgstr "পৰ্দা ৰেকৰ্ডাৰ অদল বদল কৰিবলে Keybinding"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30 #: ../data/org.gnome.shell.gschema.xml.in.in.h:28
msgid "Keybinding to start/stop the builtin screen recorder." msgid "Keybinding to start/stop the builtin screen recorder."
msgstr "বিল্টইন পৰ্দা ৰেকৰ্ডাৰ আৰম্ভ/বন্ধ কৰিবলে Keybinding।" msgstr "বিল্টইন পৰ্দা ৰেকৰ্ডাৰ আৰম্ভ/বন্ধ কৰিবলে Keybinding।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31 #: ../data/org.gnome.shell.gschema.xml.in.in.h:29
msgid "Which keyboard to use" msgid "Which keyboard to use"
msgstr "কোনটো কিবৰ্ড ব্যৱহাৰ কৰা হব" msgstr "কোনটো কিবৰ্ড ব্যৱহাৰ কৰা হব"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32 #: ../data/org.gnome.shell.gschema.xml.in.in.h:30
msgid "The type of keyboard to use." msgid "The type of keyboard to use."
msgstr "ব্যৱহাৰ কৰিব লগিয়া কিবৰ্ডৰ ধৰণ।" msgstr "ব্যৱহাৰ কৰিব লগিয়া কিবৰ্ডৰ ধৰণ।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33 #: ../data/org.gnome.shell.gschema.xml.in.in.h:31
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "screencasts ৰেকৰ্ড কৰাৰ কাৰণে ব্যৱহৃত Framerate" msgstr "screencasts ৰেকৰ্ড কৰাৰ কাৰণে ব্যৱহৃত Framerate"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34 #: ../data/org.gnome.shell.gschema.xml.in.in.h:32
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
@@ -263,11 +242,11 @@ msgstr ""
"GNOME শ্বেলৰ screencast ৰেকৰ্ডাৰে ফ্ৰেইম-প্ৰতি ছেকেণ্ডত ৰেকৰ্ড কৰা পৰিণাম " "GNOME শ্বেলৰ screencast ৰেকৰ্ডাৰে ফ্ৰেইম-প্ৰতি ছেকেণ্ডত ৰেকৰ্ড কৰা পৰিণাম "
"screencast ৰ framerate।" "screencast ৰ framerate।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35 #: ../data/org.gnome.shell.gschema.xml.in.in.h:33
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "screencast এনক'ড কৰিবলে ব্যৱহাৰ কৰা gstreamer পাইপলাইন" msgstr "screencast এনক'ড কৰিবলে ব্যৱহাৰ কৰা gstreamer পাইপলাইন"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37 #: ../data/org.gnome.shell.gschema.xml.in.in.h:35
#, no-c-format #, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@@ -295,11 +274,11 @@ msgstr ""
"কাওন্টত এটা " "কাওন্টত এটা "
"অনুমানৰ প্লেইচহল্ডাৰ হিচাপে ব্যৱহাৰ কৰা হয়।" "অনুমানৰ প্লেইচহল্ডাৰ হিচাপে ব্যৱহাৰ কৰা হয়।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38 #: ../data/org.gnome.shell.gschema.xml.in.in.h:36
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "screencast সংৰক্ষণ কৰাৰ কাৰণে লথিপত্ৰ সম্প্ৰসাৰন" msgstr "screencast সংৰক্ষণ কৰাৰ কাৰণে লথিপত্ৰ সম্প্ৰসাৰন"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39 #: ../data/org.gnome.shell.gschema.xml.in.in.h:37
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
@@ -310,36 +289,20 @@ msgstr ""
"অন্তৰ্ভুক্তক " "অন্তৰ্ভুক্তক "
"বিন্যাসত ৰেকৰ্ড কৰোতে পৰিবৰ্তন কৰিব লাগিব।" "বিন্যাসত ৰেকৰ্ড কৰোতে পৰিবৰ্তন কৰিব লাগিব।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40 #: ../data/org.gnome.shell.gschema.xml.in.in.h:38
#| msgid "Open the application menu"
msgid "The application icon mode."
msgstr "এপ্লিকেচন আইকন অৱস্থা।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
msgid ""
"Configures how the windows are shown in the switcher. Valid possibilities "
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
"only' (shows only the application icon) or 'both'."
msgstr ""
"চুইচাৰত উইন্ডোসমূহ কেনেধৰণে দেখুৱা হয় সংৰূপণ কৰে। বৈধ সম্ভাবনাসমূহ হল "
"'thumbnail-only' "
"(উইন্ডোৰ এটা থাম্বনেইল দেখুৱায়), 'app-icon-only' (কেৱল এপ্লিকেচন আইকন "
"দেখুৱায়) অথবা 'both'।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
msgid "Attach modal dialog to the parent window" msgid "Attach modal dialog to the parent window"
msgstr "মডাল ডাইলগ উপধায়ক উইন্ডোৰ সৈতে সংলগ্ন কৰক" msgstr "মডাল ডাইলগ উপধায়ক উইন্ডোৰ সৈতে সংলগ্ন কৰক"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43 #: ../data/org.gnome.shell.gschema.xml.in.in.h:39
msgid "" msgid ""
"This key overrides the key in org.gnome.mutter when running GNOME Shell." "This key overrides the key in org.gnome.mutter when running GNOME Shell."
msgstr "GNOME শ্বেল চলাওতে এই কি'য়ে org.gnome.mutter ত থকা কি' অভাৰৰাইড কৰে।" msgstr "GNOME শ্বেল চলাওতে এই কি'য়ে org.gnome.mutter ত থকা কি' অভাৰৰাইড কৰে।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:44 #: ../data/org.gnome.shell.gschema.xml.in.in.h:40
msgid "Arrangement of buttons on the titlebar" msgid "Arrangement of buttons on the titlebar"
msgstr "শীৰ্ষকবাৰত বুটামসমূহ সজোঁৱা" msgstr "শীৰ্ষকবাৰত বুটামসমূহ সজোঁৱা"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:45 #: ../data/org.gnome.shell.gschema.xml.in.in.h:41
msgid "" msgid ""
"This key overrides the key in org.gnome.desktop.wm.preferences when running " "This key overrides the key in org.gnome.desktop.wm.preferences when running "
"GNOME Shell." "GNOME Shell."
@@ -347,15 +310,15 @@ msgstr ""
"GNOME শ্বেল চলাওতে এই কি'য়ে org.gnome.desktop.wm.preferences ত থকা কি' " "GNOME শ্বেল চলাওতে এই কি'য়ে org.gnome.desktop.wm.preferences ত থকা কি' "
"অভাৰৰাইড কৰে।" "অভাৰৰাইড কৰে।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:46 #: ../data/org.gnome.shell.gschema.xml.in.in.h:42
msgid "Enable edge tiling when dropping windows on screen edges" msgid "Enable edge tiling when dropping windows on screen edges"
msgstr "উইন্ডোসমূহক পৰ্দাৰ প্ৰান্তসমূহত এৰোতে প্ৰান্ত টাইলিং সামৰ্থবান কৰক" msgstr "উইন্ডোসমূহক পৰ্দাৰ প্ৰান্তসমূহত এৰোতে প্ৰান্ত টাইলিং সামৰ্থবান কৰক"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:47 #: ../data/org.gnome.shell.gschema.xml.in.in.h:43
msgid "Workspaces are managed dynamically" msgid "Workspaces are managed dynamically"
msgstr "কাৰ্য্যস্থানসমূহক চলমানভাৱে ব্যৱস্থাপনা কৰা হয়" msgstr "কাৰ্য্যস্থানসমূহক চলমানভাৱে ব্যৱস্থাপনা কৰা হয়"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:48 #: ../data/org.gnome.shell.gschema.xml.in.in.h:44
msgid "Workspaces only on primary monitor" msgid "Workspaces only on primary monitor"
msgstr "কাৰ্য্যস্থানসমূহ কেৱল প্ৰাথমিক মনিটৰত" msgstr "কাৰ্য্যস্থানসমূহ কেৱল প্ৰাথমিক মনিটৰত"
@@ -390,8 +353,8 @@ msgstr "তালিকাভুক্ত নহয়?"
#: ../js/gdm/loginDialog.js:962 ../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/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396
#: ../js/ui/status/bluetooth.js:413 ../js/ui/unlockDialog.js:178 #: ../js/ui/status/bluetooth.js:413 ../js/ui/unlockDialog.js:179
msgid "Cancel" msgid "Cancel"
msgstr "বাতিল কৰক" msgstr "বাতিল কৰক"
@@ -470,23 +433,23 @@ msgstr "'%s' ৰ প্ৰেৰণ ব্যৰ্থ হল:"
msgid "All" msgid "All"
msgstr "সকলো" msgstr "সকলো"
#: ../js/ui/appDisplay.js:318 #: ../js/ui/appDisplay.js:317
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "APPLICATIONS" msgstr "APPLICATIONS"
#: ../js/ui/appDisplay.js:375 #: ../js/ui/appDisplay.js:377
msgid "SETTINGS" msgid "SETTINGS"
msgstr "SETTINGS" msgstr "SETTINGS"
#: ../js/ui/appDisplay.js:679 #: ../js/ui/appDisplay.js:682
msgid "New Window" msgid "New Window"
msgstr "নতুন উইন্ডো" msgstr "নতুন উইন্ডো"
#: ../js/ui/appDisplay.js:682 ../js/ui/dash.js:289 #: ../js/ui/appDisplay.js:685 ../js/ui/dash.js:289
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "পছন্দৰ পৰা আতৰাওক" msgstr "পছন্দৰ পৰা আতৰাওক"
#: ../js/ui/appDisplay.js:683 #: ../js/ui/appDisplay.js:686
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "পছন্দলে যোগ কৰক" msgstr "পছন্দলে যোগ কৰক"
@@ -759,7 +722,7 @@ msgstr "প্ৰমাণীত কৰক"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/components/polkitAgent.js:248 ../js/ui/shellMountOperation.js:383 #: ../js/ui/components/polkitAgent.js:248 ../js/ui/shellMountOperation.js:381
msgid "Sorry, that didn't work. Please try again." msgid "Sorry, that didn't work. Please try again."
msgstr "ক্ষমা কৰিব, সেয়া কাম নকৰিলে। অনুগ্ৰহ কৰি পুনৰ চেষ্টা কৰক।" msgstr "ক্ষমা কৰিব, সেয়া কাম নকৰিলে। অনুগ্ৰহ কৰি পুনৰ চেষ্টা কৰক।"
@@ -797,40 +760,42 @@ msgstr "অমৌন কৰক"
msgid "Mute" msgid "Mute"
msgstr "মোন কৰক" msgstr "মোন কৰক"
#. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30" #. Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"
#: ../js/ui/components/telepathyClient.js:931 #: ../js/ui/components/telepathyClient.js:932
#, no-c-format #, no-c-format
msgid "<b>Yesterday</b>, <b>%H:%M</b>" msgid "<b>%H:%M</b> on Yesterday"
msgstr "<b>যোৱাকালী</b>, <b>%H:%M</b>" msgstr "<b>%H:%M</b> যোৱাকালী"
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30 #. Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday
#: ../js/ui/components/telepathyClient.js:937 #: ../js/ui/components/telepathyClient.js:938
#, no-c-format #, no-c-format
msgid "<b>%A</b>, <b>%H:%M</b>" msgid "<b>%H:%M</b> on <b>%A</b>"
msgstr "<b>%A</b>, <b>%H:%M</b>" msgstr "<b>%A</b> <b>%H:%M</b>"
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30" #. Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
#: ../js/ui/components/telepathyClient.js:942 #. shown when you get a chat message in the same year
#: ../js/ui/components/telepathyClient.js:944
#, no-c-format #, no-c-format
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>" msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
msgstr "<b>%B</b> <b>%d</b>, <b>%H:%M</b>" msgstr "<b>%A</b> <b>%H:%M</b>, <b>%B</b> <b>%d</b>"
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30" #. Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
#: ../js/ui/components/telepathyClient.js:946 #. shown when you get a chat message in a different year
#: ../js/ui/components/telepathyClient.js:949
#, no-c-format #, no-c-format
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> " msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
msgstr "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> " msgstr "<b>%A</b> <b>%H:%M</b>, <b>%B</b> <b>%d</b>, %Y"
#. Translators: this is the other person changing their old IM name to their new #. Translators: this is the other person changing their old IM name to their new
#. IM name. #. IM name.
#: ../js/ui/components/telepathyClient.js:974 #: ../js/ui/components/telepathyClient.js:977
#, c-format #, c-format
msgid "%s is now known as %s" msgid "%s is now known as %s"
msgstr "%s এতিয়া %s হিচাপে জনাজাত" msgstr "%s এতিয়া %s হিচাপে জনাজাত"
#. translators: argument is a room name like #. translators: argument is a room name like
#. * room@jabber.org for example. #. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1073 #: ../js/ui/components/telepathyClient.js:1076
#, c-format #, c-format
msgid "Invitation to %s" msgid "Invitation to %s"
msgstr "%s লে নিমন্ত্ৰণ" msgstr "%s লে নিমন্ত্ৰণ"
@@ -838,38 +803,38 @@ msgstr "%s লে নিমন্ত্ৰণ"
#. translators: first argument is the name of a contact and the second #. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org #. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example. #. * for example.
#: ../js/ui/components/telepathyClient.js:1081 #: ../js/ui/components/telepathyClient.js:1084
#, c-format #, c-format
msgid "%s is inviting you to join %s" msgid "%s is inviting you to join %s"
msgstr "%s এ আপোনাক %s ত অংশগ্ৰহণ কৰিবলে আমন্ত্ৰণ জনাইছে" msgstr "%s এ আপোনাক %s ত অংশগ্ৰহণ কৰিবলে আমন্ত্ৰণ জনাইছে"
#: ../js/ui/components/telepathyClient.js:1083 #: ../js/ui/components/telepathyClient.js:1086
#: ../js/ui/components/telepathyClient.js:1122 #: ../js/ui/components/telepathyClient.js:1125
#: ../js/ui/components/telepathyClient.js:1162 #: ../js/ui/components/telepathyClient.js:1165
#: ../js/ui/components/telepathyClient.js:1225 #: ../js/ui/components/telepathyClient.js:1228
msgid "Decline" msgid "Decline"
msgstr "নাকচ কৰক" msgstr "নাকচ কৰক"
#: ../js/ui/components/telepathyClient.js:1084 #: ../js/ui/components/telepathyClient.js:1087
#: ../js/ui/components/telepathyClient.js:1163 #: ../js/ui/components/telepathyClient.js:1166
#: ../js/ui/components/telepathyClient.js:1226 #: ../js/ui/components/telepathyClient.js:1229
msgid "Accept" msgid "Accept"
msgstr "গ্ৰহন কৰক" msgstr "গ্ৰহন কৰক"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1114 #: ../js/ui/components/telepathyClient.js:1117
#, c-format #, c-format
msgid "Video call from %s" msgid "Video call from %s"
msgstr "%s ৰ পৰা ভিডিঅ' কল" msgstr "%s ৰ পৰা ভিডিঅ' কল"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1117 #: ../js/ui/components/telepathyClient.js:1120
#, c-format #, c-format
msgid "Call from %s" msgid "Call from %s"
msgstr "%s ৰ পৰা কল" msgstr "%s ৰ পৰা কল"
#. translators: this is a button label (verb), not a noun #. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1124 #: ../js/ui/components/telepathyClient.js:1127
msgid "Answer" msgid "Answer"
msgstr "উত্তৰ দিয়ক" msgstr "উত্তৰ দিয়ক"
@@ -878,110 +843,110 @@ msgstr "উত্তৰ দিয়ক"
#. * file name. The string will be something #. * file name. The string will be something
#. * like: "Alice is sending you test.ogg" #. * like: "Alice is sending you test.ogg"
#. #.
#: ../js/ui/components/telepathyClient.js:1156 #: ../js/ui/components/telepathyClient.js:1159
#, c-format #, c-format
msgid "%s is sending you %s" msgid "%s is sending you %s"
msgstr "%s এ আপোনাক %s পঠাই আছে" msgstr "%s এ আপোনাক %s পঠাই আছে"
#. To translators: The parameter is the contact's alias #. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1191 #: ../js/ui/components/telepathyClient.js:1194
#, c-format #, c-format
msgid "%s would like permission to see when you are online" msgid "%s would like permission to see when you are online"
msgstr "আপুনি কেতিয়া অনলাইন আছে চাবলে %s এ অনুমতি বিচাৰিব" msgstr "আপুনি কেতিয়া অনলাইন আছে চাবলে %s এ অনুমতি বিচাৰিব"
#: ../js/ui/components/telepathyClient.js:1283 #: ../js/ui/components/telepathyClient.js:1286
msgid "Network error" msgid "Network error"
msgstr "নেটৱাৰ্ক ত্ৰুটি" msgstr "নেটৱাৰ্ক ত্ৰুটি"
#: ../js/ui/components/telepathyClient.js:1285 #: ../js/ui/components/telepathyClient.js:1288
msgid "Authentication failed" msgid "Authentication failed"
msgstr "প্ৰমাণীকৰণ ব্যৰ্থ" msgstr "প্ৰমাণীকৰণ ব্যৰ্থ"
#: ../js/ui/components/telepathyClient.js:1287 #: ../js/ui/components/telepathyClient.js:1290
msgid "Encryption error" msgid "Encryption error"
msgstr "ইনক্ৰিপষণ ত্ৰুটি" msgstr "ইনক্ৰিপষণ ত্ৰুটি"
#: ../js/ui/components/telepathyClient.js:1289 #: ../js/ui/components/telepathyClient.js:1292
msgid "Certificate not provided" msgid "Certificate not provided"
msgstr "প্ৰমাণপত্ৰ প্ৰদান কৰা হোৱা নাই" msgstr "প্ৰমাণপত্ৰ প্ৰদান কৰা হোৱা নাই"
#: ../js/ui/components/telepathyClient.js:1291 #: ../js/ui/components/telepathyClient.js:1294
msgid "Certificate untrusted" msgid "Certificate untrusted"
msgstr "প্ৰমাণপত্ৰক ভৰষা কৰিব নোৱাৰি" msgstr "প্ৰমাণপত্ৰক ভৰষা কৰিব নোৱাৰি"
#: ../js/ui/components/telepathyClient.js:1293 #: ../js/ui/components/telepathyClient.js:1296
msgid "Certificate expired" msgid "Certificate expired"
msgstr "প্ৰমাণপত্ৰৰ অৱসান ঘটিছে" msgstr "প্ৰমাণপত্ৰৰ অৱসান ঘটিছে"
#: ../js/ui/components/telepathyClient.js:1295 #: ../js/ui/components/telepathyClient.js:1298
msgid "Certificate not activated" msgid "Certificate not activated"
msgstr "প্ৰমাণপত্ৰ সক্ৰিয় কৰা হোৱা নাই" msgstr "প্ৰমাণপত্ৰ সক্ৰিয় কৰা হোৱা নাই"
#: ../js/ui/components/telepathyClient.js:1297 #: ../js/ui/components/telepathyClient.js:1300
msgid "Certificate hostname mismatch" msgid "Certificate hostname mismatch"
msgstr "প্ৰমাণপত্ৰ হস্টনাম অমিল" msgstr "প্ৰমাণপত্ৰ হস্টনাম অমিল"
#: ../js/ui/components/telepathyClient.js:1299 #: ../js/ui/components/telepathyClient.js:1302
msgid "Certificate fingerprint mismatch" msgid "Certificate fingerprint mismatch"
msgstr "প্ৰমাণপত্ৰ ফিংগাৰপ্ৰিন্ট অমিল" msgstr "প্ৰমাণপত্ৰ ফিংগাৰপ্ৰিন্ট অমিল"
#: ../js/ui/components/telepathyClient.js:1301 #: ../js/ui/components/telepathyClient.js:1304
msgid "Certificate self-signed" msgid "Certificate self-signed"
msgstr "প্ৰমাণপত্ৰ স্ব-স্বাক্ষৰীত" msgstr "প্ৰমাণপত্ৰ স্ব-স্বাক্ষৰীত"
#: ../js/ui/components/telepathyClient.js:1303 #: ../js/ui/components/telepathyClient.js:1306
msgid "Status is set to offline" msgid "Status is set to offline"
msgstr "অৱস্থা অফলাইনলে সংহতি কৰা হৈছে" msgstr "অৱস্থা অফলাইনলে সংহতি কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1305 #: ../js/ui/components/telepathyClient.js:1308
msgid "Encryption is not available" msgid "Encryption is not available"
msgstr "ইনক্ৰিপষণ উপলব্ধ নহয়" msgstr "ইনক্ৰিপষণ উপলব্ধ নহয়"
#: ../js/ui/components/telepathyClient.js:1307 #: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate is invalid" msgid "Certificate is invalid"
msgstr "প্ৰমাণপত্ৰ অবৈধ" msgstr "প্ৰমাণপত্ৰ অবৈধ"
#: ../js/ui/components/telepathyClient.js:1309 #: ../js/ui/components/telepathyClient.js:1312
msgid "Connection has been refused" msgid "Connection has been refused"
msgstr "সংযোগ নাকচ কৰা হৈছে" msgstr "সংযোগ নাকচ কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1311 #: ../js/ui/components/telepathyClient.js:1314
msgid "Connection can't be established" msgid "Connection can't be established"
msgstr "সংযোগ স্থাপন কৰিব নোৱাৰি" msgstr "সংযোগ স্থাপন কৰিব নোৱাৰি"
#: ../js/ui/components/telepathyClient.js:1313 #: ../js/ui/components/telepathyClient.js:1316
msgid "Connection has been lost" msgid "Connection has been lost"
msgstr "সংযোগ হেৰাইছে" msgstr "সংযোগ হেৰাইছে"
#: ../js/ui/components/telepathyClient.js:1315 #: ../js/ui/components/telepathyClient.js:1318
msgid "This account is already connected to the server" msgid "This account is already connected to the server"
msgstr "এই একাওন্ট ইতিমধ্যে চাৰ্ভাৰৰ সৈতে সংযোগিত" msgstr "এই একাওন্ট ইতিমধ্যে চাৰ্ভাৰৰ সৈতে সংযোগিত"
#: ../js/ui/components/telepathyClient.js:1317 #: ../js/ui/components/telepathyClient.js:1320
msgid "" msgid ""
"Connection has been replaced by a new connection using the same resource" "Connection has been replaced by a new connection using the same resource"
msgstr "সংযোগক একে সম্পদ ব্যৱহাৰ কৰি এটা নতুন সংযোগৰে প্ৰতিস্থাপন কৰা হৈছে" msgstr "সংযোগক একে সম্পদ ব্যৱহাৰ কৰি এটা নতুন সংযোগৰে প্ৰতিস্থাপন কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1319 #: ../js/ui/components/telepathyClient.js:1322
msgid "The account already exists on the server" msgid "The account already exists on the server"
msgstr "একাওন্ট ইতিমধ্যে চাৰ্ভাৰত উপস্থিত" msgstr "একাওন্ট ইতিমধ্যে চাৰ্ভাৰত উপস্থিত"
#: ../js/ui/components/telepathyClient.js:1321 #: ../js/ui/components/telepathyClient.js:1324
msgid "Server is currently too busy to handle the connection" msgid "Server is currently too busy to handle the connection"
msgstr "চাৰ্ভাৰ সংযোগ ব্যৱস্থাপনা কৰিবলে বৰ্তমানে অতি ব্যস্ত" msgstr "চাৰ্ভাৰ সংযোগ ব্যৱস্থাপনা কৰিবলে বৰ্তমানে অতি ব্যস্ত"
#: ../js/ui/components/telepathyClient.js:1323 #: ../js/ui/components/telepathyClient.js:1326
msgid "Certificate has been revoked" msgid "Certificate has been revoked"
msgstr "প্ৰমাণপত্ৰ প্ৰত্যাহাৰ কৰা হৈছে" msgstr "প্ৰমাণপত্ৰ প্ৰত্যাহাৰ কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1325 #: ../js/ui/components/telepathyClient.js:1328
msgid "" msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak" "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "" msgstr ""
"প্ৰমাণপত্ৰয় এটা অসুৰক্ষিত চিফাৰ এলগৰিথম ব্যৱহাৰ কৰে অথবা ক্ৰিপ্টোগ্ৰাফিয়ভাৱে " "প্ৰমাণপত্ৰয় এটা অসুৰক্ষিত চিফাৰ এলগৰিথম ব্যৱহাৰ কৰে অথবা ক্ৰিপ্টোগ্ৰাফিয়ভাৱে "
"দুৰ্বল" "দুৰ্বল"
#: ../js/ui/components/telepathyClient.js:1327 #: ../js/ui/components/telepathyClient.js:1330
msgid "" msgid ""
"The length of the server certificate, or the depth of the server certificate " "The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library" "chain, exceed the limits imposed by the cryptography library"
@@ -990,29 +955,26 @@ msgstr ""
"ক্ৰিপ্টোগ্ৰাফী " "ক্ৰিপ্টোগ্ৰাফী "
"লাইব্ৰেৰীয়ে প্ৰণয়ন কৰা সীমাসমূহত অতিক্ৰম কৰে" "লাইব্ৰেৰীয়ে প্ৰণয়ন কৰা সীমাসমূহত অতিক্ৰম কৰে"
#: ../js/ui/components/telepathyClient.js:1329 #: ../js/ui/components/telepathyClient.js:1332
msgid "Internal error" msgid "Internal error"
msgstr "অভ্যন্তৰীক ত্ৰুটি" msgstr "অভ্যন্তৰীক ত্ৰুটি"
#. translators: argument is the account name, like #. translators: argument is the account name, like
#. * name@jabber.org for example. #. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1339 #: ../js/ui/components/telepathyClient.js:1342
#, c-format #, c-format
msgid "Unable to connect to %s" msgid "Unable to connect to %s"
msgstr "%s ৰ সৈতে সংযোগ কৰিবলে অক্ষম" msgstr "%s ৰ সৈতে সংযোগ কৰিবলে অক্ষম"
#: ../js/ui/components/telepathyClient.js:1344 #: ../js/ui/components/telepathyClient.js:1347
#| msgid "Edit account"
msgid "View account" msgid "View account"
msgstr "একাওন্ট দৰ্শন কৰক" msgstr "একাওন্ট দৰ্শন কৰক"
#: ../js/ui/components/telepathyClient.js:1384 #: ../js/ui/components/telepathyClient.js:1387
msgid "Unknown reason" msgid "Unknown reason"
msgstr "অজ্ঞাত কাৰণ" msgstr "অজ্ঞাত কাৰণ"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:87
msgid "Windows"
msgstr "উইন্ডোসমূহ"
#: ../js/ui/dash.js:253 ../js/ui/dash.js:291 #: ../js/ui/dash.js:253 ../js/ui/dash.js:291
msgid "Show Applications" msgid "Show Applications"
msgstr "এপ্লিকেচনসমূহ দেখুৱাওক" msgstr "এপ্লিকেচনসমূহ দেখুৱাওক"
@@ -1162,7 +1124,9 @@ msgstr "ত্ৰুটিসমূহ দেখুৱাওক"
msgid "Enabled" msgid "Enabled"
msgstr "সামৰ্থবান কৰা আছে" msgstr "সামৰ্থবান কৰা আছে"
#: ../js/ui/lookingGlass.js:767 #. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:767 ../src/gvc/gvc-mixer-control.c:1082
msgid "Disabled" msgid "Disabled"
msgstr "অসামৰ্থবান কৰা আছে" msgstr "অসামৰ্থবান কৰা আছে"
@@ -1194,15 +1158,15 @@ msgstr "খোলক"
msgid "Remove" msgid "Remove"
msgstr "আতৰাওক" msgstr "আতৰাওক"
#: ../js/ui/messageTray.js:1551 #: ../js/ui/messageTray.js:1552
msgid "No Messages" msgid "No Messages"
msgstr "কোনো বাৰ্তা নাই" msgstr "কোনো বাৰ্তা নাই"
#: ../js/ui/messageTray.js:1568 #: ../js/ui/messageTray.js:1569
msgid "Message Tray" msgid "Message Tray"
msgstr "বাৰ্তা ট্ৰে" msgstr "বাৰ্তা ট্ৰে"
#: ../js/ui/messageTray.js:2635 #: ../js/ui/messageTray.js:2639
msgid "System Information" msgid "System Information"
msgstr "চিস্টেম তথ্য" msgstr "চিস্টেম তথ্য"
@@ -1211,11 +1175,11 @@ msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "অজ্ঞাত" msgstr "অজ্ঞাত"
#: ../js/ui/overview.js:95 #: ../js/ui/overview.js:107
msgid "Undo" msgid "Undo"
msgstr "কাৰ্য্য বাতিল কৰক" msgstr "কাৰ্য্য বাতিল কৰক"
#: ../js/ui/overview.js:144 #: ../js/ui/overview.js:155
msgid "Overview" msgid "Overview"
msgstr "অভাৰভিউ" msgstr "অভাৰভিউ"
@@ -1223,27 +1187,27 @@ msgstr "অভাৰভিউ"
#. in the search entry when no search is #. in the search entry when no search is
#. active; it should not exceed ~30 #. active; it should not exceed ~30
#. characters. #. characters.
#: ../js/ui/overview.js:221 #: ../js/ui/overview.js:229
msgid "Type to search..." msgid "Type to search..."
msgstr "সন্ধান কৰিবলে টাইপ কৰক..." msgstr "সন্ধান কৰিবলে টাইপ কৰক..."
#. Translators: this is the name of the dock/favorites area on #. Translators: this is the name of the dock/favorites area on
#. the left of the overview #. the left of the overview
#: ../js/ui/overview.js:242 #: ../js/ui/overview.js:250
msgid "Dash" msgid "Dash"
msgstr "ডেশ" msgstr "ডেশ"
#: ../js/ui/panel.js:608 #: ../js/ui/panel.js:599
msgid "Quit" msgid "Quit"
msgstr "প্ৰস্থান কৰক" msgstr "প্ৰস্থান কৰক"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:637 #: ../js/ui/panel.js:631
msgid "Activities" msgid "Activities"
msgstr "কাৰ্য্যসমূহ" msgstr "কাৰ্য্যসমূহ"
#: ../js/ui/panel.js:980 #: ../js/ui/panel.js:999
msgid "Top Bar" msgid "Top Bar"
msgstr "উপৰৰ বাৰ" msgstr "উপৰৰ বাৰ"
@@ -1252,7 +1216,7 @@ msgstr "উপৰৰ বাৰ"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:732 #: ../js/ui/popupMenu.js:731
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-us" msgstr "toggle-switch-us"
@@ -1284,15 +1248,15 @@ msgid_plural "%d new notifications"
msgstr[0] "%d নতুন অধিসূচনা" msgstr[0] "%d নতুন অধিসূচনা"
msgstr[1] "%d নতুন অধিসূচনাসমূহ" msgstr[1] "%d নতুন অধিসূচনাসমূহ"
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:780 #: ../js/ui/screenShield.js:401 ../js/ui/userMenu.js:780
msgid "Lock" msgid "Lock"
msgstr "লক কৰক" msgstr "লক কৰক"
#: ../js/ui/searchDisplay.js:277 #: ../js/ui/searchDisplay.js:275
msgid "Searching..." msgid "Searching..."
msgstr "সন্ধান কৰা হৈছে..." msgstr "সন্ধান কৰা হৈছে..."
#: ../js/ui/searchDisplay.js:325 #: ../js/ui/searchDisplay.js:323
msgid "No results." msgid "No results."
msgstr "কোনো ফলাফল নাই।" msgstr "কোনো ফলাফল নাই।"
@@ -1312,15 +1276,15 @@ msgstr "লিখনী দেখুৱাওক"
msgid "Hide Text" msgid "Hide Text"
msgstr "লিখনী লুকুৱাওক" msgstr "লিখনী লুকুৱাওক"
#: ../js/ui/shellMountOperation.js:370 #: ../js/ui/shellMountOperation.js:368
msgid "Password" msgid "Password"
msgstr "পাছৱাৰ্ড" msgstr "পাছৱাৰ্ড"
#: ../js/ui/shellMountOperation.js:391 #: ../js/ui/shellMountOperation.js:389
msgid "Remember Password" msgid "Remember Password"
msgstr "পাছৱাৰ্ড মনত ৰাখক" msgstr "পাছৱাৰ্ড মনত ৰাখক"
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:192 #: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:193
msgid "Unlock" msgid "Unlock"
msgstr "আনলক কৰক" msgstr "আনলক কৰক"
@@ -1408,7 +1372,7 @@ msgid "disconnecting..."
msgstr "বিচ্ছিনিত কৰা হৈছে..." msgstr "বিচ্ছিনিত কৰা হৈছে..."
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:442 #: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:442
#: ../js/ui/status/network.js:1453 #: ../js/ui/status/network.js:1449
msgid "connecting..." msgid "connecting..."
msgstr "সংযোগ কৰা হৈছে..." msgstr "সংযোগ কৰা হৈছে..."
@@ -1424,7 +1388,7 @@ msgstr "কিবৰ্ড সংহতিসমূহ"
msgid "Mouse Settings" msgid "Mouse Settings"
msgstr "মাউছ আৰু টাচপেড সংহতিসমূহ" msgstr "মাউছ আৰু টাচপেড সংহতিসমূহ"
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:270 #: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:234
msgid "Sound Settings" msgid "Sound Settings"
msgstr "শব্দ সংহতিসমূহ" msgstr "শব্দ সংহতিসমূহ"
@@ -1516,7 +1480,7 @@ msgid "unmanaged"
msgstr "অব্যৱস্থাপিত" msgstr "অব্যৱস্থাপিত"
#. Translators: this is for network connections that require some kind of key or password #. 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:1456 #: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1452
msgid "authentication required" msgid "authentication required"
msgstr "প্ৰমাণীকৰণৰ প্ৰয়োজন" msgstr "প্ৰমাণীকৰণৰ প্ৰয়োজন"
@@ -1537,72 +1501,72 @@ msgstr "কেবুল আনপ্লাগ্গড"
msgid "unavailable" msgid "unavailable"
msgstr "উপলব্ধ নাই" msgstr "উপলব্ধ নাই"
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1458 #: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1454
msgid "connection failed" msgid "connection failed"
msgstr "সংযোগ ব্যৰ্থ" msgstr "সংযোগ ব্যৰ্থ"
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1392 #: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1388
#: ../js/ui/status/network.js:1534 #: ../js/ui/status/network.js:1530
msgid "More..." msgid "More..."
msgstr "অধিক..." msgstr "অধিক..."
#. TRANSLATORS: this is the indication that a connection for another logged in user is active, #. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name) #. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1322 #: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1318
msgid "Connected (private)" msgid "Connected (private)"
msgstr "সংযোগিত (ব্যক্তিগত)" msgstr "সংযোগিত (ব্যক্তিগত)"
#: ../js/ui/status/network.js:619 #: ../js/ui/status/network.js:615
msgid "Auto Ethernet" msgid "Auto Ethernet"
msgstr "স্বচালিত ইথাৰনেট" msgstr "স্বচালিত ইথাৰনেট"
#: ../js/ui/status/network.js:677 #: ../js/ui/status/network.js:673
msgid "Auto broadband" msgid "Auto broadband"
msgstr "স্বচালিত ব্ৰডবেণ্ড" msgstr "স্বচালিত ব্ৰডবেণ্ড"
#: ../js/ui/status/network.js:680 #: ../js/ui/status/network.js:676
msgid "Auto dial-up" msgid "Auto dial-up"
msgstr "স্বচালিত ডায়েল-আপ" msgstr "স্বচালিত ডায়েল-আপ"
#. TRANSLATORS: this the automatic wireless connection name (including the network name) #. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:809 ../js/ui/status/network.js:1339 #: ../js/ui/status/network.js:805 ../js/ui/status/network.js:1335
#, c-format #, c-format
msgid "Auto %s" msgid "Auto %s"
msgstr "স্বচালিত %s" msgstr "স্বচালিত %s"
#: ../js/ui/status/network.js:811 #: ../js/ui/status/network.js:807
msgid "Auto bluetooth" msgid "Auto bluetooth"
msgstr "স্বচালিত ব্লুটুথ" msgstr "স্বচালিত ব্লুটুথ"
#: ../js/ui/status/network.js:1341 #: ../js/ui/status/network.js:1337
msgid "Auto wireless" msgid "Auto wireless"
msgstr "স্বচালিত বেতাঁৰ" msgstr "স্বচালিত বেতাঁৰ"
#: ../js/ui/status/network.js:1584 #: ../js/ui/status/network.js:1579
msgid "Enable networking" msgid "Enable networking"
msgstr "নেটৱাৰ্কিং সামৰ্থবান কৰক" msgstr "নেটৱাৰ্কিং সামৰ্থবান কৰক"
#: ../js/ui/status/network.js:1616 #: ../js/ui/status/network.js:1611
msgid "Wi-Fi" msgid "Wi-Fi"
msgstr "Wi-Fi" msgstr "Wi-Fi"
#: ../js/ui/status/network.js:1635 #: ../js/ui/status/network.js:1630
msgid "Network Settings" msgid "Network Settings"
msgstr "নেটৱাৰ্ক সংহতিসমূহ" msgstr "নেটৱাৰ্ক সংহতিসমূহ"
#: ../js/ui/status/network.js:1679 #: ../js/ui/status/network.js:1674
msgid "Network Manager" msgid "Network Manager"
msgstr "নেটৱাৰ্ক ব্যৱস্থাপক" msgstr "নেটৱাৰ্ক ব্যৱস্থাপক"
#: ../js/ui/status/network.js:1761 #: ../js/ui/status/network.js:1756
msgid "Connection failed" msgid "Connection failed"
msgstr "সংযোগ ব্যৰ্থ" msgstr "সংযোগ ব্যৰ্থ"
#: ../js/ui/status/network.js:1762 #: ../js/ui/status/network.js:1757
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "নেটৱাৰ্ক সংযোগ সক্ৰিয়কৰণ ব্যৰ্থ হল" msgstr "নেটৱাৰ্ক সংযোগ সক্ৰিয়কৰণ ব্যৰ্থ হল"
#: ../js/ui/status/network.js:2079 #: ../js/ui/status/network.js:2074
msgid "Networking is disabled" msgid "Networking is disabled"
msgstr "নেটৱাৰ্কিং অসামৰ্থবান কৰা আছে" msgstr "নেটৱাৰ্কিং অসামৰ্থবান কৰা আছে"
@@ -1704,19 +1668,19 @@ msgid "Unknown"
msgstr "অজ্ঞাত" msgstr "অজ্ঞাত"
#. Translators: This is the label for audio volume #. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:50 ../js/ui/status/volume.js:251 #: ../js/ui/status/volume.js:47 ../js/ui/status/volume.js:221
msgid "Volume" msgid "Volume"
msgstr "ভলিউম" msgstr "ভলিউম"
#: ../js/ui/status/volume.js:62 #: ../js/ui/status/volume.js:59
msgid "Microphone" msgid "Microphone"
msgstr "মাইক্ৰোফোন" msgstr "মাইক্ৰোফোন"
#: ../js/ui/unlockDialog.js:201 #: ../js/ui/unlockDialog.js:202
msgid "Log in as another user" msgid "Log in as another user"
msgstr "অন্য ব্যৱহাৰকাৰী হিচাপে লগিন কৰক" msgstr "অন্য ব্যৱহাৰকাৰী হিচাপে লগিন কৰক"
#: ../js/ui/unlockDialog.js:224 #: ../js/ui/unlockDialog.js:225
msgid "Unlock Window" msgid "Unlock Window"
msgstr "উইন্ডো আনলক কৰক" msgstr "উইন্ডো আনলক কৰক"
@@ -1778,6 +1742,10 @@ msgstr ""
"অনলাইন অৱস্থা ঠিক কৰা হৈছে যাতে আনে জানিব পাৰে যে আপুনি সিহতৰ বাৰ্তা চাব " "অনলাইন অৱস্থা ঠিক কৰা হৈছে যাতে আনে জানিব পাৰে যে আপুনি সিহতৰ বাৰ্তা চাব "
"নোৱাৰিবও পাৰে।" "নোৱাৰিবও পাৰে।"
#: ../js/ui/viewSelector.js:87
msgid "Windows"
msgstr "উইন্ডোসমূহ"
#: ../js/ui/viewSelector.js:91 #: ../js/ui/viewSelector.js:91
msgid "Applications" msgid "Applications"
msgstr "এপ্লিকেচনসমূহ" msgstr "এপ্লিকেচনসমূহ"
@@ -1786,7 +1754,7 @@ msgstr "এপ্লিকেচনসমূহ"
msgid "Search" msgid "Search"
msgstr "সন্ধান কৰক" msgstr "সন্ধান কৰক"
#: ../js/ui/wanda.js:94 #: ../js/ui/wanda.js:117
#, c-format #, c-format
msgid "" msgid ""
"Sorry, no wisdom for you today:\n" "Sorry, no wisdom for you today:\n"
@@ -1795,12 +1763,12 @@ msgstr ""
"ক্ষমা কৰিব, আপোনাৰ বাবে আজি কোনো জ্ঞান নাই:\n" "ক্ষমা কৰিব, আপোনাৰ বাবে আজি কোনো জ্ঞান নাই:\n"
"%s" "%s"
#: ../js/ui/wanda.js:98 #: ../js/ui/wanda.js:121
#, c-format #, c-format
msgid "%s the Oracle says" msgid "%s the Oracle says"
msgstr "%s Oracle এ ক'য়" msgstr "%s Oracle এ ক'য়"
#: ../js/ui/wanda.js:139 #: ../js/ui/wanda.js:162
msgid "Your favorite Easter Egg" msgid "Your favorite Easter Egg"
msgstr "আপোনাৰ পছন্দৰ Easter Egg" msgstr "আপোনাৰ পছন্দৰ Easter Egg"
@@ -1813,6 +1781,28 @@ msgstr "'%s' প্ৰস্তুত"
msgid "Evolution Calendar" msgid "Evolution Calendar"
msgstr "Evolution কেলেন্ডাৰ" msgstr "Evolution কেলেন্ডাৰ"
#. translators:
#. * The number of sound outputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1089
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
msgstr[0] "%u আউটপুট"
msgstr[1] "%u আউটপুটসমূহ"
#. translators:
#. * The number of sound inputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1099
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "%u ইনপুট"
msgstr[1] "%u ইনপুটসমূহ"
#: ../src/gvc/gvc-mixer-control.c:1397
msgid "System Sounds"
msgstr "চিস্টেম শব্দসমূহ"
#: ../src/main.c:332 #: ../src/main.c:332
msgid "Print version" msgid "Print version"
msgstr "প্ৰিন্ট সংস্কৰণ" msgstr "প্ৰিন্ট সংস্কৰণ"
@@ -1854,25 +1844,6 @@ msgstr "অবিকল্পিত"
msgid "Authentication dialog was dismissed by the user" msgid "Authentication dialog was dismissed by the user"
msgstr "প্ৰমাণীকৰণ ডাইলগ ব্যৱহাৰকাৰী দ্বাৰা নাকচ কৰা হৈছিল" msgstr "প্ৰমাণীকৰণ ডাইলগ ব্যৱহাৰকাৰী দ্বাৰা নাকচ কৰা হৈছিল"
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "%u আউটপুট"
#~ msgstr[1] "%u আউটপুটসমূহ"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "%u ইনপুট"
#~ msgstr[1] "%u ইনপুটসমূহ"
#~ msgid "System Sounds"
#~ msgstr "চিস্টেম শব্দসমূহ"
#~ msgid "<b>%H:%M</b> on Yesterday"
#~ msgstr "<b>%H:%M</b> যোৱাকালী"
#~ msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
#~ msgstr "<b>%A</b> ত <b>%H:%M</b>, <b>%B</b> <b>%d</b>, %Y"
#~ msgid "Subscription request" #~ msgid "Subscription request"
#~ msgstr "স্বাক্ষৰণ অনুৰোধ" #~ msgstr "স্বাক্ষৰণ অনুৰোধ"

805
po/es.po

File diff suppressed because it is too large Load Diff

173
po/et.po
View File

@@ -13,8 +13,8 @@ msgstr ""
"Project-Id-Version: gnome-shell MASTER\n" "Project-Id-Version: gnome-shell MASTER\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-12-09 13:03+0000\n" "POT-Creation-Date: 2012-11-16 18:27+0000\n"
"PO-Revision-Date: 2012-12-18 17:13+0300\n" "PO-Revision-Date: 2012-11-16 20:40+0300\n"
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n" "Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
"Language-Team: Estonian <>\n" "Language-Team: Estonian <>\n"
"Language: et\n" "Language: et\n"
@@ -135,28 +135,6 @@ msgstr ""
"See võti keelab automaatse 'Logi välja' menüükirje peitmise, kui arvutis on " "See võti keelab automaatse 'Logi välja' menüükirje peitmise, kui arvutis on "
"üks kasutaja ning avatud üks seanss." "üks kasutaja ning avatud üks seanss."
msgid "Show full name in the user menu"
msgstr "Kasutajamenüüs näidatakse kasutaja tervet nime"
msgid "Whether the users full name is shown in the user menu or not."
msgstr "Kas kasutajamenüüs näidatakse kasutaja kogu nime või mitte."
msgid ""
"Whether to remember password for mounting encrypted or remote filesystems"
msgstr ""
"Kas pidada meeles krüpteeritud või kaugfailisüsteemide haakimise paroole."
msgid ""
"The shell will request a password when an encrypted device or a remote "
"filesystem is mounted. If the password can be saved for future use a "
"'Remember Password' checkbox will be present. This key sets the default "
"state of the checkbox."
msgstr ""
"Shell küsib parooli, kui haagitakse krüpteeritud seade või kaugfailisüsteem. "
"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" msgid "Show the week date in the calendar"
msgstr "Kalendris näidatakse kuupäeva nädalavormingus" msgstr "Kalendris näidatakse kuupäeva nädalavormingus"
@@ -249,18 +227,6 @@ msgstr ""
"konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend " "konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend "
"määrata." "määrata."
msgid "The application icon mode."
msgstr "Rakenduste ikooni režiim."
msgid ""
"Configures how the windows are shown in the switcher. Valid possibilities "
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
"only' (shows only the application icon) or 'both'."
msgstr ""
"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" msgid "Attach modal dialog to the parent window"
msgstr "Modaaldialoog kuulub vanemakna juurde" msgstr "Modaaldialoog kuulub vanemakna juurde"
@@ -622,8 +588,11 @@ msgstr "Helista"
msgid "File Transfer" msgid "File Transfer"
msgstr "Failiülekanne" msgstr "Failiülekanne"
msgid "Chat" msgid "Subscription request"
msgstr "Vestlus" msgstr "Tellimuse päring"
msgid "Connection error"
msgstr "Ühenduse viga"
msgid "Unmute" msgid "Unmute"
msgstr "Heli peale" msgstr "Heli peale"
@@ -631,25 +600,27 @@ msgstr "Heli peale"
msgid "Mute" msgid "Mute"
msgstr "Heli maha" msgstr "Heli maha"
#. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30" #. Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"
#, no-c-format #, no-c-format
msgid "<b>Yesterday</b>, <b>%H:%M</b>" msgid "<b>%H:%M</b> on Yesterday"
msgstr "<b>Eile</b> <b>%H:%M</b>" msgstr "Eile <b>%H:%M</b>"
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30 #. Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday
#, no-c-format #, no-c-format
msgid "<b>%A</b>, <b>%H:%M</b>" msgid "<b>%H:%M</b> on <b>%A</b>"
msgstr "<b>%A</b>, <b>%H:%M</b>" msgstr "<b>%H:%M</b>, <b>%A</b>"
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30" #. Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
#. shown when you get a chat message in the same year
#, no-c-format #, no-c-format
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>" msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
msgstr "<b>%d. %B</b>, <b>%H:%M</b>" msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b>"
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30" #. Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year
#, no-c-format #, no-c-format
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> " msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
msgstr "<b>%d. %B %Y</b>, <b>%H:%M</b>" msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b> %Y"
#. Translators: this is the other person changing their old IM name to their new #. Translators: this is the other person changing their old IM name to their new
#. IM name. #. IM name.
@@ -786,18 +757,18 @@ msgstr "Sisemine viga"
#. translators: argument is the account name, like #. translators: argument is the account name, like
#. * name@jabber.org for example. #. * name@jabber.org for example.
#, c-format #, c-format
msgid "Unable to connect to %s" msgid "Connection to %s failed"
msgstr "Pole võimalik ühenduda võrguga %s" msgstr "Ühendus %s nurjus"
msgid "View account" msgid "Reconnect"
msgstr "Konto kuvamine" msgstr "Ühendu uuesti"
msgid "Edit account"
msgstr "Konto muutmine"
msgid "Unknown reason" msgid "Unknown reason"
msgstr "Põhjus teadmata" msgstr "Põhjus teadmata"
msgid "Windows"
msgstr "Aknad"
msgid "Show Applications" msgid "Show Applications"
msgstr "Rakenduste kuvamine" msgstr "Rakenduste kuvamine"
@@ -920,6 +891,8 @@ msgstr "Näita vigu"
msgid "Enabled" msgid "Enabled"
msgstr "Lubatud" msgstr "Lubatud"
#. translators:
#. * The device has been disabled
msgid "Disabled" msgid "Disabled"
msgstr "Keelatud" msgstr "Keelatud"
@@ -944,9 +917,6 @@ msgstr "Ava"
msgid "Remove" msgid "Remove"
msgstr "Eemalda" msgstr "Eemalda"
msgid "No Messages"
msgstr "Teateid pole"
msgid "Message Tray" msgid "Message Tray"
msgstr "Teateala" msgstr "Teateala"
@@ -1017,9 +987,6 @@ msgid_plural "%d new notifications"
msgstr[0] "%d uus märguanne" msgstr[0] "%d uus märguanne"
msgstr[1] "%d uut märguannet" msgstr[1] "%d uut märguannet"
msgid "Lock"
msgstr "Lukusta"
msgid "Searching..." msgid "Searching..."
msgstr "Otsimine..." msgstr "Otsimine..."
@@ -1140,7 +1107,6 @@ msgstr "Luba ainult seekord"
msgid "Reject" msgid "Reject"
msgstr "Lükka tagasi" msgstr "Lükka tagasi"
#. Translators: argument is the device short name
#, c-format #, c-format
msgid "Pairing confirmation for %s" msgid "Pairing confirmation for %s"
msgstr "Paardumise kinnitus seadmele %s" msgstr "Paardumise kinnitus seadmele %s"
@@ -1153,7 +1119,6 @@ msgstr "Seade '%s' tahab selle arvutiga paarduda"
msgid "Please confirm whether the PIN '%06d' matches the one on the device." msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "Palun kontrolli, kas PIN-kood '%06d' kattub seadme parooliga." msgstr "Palun kontrolli, kas PIN-kood '%06d' kattub seadme parooliga."
#. Translators: this is the verb, not the noun
msgid "Matches" msgid "Matches"
msgstr "Kattub" msgstr "Kattub"
@@ -1243,8 +1208,14 @@ msgstr "Automaatne juhtmeta ühendus"
msgid "Enable networking" msgid "Enable networking"
msgstr "Luba võrguühendused" msgstr "Luba võrguühendused"
msgid "Wi-Fi" msgid "Wired"
msgstr "Wi-Fi" msgstr "Juhtmega"
msgid "Wireless"
msgstr "Juhtmeta"
msgid "Mobile broadband"
msgstr "Mobiiliühendus"
msgid "Network Settings" msgid "Network Settings"
msgstr "Võrgusätted" msgstr "Võrgusätted"
@@ -1348,9 +1319,6 @@ msgstr "Mikrofon"
msgid "Log in as another user" msgid "Log in as another user"
msgstr "Logi sisse teise kasutajana" msgstr "Logi sisse teise kasutajana"
msgid "Unlock Window"
msgstr "Võta aken lukust lahti"
msgid "Available" msgid "Available"
msgstr "Saadaval" msgstr "Saadaval"
@@ -1381,6 +1349,9 @@ msgstr "Vaheta kasutajat"
msgid "Log Out" msgid "Log Out"
msgstr "Logi välja" msgstr "Logi välja"
msgid "Lock"
msgstr "Lukusta"
msgid "Install Updates & Restart" msgid "Install Updates & Restart"
msgstr "Paigalda uuendused ja taaskäivita" msgstr "Paigalda uuendused ja taaskäivita"
@@ -1394,6 +1365,9 @@ msgstr ""
"Märguanded on nüüd keelatud, sealhulgas vestlusteated. Sinu netiolekut " "Märguanded on nüüd keelatud, sealhulgas vestlusteated. Sinu netiolekut "
"muudeti, et teised teaksid, et sa ei pruugi nende teateid näha." "muudeti, et teised teaksid, et sa ei pruugi nende teateid näha."
msgid "Windows"
msgstr "Aknad"
msgid "Applications" msgid "Applications"
msgstr "Rakendused" msgstr "Rakendused"
@@ -1422,6 +1396,25 @@ msgstr "'%s' on valmis"
msgid "Evolution Calendar" msgid "Evolution Calendar"
msgstr "Evolutioni kalender" msgstr "Evolutioni kalender"
#. translators:
#. * The number of sound outputs on a particular device
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
msgstr[0] "%u väljund"
msgstr[1] "%u väljundit"
#. translators:
#. * The number of sound inputs on a particular device
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "%u sisend"
msgstr[1] "%u sisendit"
msgid "System Sounds"
msgstr "Süsteemi helid"
msgid "Print version" msgid "Print version"
msgstr "Printimise versioon" msgstr "Printimise versioon"
@@ -1453,46 +1446,6 @@ msgstr "Vaikimisi"
msgid "Authentication dialog was dismissed by the user" msgid "Authentication dialog was dismissed by the user"
msgstr "Kasutaja katkestas autentimisdialoogi" msgstr "Kasutaja katkestas autentimisdialoogi"
#~ msgid "Subscription request"
#~ msgstr "Tellimuse päring"
#~ msgid "Connection error"
#~ msgstr "Ühenduse viga"
#~ msgid "<b>%H:%M</b> on Yesterday"
#~ msgstr "Eile <b>%H:%M</b>"
#~ msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
#~ msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b> %Y"
#~ msgid "Connection to %s failed"
#~ msgstr "Ühendus %s nurjus"
#~ msgid "Reconnect"
#~ msgstr "Ühendu uuesti"
#~ msgid "Wired"
#~ msgstr "Juhtmega"
#~ msgid "Wireless"
#~ msgstr "Juhtmeta"
#~ msgid "Mobile broadband"
#~ msgstr "Mobiiliühendus"
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "%u väljund"
#~ msgstr[1] "%u väljundit"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "%u sisend"
#~ msgstr[1] "%u sisendit"
#~ msgid "System Sounds"
#~ msgstr "Süsteemi helid"
#~ msgid "disabled OpenSearch providers" #~ msgid "disabled OpenSearch providers"
#~ msgstr "keelatud OpenSearch pakkujad" #~ msgstr "keelatud OpenSearch pakkujad"

418
po/kn.po
View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-12-07 10:16+0000\n" "POT-Creation-Date: 2012-09-19 11:02+0000\n"
"PO-Revision-Date: 2012-12-07 16:12+0530\n" "PO-Revision-Date: 2012-09-26 16:05+0530\n"
"Last-Translator: Shankar Prasad <svenkate@redhat.com>\n" "Last-Translator: Shankar Prasad <svenkate@redhat.com>\n"
"Language-Team: Kannada <kn@li.org>\n" "Language-Team: Kannada <kn@li.org>\n"
"Language: kn\n" "Language: kn\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: Lokalize 1.5\n" "X-Generator: Lokalize 1.2\n"
#: ../data/50-gnome-shell-screenshot.xml.in.h:1 #: ../data/50-gnome-shell-screenshot.xml.in.h:1
msgid "Screenshots" msgid "Screenshots"
@@ -25,15 +25,16 @@ msgstr "ತೆರೆಚಿತ್ರಗಳು"
#: ../data/50-gnome-shell-screenshot.xml.in.h:2 #: ../data/50-gnome-shell-screenshot.xml.in.h:2
msgid "Record a screencast" msgid "Record a screencast"
msgstr "ಒಂದು ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟನ್ನು ರೆಕಾರ್ಡು ಮಾಡಿ" msgstr ""
#: ../data/50-gnome-shell-system.xml.in.h:1 #: ../data/50-gnome-shell-system.xml.in.h:1
#| msgid "File System"
msgid "System" msgid "System"
msgstr "ವ್ಯವಸ್ಥೆ" msgstr "ವ್ಯವಸ್ಥೆ"
#: ../data/50-gnome-shell-system.xml.in.h:2 #: ../data/50-gnome-shell-system.xml.in.h:2
msgid "Show the message tray" msgid "Show the message tray"
msgstr "ಸಂದೇಶ ಟ್ರೇ ಅನ್ನು ತೋರಿಸು" msgstr ""
#: ../data/gnome-shell.desktop.in.in.h:1 #: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell" msgid "GNOME Shell"
@@ -78,12 +79,6 @@ msgid ""
"list. You can also manipulate this list with the EnableExtension and " "list. You can also manipulate this list with the EnableExtension and "
"DisableExtension DBus methods on org.gnome.Shell." "DisableExtension DBus methods on org.gnome.Shell."
msgstr "" msgstr ""
"GNOME ಶೆಲ್ ವಿಸ್ತರಣೆಗಳು ಒಂದು uuid ಗುಣವನ್ನು ಹೊಂದಿವೆ; ಈ ಕೀಲಿ ಪಟ್ಟಿಯು ಲೋಡ್ "
"ಮಾಡಬೇಕಿರುವ "
"ವಿಸ್ತರಣೆಗಳ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸುತ್ತದೆ. ಯಾವುದೆ ವಿಸ್ತರಣೆಗಳನ್ನು ಲೋಡ್‌ ಮಾಡಬೇಕಿದ್ದಲ್ಲಿ "
"ಅದು ಈ "
"ಪಟ್ಟಿಯಲ್ಲಿ ಇರುವುದು ಅತ್ಯಗತ್ಯ. org.gnome.Shell ನಲ್ಲಿ EnableExtension ಮತ್ತು "
"DisableExtension DBus ವಿಧಾನಗಳನ್ನು ಬಳಸಿಕೊಂಡೂ ಸಹ ಈ ಪಟ್ಟಿಯನ್ನು ನಿರ್ವಹಿಸಬಹುದು."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5 #: ../data/org.gnome.shell.gschema.xml.in.in.h:5
msgid "Whether to collect stats about applications usage" msgid "Whether to collect stats about applications usage"
@@ -96,11 +91,6 @@ msgid ""
"want to disable this for privacy reasons. Please note that doing so won't " "want to disable this for privacy reasons. Please note that doing so won't "
"remove already saved data." "remove already saved data."
msgstr "" msgstr ""
"ಶೆಲ್‌ ಸಾಮಾನ್ಯವಾಗಿ ಹೆಚ್ಚಾಗಿ ಬಳಸಲಾದ (ಉದಾ. ಆರಂಭಕಗಳಲ್ಲಿ) ಅನ್ವಯಗಳನ್ನು ತೋರಿಸಲು "
"ಸಕ್ರಿಯವಾದವುಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ನಡೆಸುತ್ತದೆ. ಈ ದತ್ತಾಂಶವನ್ನು ಗೌಪ್ಯವಾಗಿ "
"ಇರಿಸಲಾಗುತ್ತದೆ, "
"ಹಾಗೂ ಗೌಪ್ಯತಾ ಕಾರಣಗಳಿದ್ದಲ್ಲಿ ನೀವು ಅದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು. ಹಾಗೆ ಮಾಡುವುದರಿಂದ "
"ಉಳಿಸಲಾದ ಯಾವದೆ ದತ್ತಾಂಶವು ತೆಗೆದುಹಾಕಲ್ಪಡುವುದಿಲ್ಲ ಎನ್ನುವುದನ್ನು ನೆನಪಿಡಿ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7 #: ../data/org.gnome.shell.gschema.xml.in.in.h:7
msgid "List of desktop file IDs for favorite applications" msgid "List of desktop file IDs for favorite applications"
@@ -126,75 +116,64 @@ msgid ""
"Internally used to store the last IM presence explicitly set by the user. " "Internally used to store the last IM presence explicitly set by the user. "
"The value here is from the TpConnectionPresenceType enumeration." "The value here is from the TpConnectionPresenceType enumeration."
msgstr "" msgstr ""
"ಆಂತರಿಕವಾಗಿ ಬಳಕೆದಾರರಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ಹೊಂದಿಸಲಾದ ಕೊನೆಯ IM ಅನ್ನು ಶೇಖರಿಸಿಡಸಲು "
"ಬಳಸಲಾಗುತ್ತದೆ. ಇಲ್ಲಿರುವ ಮೌಲ್ಯವು TpConnectionPresenceType ಎನ್ಯೂಮರೇಶನ್‌ನಿಂದ "
"ಬಂದಿರುತ್ತದೆ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12 #: ../data/org.gnome.shell.gschema.xml.in.in.h:12
msgid "" msgid ""
"Internally used to store the last session presence status for the user. The " "Internally used to store the last session presence status for the user. The "
"value here is from the GsmPresenceStatus enumeration." "value here is from the GsmPresenceStatus enumeration."
msgstr "" msgstr ""
"ಆಂತರಿಕವಾಗಿ ಬಳಕೆದಾರರಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ಹೊಂದಿಸಲಾದ ಕೊನೆಯ ಅಧಿವೇಶನವನ್ನು ಶೇಖರಿಸಿಡಸಲು "
"ಬಳಸಲಾಗುತ್ತದೆ. ಇಲ್ಲಿರುವ ಮೌಲ್ಯವು GsmPresenceStatus ಎನ್ಯೂಮರೇಶನ್‌ನಿಂದ ಬಂದಿರುತ್ತದೆ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13 #: ../data/org.gnome.shell.gschema.xml.in.in.h:13
msgid "Always show the 'Log out' menuitem in the user menu."
msgstr "ಯಾವಾಗಲೂ 'ನಿರ್ಗಮಿಸು' ಪರಿವಿಡಿಅಂಶವನ್ನು ಬಳಕೆದಾರ ಪರಿವಿಡಿಯಲ್ಲಿ ತೋರಿಸು."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
msgid ""
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
"user, single-session situations."
msgstr ""
"ಈ ಕೀಲಿಯು ಏಕ-ಬಳಕೆದಾರ, ಏಕ-ಅಧಿವೇಶನ ಸಂದರ್ಭಗಳಲ್ಲಿ 'ನಿರ್ಗಮಿಸು' ಪರಿವಿಡಿಅಂಶವನ್ನು "
"ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಅಡಗಿಸುವ ಆಯ್ಕೆಯನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
msgstr "ಕ್ಯಾಲೆಂಡರಿನಲ್ಲಿ ವಾರದ ದಿನವನ್ನು ತೋರಿಸು" msgstr "ಕ್ಯಾಲೆಂಡರಿನಲ್ಲಿ ವಾರದ ದಿನವನ್ನು ತೋರಿಸು"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16 #: ../data/org.gnome.shell.gschema.xml.in.in.h:14
msgid "If true, display the ISO week date in the calendar." msgid "If true, display the ISO week date in the calendar."
msgstr "true ಆದಲ್ಲಿ, ಕ್ಯಾಲೆಂಡರಿನಲ್ಲಿ ISO ವಾರದ ದಿನವನ್ನು ತೋರಿಸುತ್ತದೆ." msgstr "true ಆದಲ್ಲಿ, ಕ್ಯಾಲೆಂಡರಿನಲ್ಲಿ ISO ವಾರದ ದಿನವನ್ನು ತೋರಿಸುತ್ತದೆ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17 #: ../data/org.gnome.shell.gschema.xml.in.in.h:15
msgid "Keybinding to open the application menu" msgid "Keybinding to open the application menu"
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್" msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18 #: ../data/org.gnome.shell.gschema.xml.in.in.h:16
msgid "Keybinding to open the application menu." msgid "Keybinding to open the application menu."
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್." msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19 #: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid "Keybinding to toggle the visibility of the message tray" msgid "Keybinding to toggle the visibility of the message tray"
msgstr "ಸಂದೇಶ ಟ್ರೇಯ ಗೋಚರಿಕೆಯನ್ನು ಹೊರಳಿಸಲು ಕೀಬೈಂಡಿಂಗ್" msgstr ""
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
#, fuzzy
#| msgid "Keybinding to open the application menu."
msgid "Keybinding to toggle the visibility of the message tray."
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
#, fuzzy
#| msgid "Keybinding to open the application menu"
msgid "Keybinding to toggle the screen recorder"
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20 #: ../data/org.gnome.shell.gschema.xml.in.in.h:20
msgid "Keybinding to toggle the visibility of the message tray." #, fuzzy
msgstr "ಸಂದೇಶ ಟ್ರೇಯ ಗೋಚರಿಕೆಯನ್ನು ಹೊರಳಿಸಲು ಕೀಬೈಂಡಿಂಗ್." #| msgid "Keybinding to open the application menu."
msgid "Keybinding to start/stop the builtin screen recorder."
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21 #: ../data/org.gnome.shell.gschema.xml.in.in.h:21
msgid "Keybinding to toggle the screen recorder"
msgstr "ತೆರೆ ರೆಕಾರ್ಡರ್ ಅನ್ನು ಹೊರಳಿಸಲು ಕೀಬೈಂಡಿಂಗ್"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "Keybinding to start/stop the builtin screen recorder."
msgstr "ಒಳನಿರ್ಮಿತ ತೆರೆ ರೆಕಾರ್ಡರ್ ಅನ್ನು ಆರಂಭಿಸಲು/ನಿಲ್ಲಿಸಲು ಕೀಬೈಂಡಿಂಗ್."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "Which keyboard to use" msgid "Which keyboard to use"
msgstr "ಯಾವ ಕೀಲಿಮಣೆಯನ್ನು ಬಳಸಬೇಕಿದೆ" msgstr "ಯಾವ ಕೀಲಿಮಣೆಯನ್ನು ಬಳಸಬೇಕಿದೆ"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24 #: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "The type of keyboard to use." msgid "The type of keyboard to use."
msgstr "ಬಳಸಬೇಕಿರುವ ಕೀಲಿಮಣೆಯ ಬಗೆ." msgstr "ಬಳಸಬೇಕಿರುವ ಕೀಲಿಮಣೆಯ ಬಗೆ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25 #: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟುಗಳನ್ನು ರೆಕಾರ್ಡು ಮಾಡಲು ಬಳಸಲಾಗುವ ಫ್ರೇಮ್‌ದರಗಳು." msgstr "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟುಗಳನ್ನು ರೆಕಾರ್ಡು ಮಾಡಲು ಬಳಸಲಾಗುವ ಫ್ರೇಮ್‌ದರಗಳು."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26 #: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
@@ -203,11 +182,11 @@ msgstr ""
"ರೆಕಾರ್ಡು ಮಾಡಲಾದ " "ರೆಕಾರ್ಡು ಮಾಡಲಾದ "
"ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟಿನ ಫ್ರೇಮ್‌ದರ. " "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟಿನ ಫ್ರೇಮ್‌ದರ. "
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27 #: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟ್‍ ಅನ್ನು ಎನ್ಕೋಡ್ ಮಾಡಲು ಬಳಸಲಾಗುವ gstreamer ಪೈಪ್‌ಲೈನ್" msgstr "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟ್‍ ಅನ್ನು ಎನ್ಕೋಡ್ ಮಾಡಲು ಬಳಸಲಾಗುವ gstreamer ಪೈಪ್‌ಲೈನ್"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29 #: ../data/org.gnome.shell.gschema.xml.in.in.h:27
#, no-c-format #, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@@ -221,31 +200,12 @@ msgid ""
"threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is " "threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is "
"used as a placeholder for a guess at the optimal thread count on the system." "used as a placeholder for a guess at the optimal thread count on the system."
msgstr "" msgstr ""
"ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ಎನ್ಕೋಡ್ ಮಾಡಲು ಬಳಸಲಾದ GStreamer ಪೈಪ್‌ಲೈನ್‌ ಅನ್ನು "
"ಹೊಂದಿಸುತ್ತದೆ. ಇದು gst-"
"launch ನಲ್ಲಿ ಬಳಸಲಾದ ಸಿಂಟ್ಯಾಕ್ಸನ್ನು ಅನುಸರಿಸುತ್ತದೆ. ಪೈಪ್‌ಲೈನ್ ವಿಡಿಯೊವನ್ನು "
"ರೆಕಾರ್ಡು ಮಾಡಲು "
"ಒಂದು ನಿಯೋಜಿಸದೇ ಇರುವ ಸಿಂಕ್‌ಪ್ಯಾಡ್‌ಗೆ ಸಂಪರ್ಕಿತಗೊಂಡಿರಬೇಕು. ಇದು ಸಾಮಾನ್ಯವಾಗಿ "
"ಸಂಪರ್ಕಿತಗೊಂಡಿರದೆ ಇರುವ ಪೈಪ್‌ಲೈನ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ; ಆ ಪ್ಯಾಡ್‌ನಿಂದ ಔಟ್‌ಪುಟ್ "
"ಅನ್ನು ಔಟ್‌ಪುಟ್ "
"ಕಡತಕ್ಕೆ ಬರೆಯಲಾಗುತ್ತದೆ. ಆದರೆ ಪೈಪ್‌ಲೈನ್ ತನ್ನದೆ ಆದ ಔಟ್‌ಪುಟ್ ಅನ್ನು "
"ನೋಡಿಕೊಳ್ಳಬಲ್ಲದು - "
"shout2send ಅಥವ ಅದೇ ರೀತಿಯದರ ಮೂಲಕ icecast ಪೂರೈಕೆಗಣಕಕ್ಕೆ ಔಟ್‌ಪುಟ್ ಅನ್ನು ಕಳುಹಿಸಲು "
"ಇದನ್ನು ಬಳಸಬಹುದಾಗಿರುತ್ತದೆ. ಇದರ ಹೊಂದಿಕೆಯನ್ನು ರದ್ದುಗೊಳಿಸಿದಲ್ಲಿ ಅಥವ ಒಂದು ಖಾಲಿ "
"ಮೌಲ್ಯಕ್ಕೆ "
"ಹೊಂದಿಸಿದಲ್ಲಿ, ಪೂರ್ವನಿಯೋಜಿತ ಪೈಪ್‌ಲೈನ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ. ಇದು ಪ್ರಸ್ತುತ 'vp8enc "
"min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! "
"queue ! webmmux' ಆಗಿರುತ್ತದೆ ಮತ್ತು VP8 ಕೋಡೆಕ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು WEBM ಅನ್ನು "
"ರೆಕಾರ್ಡು "
"ಮಾಡುತ್ತದೆ. %T ಎನ್ನು ವ್ಯವಸ್ತೆಯಲ್ಲಿನ ಸೂಕ್ತವಾದ ಎಳೆಯ ಎಣಿಕೆಯನ್ನು ಊಹಿಸಲು ಒಂದು "
"ಪ್ಲೇಸ್‌ಹೋಲ್ಡರ್ "
"ಆಗಿ ಬಳಸಲಾಗುತ್ತದೆ."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30 #: ../data/org.gnome.shell.gschema.xml.in.in.h:28
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟುಗಳನ್ನು ಶೇಖರಿಸಿಡಲು ಬಳಸಲಾಗುವ ಕಡತ ವಿಸ್ತರಣೆಗಳು" msgstr "ಸ್ಕ್ರೀನ್‌ಕ್ಯಾಸ್ಟುಗಳನ್ನು ಶೇಖರಿಸಿಡಲು ಬಳಸಲಾಗುವ ಕಡತ ವಿಸ್ತರಣೆಗಳು"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31 #: ../data/org.gnome.shell.gschema.xml.in.in.h:29
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
@@ -262,6 +222,7 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "%s ಗಾಗಿ ಆದ್ಯತೆಗಳ ಸಂವಾದವನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ದೋಷ ಉಂಟಾಗಿದೆ:" msgstr "%s ಗಾಗಿ ಆದ್ಯತೆಗಳ ಸಂವಾದವನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ದೋಷ ಉಂಟಾಗಿದೆ:"
#: ../js/extensionPrefs/main.js:164 #: ../js/extensionPrefs/main.js:164
#| msgid "<b>Extension</b>"
msgid "Extension" msgid "Extension"
msgstr "ವಿಸ್ತರಣೆ" msgstr "ವಿಸ್ತರಣೆ"
@@ -270,11 +231,11 @@ msgid "Select an extension to configure using the combobox above."
msgstr "" msgstr ""
"ಮೇಲಿನ ಸಂಯೋಜನಾಚೌಕವನ್ನು ಬಳಸಿಕೊಂಡು ಸಂರಚಿಸಬೇಕಿರುವ ಒಂದು ವಿಸ್ತರಣೆಯನ್ನು ಆರಿಸಿ." "ಮೇಲಿನ ಸಂಯೋಜನಾಚೌಕವನ್ನು ಬಳಸಿಕೊಂಡು ಸಂರಚಿಸಬೇಕಿರುವ ಒಂದು ವಿಸ್ತರಣೆಯನ್ನು ಆರಿಸಿ."
#: ../js/gdm/loginDialog.js:529 #: ../js/gdm/loginDialog.js:526
msgid "Session..." msgid "Session..."
msgstr "ಅಧಿವೇಶನ..." msgstr "ಅಧಿವೇಶನ..."
#: ../js/gdm/loginDialog.js:680 #: ../js/gdm/loginDialog.js:674
msgctxt "title" msgctxt "title"
msgid "Sign In" msgid "Sign In"
msgstr "ಒಳ ಪ್ರವೇಶಿಸಿ" msgstr "ಒಳ ಪ್ರವೇಶಿಸಿ"
@@ -282,68 +243,55 @@ msgstr "ಒಳ ಪ್ರವೇಶಿಸಿ"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: ../js/gdm/loginDialog.js:740 #: ../js/gdm/loginDialog.js:741
msgid "Not listed?" msgid "Not listed?"
msgstr "ಪಟ್ಟಿಯಲ್ಲಿಲ್ಲವೆ?" msgstr "ಪಟ್ಟಿಯಲ್ಲಿಲ್ಲವೆ?"
#: ../js/gdm/loginDialog.js:898 ../js/ui/components/networkAgent.js:137 #: ../js/gdm/loginDialog.js:894 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373 #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396 #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:168 #: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:166
msgid "Cancel" msgid "Cancel"
msgstr "ರದ್ದು ಮಾಡು" msgstr "ರದ್ದು ಮಾಡು"
#: ../js/gdm/loginDialog.js:903 #: ../js/gdm/loginDialog.js:899
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "ಒಳಗೆ ಪ್ರವೇಶಿಸು" msgstr "ಒಳಗೆ ಪ್ರವೇಶಿಸು"
#. TTLS and PEAP are actually much more complicated, but this complication #: ../js/gdm/loginDialog.js:1238
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: ../js/gdm/loginDialog.js:962 ../js/ui/components/networkAgent.js:260
#: ../js/ui/components/networkAgent.js:278
msgid "Username: "
msgstr "ಬಳಕೆದಾರ ಹೆಸರು: "
#: ../js/gdm/loginDialog.js:1269
msgid "Login Window" msgid "Login Window"
msgstr "ಪ್ರವೇಶದ ಕಿಟಕಿ" msgstr "ಪ್ರವೇಶದ ಕಿಟಕಿ"
#. Translators: accessible name of the power menu in the login screen #: ../js/gdm/powerMenu.js:88 ../js/ui/userMenu.js:658 ../js/ui/userMenu.js:662
#: ../js/gdm/powerMenu.js:35 #: ../js/ui/userMenu.js:773
#| msgid "Power Off"
msgid "Power"
msgstr "ವಿದ್ಯುಚ್ಛಕ್ತಿ"
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:664 ../js/ui/userMenu.js:668
#: ../js/ui/userMenu.js:779
msgid "Suspend" msgid "Suspend"
msgstr "ಅಮಾನತ್ತಿನಲ್ಲಿಡು" msgstr "ಅಮಾನತ್ತಿನಲ್ಲಿಡು"
#: ../js/gdm/powerMenu.js:94 #: ../js/gdm/powerMenu.js:93
msgid "Restart" msgid "Restart"
msgstr "ಮರಳಿ ಆರಂಭಿಸು" msgstr "ಮರಳಿ ಆರಂಭಿಸು"
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:666 ../js/ui/userMenu.js:668 #: ../js/gdm/powerMenu.js:98 ../js/ui/userMenu.js:660 ../js/ui/userMenu.js:662
#: ../js/ui/userMenu.js:778 #: ../js/ui/userMenu.js:772
msgid "Power Off" msgid "Power Off"
msgstr "ಸ್ಥಗಿತಗೊಳಿಸು" msgstr "ಸ್ಥಗಿತಗೊಳಿಸು"
#: ../js/gdm/util.js:152 #: ../js/gdm/util.js:148
#| msgid "Authentication Required"
msgid "Authentication error" msgid "Authentication error"
msgstr "ದೃಢೀಕರಣ ದೋಷ" msgstr "ದೃಢೀಕರಣ ದೋಷ"
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:269 #: ../js/gdm/util.js:265
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(ಅಥವ ನಿಮ್ಮ ಬೆರಳನ್ನು ಉಜ್ಜಿ)" msgstr "(ಅಥವ ನಿಮ್ಮ ಬೆರಳನ್ನು ಉಜ್ಜಿ)"
#: ../js/gdm/util.js:294 #: ../js/gdm/util.js:290
#, c-format #, c-format
msgid "(e.g., user or %s)" msgid "(e.g., user or %s)"
msgstr "(ಉದಾ., ಬಳಕೆದಾರ ಅಥವ %s)" msgstr ""
#: ../js/misc/util.js:92 #: ../js/misc/util.js:92
msgid "Command not found" msgid "Command not found"
@@ -377,7 +325,7 @@ msgstr "SETTINGS"
msgid "New Window" msgid "New Window"
msgstr "ಹೊಸ ವಿಂಡೊ" msgstr "ಹೊಸ ವಿಂಡೊ"
#: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:290 #: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:271
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "ಎಲ್ಲಾ ಅಚ್ಚುಮೆಚ್ಚಿನವುಗಳನ್ನು ತೆಗೆದುಹಾಕು" msgstr "ಎಲ್ಲಾ ಅಚ್ಚುಮೆಚ್ಚಿನವುಗಳನ್ನು ತೆಗೆದುಹಾಕು"
@@ -541,16 +489,16 @@ msgstr "ಈ ವಾರ"
msgid "Next week" msgid "Next week"
msgstr "ಮುಂದಿನ ವಾರ" msgstr "ಮುಂದಿನ ವಾರ"
#: ../js/ui/components/autorunManager.js:297 #: ../js/ui/components/autorunManager.js:278
msgid "Removable Devices" msgid "Removable Devices"
msgstr "ತೆಗೆದುಹಾಕಬಹುದಾದ ಸಾಧನಗಳು" msgstr "ತೆಗೆದುಹಾಕಬಹುದಾದ ಸಾಧನಗಳು"
#: ../js/ui/components/autorunManager.js:594 #: ../js/ui/components/autorunManager.js:575
#, c-format #, c-format
msgid "Open with %s" msgid "Open with %s"
msgstr "%s ನೊಂದಿಗೆ ತೆರೆ" msgstr "%s ನೊಂದಿಗೆ ತೆರೆ"
#: ../js/ui/components/autorunManager.js:620 #: ../js/ui/components/autorunManager.js:601
msgid "Eject" msgid "Eject"
msgstr "ಹೊರತಳ್ಳು" msgstr "ಹೊರತಳ್ಳು"
@@ -580,6 +528,14 @@ msgstr "ದಾಟುಪದ: "
msgid "Key: " msgid "Key: "
msgstr "ಕೀಲಿ: " msgstr "ಕೀಲಿ: "
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: ../js/ui/components/networkAgent.js:260
#: ../js/ui/components/networkAgent.js:278
msgid "Username: "
msgstr "ಬಳಕೆದಾರ ಹೆಸರು: "
#: ../js/ui/components/networkAgent.js:266 #: ../js/ui/components/networkAgent.js:266
msgid "Identity: " msgid "Identity: "
msgstr "ಗುರುತು: " msgstr "ಗುರುತು: "
@@ -690,7 +646,7 @@ msgstr "ಸಂಪರ್ಕ ದೋಷ"
#: ../js/ui/components/telepathyClient.js:491 #: ../js/ui/components/telepathyClient.js:491
msgid "Unmute" msgid "Unmute"
msgstr "ಮಾತುಬರಿಸು" msgstr ""
#: ../js/ui/components/telepathyClient.js:491 #: ../js/ui/components/telepathyClient.js:491
msgid "Mute" msgid "Mute"
@@ -699,35 +655,35 @@ msgstr "ಮೂಕಗೊಳಿಸು"
#. Translators: this is a time format string followed by a date. #. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your #. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds. #. locale, without seconds.
#: ../js/ui/components/telepathyClient.js:952 #: ../js/ui/components/telepathyClient.js:948
#, no-c-format #, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>" msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "<b>%A</b> ರಂದು <b>%X</b> ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ" msgstr "<b>%A</b> ರಂದು <b>%X</b> ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ"
#. Translators: this is a time format in the style of "Wednesday, May 25", #. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year. #. shown when you get a chat message in the same year.
#: ../js/ui/components/telepathyClient.js:958 #: ../js/ui/components/telepathyClient.js:954
#, no-c-format #, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>" msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "<b>%A</b>, <b>%B %d</b> ರಂದು ಕಳುಹಿಸಲಾಗಿದೆ" msgstr "<b>%A</b>, <b>%B %d</b> ರಂದು ಕಳುಹಿಸಲಾಗಿದೆ"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012", #. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year. #. shown when you get a chat message in a different year.
#: ../js/ui/components/telepathyClient.js:963 #: ../js/ui/components/telepathyClient.js:959
#, no-c-format #, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y" msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "%A</b>, <b>%B %d</b>, %Y ರಂದು ಕಳುಹಿಸಲಾಗಿದೆ" msgstr "%A</b>, <b>%B %d</b>, %Y ರಂದು ಕಳುಹಿಸಲಾಗಿದೆ"
#. Translators: this is the other person changing their old IM name to their new #. Translators: this is the other person changing their old IM name to their new
#. IM name. #. IM name.
#: ../js/ui/components/telepathyClient.js:992 #: ../js/ui/components/telepathyClient.js:988
#, c-format #, c-format
msgid "%s is now known as %s" msgid "%s is now known as %s"
msgstr "%s ಈಗ %s ಆಗಿದ್ದಾರೆ" msgstr "%s ಈಗ %s ಆಗಿದ್ದಾರೆ"
#. translators: argument is a room name like #. translators: argument is a room name like
#. * room@jabber.org for example. #. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1092 #: ../js/ui/components/telepathyClient.js:1088
#, c-format #, c-format
msgid "Invitation to %s" msgid "Invitation to %s"
msgstr "%s ಗಾಗಿನ ಆಹ್ವಾನ" msgstr "%s ಗಾಗಿನ ಆಹ್ವಾನ"
@@ -735,42 +691,42 @@ msgstr "%s ಗಾಗಿನ ಆಹ್ವಾನ"
#. translators: first argument is the name of a contact and the second #. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org #. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example. #. * for example.
#: ../js/ui/components/telepathyClient.js:1100 #: ../js/ui/components/telepathyClient.js:1096
#, c-format #, c-format
msgid "%s is inviting you to join %s" msgid "%s is inviting you to join %s"
msgstr "%s ನಿಮ್ಮನ್ನು %s ಗೆ ಸೇರುವಂತೆ ಆಹ್ವಾನಿಸುತ್ತಿದ್ದಾರೆ" msgstr "%s ನಿಮ್ಮನ್ನು %s ಗೆ ಸೇರುವಂತೆ ಆಹ್ವಾನಿಸುತ್ತಿದ್ದಾರೆ"
#: ../js/ui/components/telepathyClient.js:1102 #: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1181 #: ../js/ui/components/telepathyClient.js:1177
#: ../js/ui/components/telepathyClient.js:1244 #: ../js/ui/components/telepathyClient.js:1240
msgid "Decline" msgid "Decline"
msgstr "ತಿರಸ್ಕರಿಸು" msgstr "ತಿರಸ್ಕರಿಸು"
#: ../js/ui/components/telepathyClient.js:1103 #: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1182 #: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1245 #: ../js/ui/components/telepathyClient.js:1241
msgid "Accept" msgid "Accept"
msgstr "ಅಂಗೀಕರಿಸು" msgstr "ಅಂಗೀಕರಿಸು"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1133 #: ../js/ui/components/telepathyClient.js:1129
#, c-format #, c-format
msgid "Video call from %s" msgid "Video call from %s"
msgstr "%s ಇಂದ ವೀಡಿಯೊ ಕರೆ ಬಂದಿದೆ" msgstr "%s ಇಂದ ವೀಡಿಯೊ ಕರೆ ಬಂದಿದೆ"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1136 #: ../js/ui/components/telepathyClient.js:1132
#, c-format #, c-format
msgid "Call from %s" msgid "Call from %s"
msgstr "%s ಇಂದ ಕರೆ ಬಂದಿದೆ" msgstr "%s ಇಂದ ಕರೆ ಬಂದಿದೆ"
#: ../js/ui/components/telepathyClient.js:1141 #: ../js/ui/components/telepathyClient.js:1137
#: ../js/ui/status/bluetooth.js:346 #: ../js/ui/status/bluetooth.js:346
msgid "Reject" msgid "Reject"
msgstr "ತಿರಸ್ಕರಿಸು" msgstr "ತಿರಸ್ಕರಿಸು"
#. translators: this is a button label (verb), not a noun #. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1143 #: ../js/ui/components/telepathyClient.js:1139
msgid "Answer" msgid "Answer"
msgstr "ಉತ್ತರ" msgstr "ಉತ್ತರ"
@@ -779,106 +735,106 @@ msgstr "ಉತ್ತರ"
#. * file name. The string will be something #. * file name. The string will be something
#. * like: "Alice is sending you test.ogg" #. * like: "Alice is sending you test.ogg"
#. #.
#: ../js/ui/components/telepathyClient.js:1175 #: ../js/ui/components/telepathyClient.js:1171
#, c-format #, c-format
msgid "%s is sending you %s" msgid "%s is sending you %s"
msgstr "%s ರವರು ನಿಮಗೆ %s ಅನ್ನು ಕಳುಹಿಸುತ್ತಿದ್ದಾರೆ" msgstr "%s ರವರು ನಿಮಗೆ %s ಅನ್ನು ಕಳುಹಿಸುತ್ತಿದ್ದಾರೆ"
#. To translators: The parameter is the contact's alias #. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1210 #: ../js/ui/components/telepathyClient.js:1206
#, c-format #, c-format
msgid "%s would like permission to see when you are online" msgid "%s would like permission to see when you are online"
msgstr "" msgstr ""
"ನೀವು ಯಾವಾಗ ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಇರುತ್ತೀರಿ ಎಂದು ತಿಳಿಯಲು %s ರವರು ನಿಮ್ಮ ಅನುಮತಿಯನ್ನು " "ನೀವು ಯಾವಾಗ ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಇರುತ್ತೀರಿ ಎಂದು ತಿಳಿಯಲು %s ರವರು ನಿಮ್ಮ ಅನುಮತಿಯನ್ನು "
"ಕೋರಿದ್ದಾರೆ" "ಕೋರಿದ್ದಾರೆ"
#: ../js/ui/components/telepathyClient.js:1302 #: ../js/ui/components/telepathyClient.js:1298
msgid "Network error" msgid "Network error"
msgstr "ಜಾಲಬಂಧದ ದೋಷ" msgstr "ಜಾಲಬಂಧದ ದೋಷ"
#: ../js/ui/components/telepathyClient.js:1304 #: ../js/ui/components/telepathyClient.js:1300
msgid "Authentication failed" msgid "Authentication failed"
msgstr "ದೃಢೀಕರಣವು ವಿಫಲಗೊಂಡಿದೆ" msgstr "ದೃಢೀಕರಣವು ವಿಫಲಗೊಂಡಿದೆ"
#: ../js/ui/components/telepathyClient.js:1306 #: ../js/ui/components/telepathyClient.js:1302
msgid "Encryption error" msgid "Encryption error"
msgstr "ಗೂಢಲಿಪೀಕರಣ ದೋಷ" msgstr "ಗೂಢಲಿಪೀಕರಣ ದೋಷ"
#: ../js/ui/components/telepathyClient.js:1308 #: ../js/ui/components/telepathyClient.js:1304
msgid "Certificate not provided" msgid "Certificate not provided"
msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ" msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1310 #: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate untrusted" msgid "Certificate untrusted"
msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ನಂಬಲಾಗಿಲ್ಲ" msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ನಂಬಲಾಗಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1312 #: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate expired" msgid "Certificate expired"
msgstr "ಪ್ರಮಾಣಪತ್ರದ ಕಾಲಾವಧಿ ತೀರಿದೆ" msgstr "ಪ್ರಮಾಣಪತ್ರದ ಕಾಲಾವಧಿ ತೀರಿದೆ"
#: ../js/ui/components/telepathyClient.js:1314 #: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate not activated" msgid "Certificate not activated"
msgstr "ಪ್ರಮಾಣಪತ್ರವು ಸಕ್ರಿಯಗೊಂಡಿಲ್ಲ" msgstr "ಪ್ರಮಾಣಪತ್ರವು ಸಕ್ರಿಯಗೊಂಡಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1316 #: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate hostname mismatch" msgid "Certificate hostname mismatch"
msgstr "ಪ್ರಮಾಣಪತ್ರದ ಅತಿಥೇಯದ ಹೆಸರು ತಾಳೆಯಾಗುತ್ತಿಲ್ಲ" msgstr "ಪ್ರಮಾಣಪತ್ರದ ಅತಿಥೇಯದ ಹೆಸರು ತಾಳೆಯಾಗುತ್ತಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1318 #: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate fingerprint mismatch" msgid "Certificate fingerprint mismatch"
msgstr "ಪ್ರಮಾಣಪತ್ರದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ತಾಳೆಯಾಗುತ್ತಿಲ್ಲ" msgstr "ಪ್ರಮಾಣಪತ್ರದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ತಾಳೆಯಾಗುತ್ತಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1320 #: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate self-signed" msgid "Certificate self-signed"
msgstr "ಪ್ರಮಾಣಪತ್ರವು ಸ್ವತಃ ಸೈನ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ" msgstr "ಪ್ರಮಾಣಪತ್ರವು ಸ್ವತಃ ಸೈನ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ"
#: ../js/ui/components/telepathyClient.js:1322 #: ../js/ui/components/telepathyClient.js:1318
msgid "Status is set to offline" msgid "Status is set to offline"
msgstr "ಸ್ಥಿತಿಯನ್ನು ಆಫ್‌ಲೈನ್‌ ಎಂದು ಸೂಚಿಸಿದ್ದಾರೆ." msgstr "ಸ್ಥಿತಿಯನ್ನು ಆಫ್‌ಲೈನ್‌ ಎಂದು ಸೂಚಿಸಿದ್ದಾರೆ."
#: ../js/ui/components/telepathyClient.js:1324 #: ../js/ui/components/telepathyClient.js:1320
msgid "Encryption is not available" msgid "Encryption is not available"
msgstr "ಗೂಢಲಿಪೀಕರಣ ಲಭ್ಯವಿಲ್ಲ" msgstr "ಗೂಢಲಿಪೀಕರಣ ಲಭ್ಯವಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1326 #: ../js/ui/components/telepathyClient.js:1322
msgid "Certificate is invalid" msgid "Certificate is invalid"
msgstr "ಪ್ರಮಾಣಪತ್ರವು ಅಮಾನ್ಯವಾಗಿದೆ" msgstr "ಪ್ರಮಾಣಪತ್ರವು ಅಮಾನ್ಯವಾಗಿದೆ"
#: ../js/ui/components/telepathyClient.js:1328 #: ../js/ui/components/telepathyClient.js:1324
msgid "Connection has been refused" msgid "Connection has been refused"
msgstr "ಸಂಪರ್ಕವನ್ನು ನಿರಾಕರಿಸಲಾಗಿದೆ" msgstr "ಸಂಪರ್ಕವನ್ನು ನಿರಾಕರಿಸಲಾಗಿದೆ"
#: ../js/ui/components/telepathyClient.js:1330 #: ../js/ui/components/telepathyClient.js:1326
msgid "Connection can't be established" msgid "Connection can't be established"
msgstr "ಸಂಪರ್ಕವನ್ನು ಸಾಧಿಸಲಾಗಿಲ್ಲ" msgstr "ಸಂಪರ್ಕವನ್ನು ಸಾಧಿಸಲಾಗಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1332 #: ../js/ui/components/telepathyClient.js:1328
msgid "Connection has been lost" msgid "Connection has been lost"
msgstr "ಸಂಪರ್ಕವು ಕಡಿದು ಹೋಗಿದೆ" msgstr "ಸಂಪರ್ಕವು ಕಡಿದು ಹೋಗಿದೆ"
#: ../js/ui/components/telepathyClient.js:1334 #: ../js/ui/components/telepathyClient.js:1330
msgid "This account is already connected to the server" msgid "This account is already connected to the server"
msgstr "ಈ ಖಾತೆಯು ಈಗಾಗಲೆ ಪರಿಚಾರಕದೊಂದಿಗೆ ಸಂಪರ್ಕ ಜೋಡಿಸಲಾಗಿದೆ" msgstr "ಈ ಖಾತೆಯು ಈಗಾಗಲೆ ಪರಿಚಾರಕದೊಂದಿಗೆ ಸಂಪರ್ಕ ಜೋಡಿಸಲಾಗಿದೆ"
#: ../js/ui/components/telepathyClient.js:1336 #: ../js/ui/components/telepathyClient.js:1332
msgid "" msgid ""
"Connection has been replaced by a new connection using the same resource" "Connection has been replaced by a new connection using the same resource"
msgstr "" msgstr ""
"ಒಂದು ಹೊಸ ಸಂಪರ್ಕದಿಂದ ಈ ಸಂಪರ್ಕವನ್ನು ಇದೇ ಸಂಪನ್ಮೂಲವನ್ನು ಬಳಸಿಕೊಂಡು ಬದಲಾಯಿಸಲಾಗಿದೆ" "ಒಂದು ಹೊಸ ಸಂಪರ್ಕದಿಂದ ಈ ಸಂಪರ್ಕವನ್ನು ಇದೇ ಸಂಪನ್ಮೂಲವನ್ನು ಬಳಸಿಕೊಂಡು ಬದಲಾಯಿಸಲಾಗಿದೆ"
#: ../js/ui/components/telepathyClient.js:1338 #: ../js/ui/components/telepathyClient.js:1334
msgid "The account already exists on the server" msgid "The account already exists on the server"
msgstr "ಖಾತೆಯು ಈಗಾಗಲೆ ಪರಿಚಾರಕದಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ" msgstr "ಖಾತೆಯು ಈಗಾಗಲೆ ಪರಿಚಾರಕದಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ"
#: ../js/ui/components/telepathyClient.js:1340 #: ../js/ui/components/telepathyClient.js:1336
msgid "Server is currently too busy to handle the connection" msgid "Server is currently too busy to handle the connection"
msgstr "ಪರಿಚಾರಕಕ್ಕೆ ಬಿಡುವಿಲ್ಲದ ಕಾರಣ ಸಂಪರ್ಕವನ್ನು ನಿಭಾಯಿಸಲಾಗುತ್ತಿಲ್ಲ" msgstr "ಪರಿಚಾರಕಕ್ಕೆ ಬಿಡುವಿಲ್ಲದ ಕಾರಣ ಸಂಪರ್ಕವನ್ನು ನಿಭಾಯಿಸಲಾಗುತ್ತಿಲ್ಲ"
#: ../js/ui/components/telepathyClient.js:1342 #: ../js/ui/components/telepathyClient.js:1338
msgid "Certificate has been revoked" msgid "Certificate has been revoked"
msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ಹಿಂದಕ್ಕೆ ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ" msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ಹಿಂದಕ್ಕೆ ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ"
#: ../js/ui/components/telepathyClient.js:1344 #: ../js/ui/components/telepathyClient.js:1340
msgid "" msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak" "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "" msgstr ""
@@ -886,7 +842,7 @@ msgstr ""
"ಗೂಢಲಿಪೀಕರಣವನ್ನು " "ಗೂಢಲಿಪೀಕರಣವನ್ನು "
"ಹೊಂದಿದೆ" "ಹೊಂದಿದೆ"
#: ../js/ui/components/telepathyClient.js:1346 #: ../js/ui/components/telepathyClient.js:1342
msgid "" msgid ""
"The length of the server certificate, or the depth of the server certificate " "The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library" "chain, exceed the limits imposed by the cryptography library"
@@ -895,30 +851,31 @@ msgstr ""
"ಲೈಬ್ರರಿಯಿಂದ " "ಲೈಬ್ರರಿಯಿಂದ "
"ನಿಗದಿ ಪಡಿಸಲಾದ ಮಿತಿಗಳನ್ನು ಮೀರಿದೆ." "ನಿಗದಿ ಪಡಿಸಲಾದ ಮಿತಿಗಳನ್ನು ಮೀರಿದೆ."
#: ../js/ui/components/telepathyClient.js:1348 #: ../js/ui/components/telepathyClient.js:1344
msgid "Internal error" msgid "Internal error"
msgstr "ಆಂತರಿಕ ತಪ್ಪು" msgstr "ಆಂತರಿಕ ತಪ್ಪು"
#. translators: argument is the account name, like #. translators: argument is the account name, like
#. * name@jabber.org for example. #. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1358 #: ../js/ui/components/telepathyClient.js:1354
#, c-format #, c-format
msgid "Connection to %s failed" msgid "Connection to %s failed"
msgstr "%s ಗಾಗಿನ ಸಂಪರ್ಕವು ವಿಫಲಗೊಂಡಿದೆ" msgstr "%s ಗಾಗಿನ ಸಂಪರ್ಕವು ವಿಫಲಗೊಂಡಿದೆ"
#: ../js/ui/components/telepathyClient.js:1367 #: ../js/ui/components/telepathyClient.js:1363
msgid "Reconnect" msgid "Reconnect"
msgstr "ಮರಳಿ ಸಂಪರ್ಕ ಜೋಡಿಸು" msgstr "ಮರಳಿ ಸಂಪರ್ಕ ಜೋಡಿಸು"
#: ../js/ui/components/telepathyClient.js:1368 #: ../js/ui/components/telepathyClient.js:1364
msgid "Edit account" msgid "Edit account"
msgstr "ಖಾತೆಯನ್ನು ಸಂಪಾದಿಸು" msgstr "ಖಾತೆಯನ್ನು ಸಂಪಾದಿಸು"
#: ../js/ui/components/telepathyClient.js:1413 #: ../js/ui/components/telepathyClient.js:1409
msgid "Unknown reason" msgid "Unknown reason"
msgstr "ಅಜ್ಞಾತ ಕಾರಣ" msgstr "ಅಜ್ಞಾತ ಕಾರಣ"
#: ../js/ui/dash.js:254 ../js/ui/dash.js:292 #: ../js/ui/dash.js:245 ../js/ui/dash.js:273
#| msgid "Applications"
msgid "Show Applications" msgid "Show Applications"
msgstr "ಅನ್ವಯಗಳನ್ನು ತೋರಿಸು" msgstr "ಅನ್ವಯಗಳನ್ನು ತೋರಿಸು"
@@ -926,14 +883,14 @@ msgstr "ಅನ್ವಯಗಳನ್ನು ತೋರಿಸು"
msgid "Date and Time Settings" msgid "Date and Time Settings"
msgstr "ದಿನಾಂಕ ಹಾಗು ಸಮಯದ ಸಿದ್ಧತೆಗಳು" msgstr "ದಿನಾಂಕ ಹಾಗು ಸಮಯದ ಸಿದ್ಧತೆಗಳು"
#: ../js/ui/dateMenu.js:111 #: ../js/ui/dateMenu.js:109
msgid "Open Calendar" msgid "Open Calendar"
msgstr "ಕ್ಯಾಲೆಂಡರನ್ನು ತೆರೆ" msgstr "ಕ್ಯಾಲೆಂಡರನ್ನು ತೆರೆ"
#. Translators: This is the date format to use when the calendar popup is #. 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"). #. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. #.
#: ../js/ui/dateMenu.js:201 #: ../js/ui/dateMenu.js:175
msgid "%A %B %e, %Y" msgid "%A %B %e, %Y"
msgstr "%A %B %e, %Y" msgstr "%A %B %e, %Y"
@@ -1038,11 +995,11 @@ msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "" msgstr ""
"'%s' ಅನ್ನು extensions.gnome.org ಇಂದ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿಕೊಂಡು ಅನುಸ್ಥಾಪಿಸಬೇಕೆ?" "'%s' ಅನ್ನು extensions.gnome.org ಇಂದ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿಕೊಂಡು ಅನುಸ್ಥಾಪಿಸಬೇಕೆ?"
#: ../js/ui/keyboard.js:337 #: ../js/ui/keyboard.js:327
msgid "tray" msgid "tray"
msgstr "ಟ್ರೇ" msgstr "ಟ್ರೇ"
#: ../js/ui/keyboard.js:584 ../js/ui/status/keyboard.js:195 #: ../js/ui/keyboard.js:561 ../js/ui/status/keyboard.js:194
#: ../js/ui/status/power.js:205 #: ../js/ui/status/power.js:205
msgid "Keyboard" msgid "Keyboard"
msgstr "ಕೀಲಿಮಣೆ" msgstr "ಕೀಲಿಮಣೆ"
@@ -1095,23 +1052,24 @@ msgstr "ಆಕರವನ್ನು ನೋಡಿ"
msgid "Web Page" msgid "Web Page"
msgstr "ಜಾಲ ಪುಟ" msgstr "ಜಾಲ ಪುಟ"
#: ../js/ui/messageTray.js:1084 #: ../js/ui/messageTray.js:1080
msgid "Open" msgid "Open"
msgstr "ತೆರೆ" msgstr "ತೆರೆ"
#: ../js/ui/messageTray.js:1091 #: ../js/ui/messageTray.js:1087
msgid "Remove" msgid "Remove"
msgstr "ತೆಗೆದು ಹಾಕು" msgstr "ತೆಗೆದು ಹಾಕು"
#: ../js/ui/messageTray.js:1531 #: ../js/ui/messageTray.js:2052
msgid "Message Tray" msgid "Message Tray"
msgstr "ಸಂದೇಶ ಟ್ರೇ" msgstr ""
#: ../js/ui/messageTray.js:2543 #: ../js/ui/messageTray.js:2508
msgid "System Information" msgid "System Information"
msgstr "ವ್ಯವಸ್ಥೆಯ ಮಾಹಿತಿ" msgstr "ವ್ಯವಸ್ಥೆಯ ಮಾಹಿತಿ"
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374 #: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:373
#| msgid "Unknown"
msgctxt "program" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "ಗೊತ್ತಿಲ್ಲದ" msgstr "ಗೊತ್ತಿಲ್ಲದ"
@@ -1167,29 +1125,33 @@ msgstr "ದಯವಿಟ್ಟು ಒಂದು ಆಜ್ಞೆಯನ್ನು ನ
#. Translators: This is a time format for a date in #. Translators: This is a time format for a date in
#. long format #. long format
#: ../js/ui/screenShield.js:81 #: ../js/ui/screenShield.js:79
#| msgctxt "calendar heading"
#| msgid "%A, %B %d"
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%A, %B %d" msgstr "%A, %B %d"
#: ../js/ui/screenShield.js:145 #: ../js/ui/screenShield.js:144
#, c-format #, c-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
msgstr[0] "%d ಹೊಸ ಸಂದೇಶ" msgstr[0] ""
msgstr[1] "%d ಹೊಸ ಸಂದೇಶಗಳು" msgstr[1] ""
#: ../js/ui/screenShield.js:147 #: ../js/ui/screenShield.js:146
#, c-format #, fuzzy, c-format
#| msgid "Notifications"
msgid "%d new notification" msgid "%d new notification"
msgid_plural "%d new notifications" msgid_plural "%d new notifications"
msgstr[0] "%d ಹೊಸ ಸೂಚನೆ" msgstr[0] "ಸೂಚನೆಗಳು"
msgstr[1] "%d ಹೊಸ ಸೂಚನೆಗಳು" msgstr[1] "ಸೂಚನೆಗಳು"
#: ../js/ui/searchDisplay.js:275 #: ../js/ui/searchDisplay.js:275
msgid "Searching..." msgid "Searching..."
msgstr "ಹುಡುಕಲಾಗುತ್ತಿದೆ..." msgstr "ಹುಡುಕಲಾಗುತ್ತಿದೆ..."
#: ../js/ui/searchDisplay.js:323 #: ../js/ui/searchDisplay.js:323
#| msgid "No matching results."
msgid "No results." msgid "No results."
msgstr "ಯಾವುದೆ ಫಲಿತಾಂಶಗಳಿಲ್ಲ." msgstr "ಯಾವುದೆ ಫಲಿತಾಂಶಗಳಿಲ್ಲ."
@@ -1210,16 +1172,18 @@ msgid "Hide Text"
msgstr "ಪಠ್ಯವನ್ನು ಅಡಗಿಸು" msgstr "ಪಠ್ಯವನ್ನು ಅಡಗಿಸು"
#: ../js/ui/shellMountOperation.js:368 #: ../js/ui/shellMountOperation.js:368
#| msgid "Password:"
msgid "Password" msgid "Password"
msgstr "ಗುಪ್ತಪದ" msgstr "ಗುಪ್ತಪದ"
#: ../js/ui/shellMountOperation.js:389 #: ../js/ui/shellMountOperation.js:389
#| msgid "Password:"
msgid "Remember Password" msgid "Remember Password"
msgstr "ಈ ಗುಪ್ತಪದವನ್ನು ನೆನಪಿನಲ್ಲಿಡು" msgstr "ಈ ಗುಪ್ತಪದವನ್ನು ನೆನಪಿನಲ್ಲಿಡು"
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:171 #: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:169
msgid "Unlock" msgid "Unlock"
msgstr "ಅನ್‌ಲಾಕ್ ಮಾಡು" msgstr ""
#: ../js/ui/status/accessibility.js:39 #: ../js/ui/status/accessibility.js:39
msgid "Accessibility" msgid "Accessibility"
@@ -1335,7 +1299,7 @@ msgstr "ಕೀಲಿಮಣೆ ಸಿದ್ಧತೆಗಳು"
msgid "Mouse Settings" msgid "Mouse Settings"
msgstr "ಮೌಸ್‌ನ ಸಿದ್ಧತೆಗಳು" msgstr "ಮೌಸ್‌ನ ಸಿದ್ಧತೆಗಳು"
#: ../js/ui/status/bluetooth.js:269 ../js/ui/status/volume.js:234 #: ../js/ui/status/bluetooth.js:269 ../js/ui/status/volume.js:236
msgid "Sound Settings" msgid "Sound Settings"
msgstr "ಧ್ವನಿಯ ಸಿದ್ಧತೆಗಳು" msgstr "ಧ್ವನಿಯ ಸಿದ್ಧತೆಗಳು"
@@ -1368,10 +1332,10 @@ msgid "Device %s wants to pair with this computer"
msgstr "%s ಎನ್ನುವ ಸಾಧನದೊಂದಿಗೆ ಸಂಪರ್ಕ ಜೋಡಿಸಲು ಬಯಸುತ್ತಿದೆ" msgstr "%s ಎನ್ನುವ ಸಾಧನದೊಂದಿಗೆ ಸಂಪರ್ಕ ಜೋಡಿಸಲು ಬಯಸುತ್ತಿದೆ"
#: ../js/ui/status/bluetooth.js:379 #: ../js/ui/status/bluetooth.js:379
#, c-format #, fuzzy, c-format
#| msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgid "Please confirm whether the PIN '%06d' matches the one on the device." msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "" msgstr "'%s' ಎನ್ನುವ PIN ಸಾಧನದಲ್ಲಿರುವುದಕ್ಕೆ ತಾಳೆಯಾಗುತ್ತದೆಯೆ ಎಂದು ಖಚಿತಪಡಿಸಿ."
"'%06d' ಎಂಬ PIN ಸಾಧನದಲ್ಲಿರುವುದಕ್ಕೆ ತಾಳೆಯಾಗುತ್ತದೆಯೆ ಎಂದು ದಯವಿಟ್ಟು ಖಚಿತಪಡಿಸಿ."
#: ../js/ui/status/bluetooth.js:381 #: ../js/ui/status/bluetooth.js:381
msgid "Matches" msgid "Matches"
@@ -1394,17 +1358,17 @@ msgstr "ದಯವಿಟ್ಟು ಸಾಧನದಲ್ಲಿ ಸೂಚಿಸಿ
msgid "OK" msgid "OK"
msgstr "ಸರಿ" msgstr "ಸರಿ"
#: ../js/ui/status/keyboard.js:228 #: ../js/ui/status/keyboard.js:227
msgid "Show Keyboard Layout" msgid "Show Keyboard Layout"
msgstr "ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸವನ್ನು ತೋರಿಸು" msgstr "ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸವನ್ನು ತೋರಿಸು"
#: ../js/ui/status/keyboard.js:233 #: ../js/ui/status/keyboard.js:232
msgid "Region and Language Settings" msgid "Region and Language Settings"
msgstr "ಪ್ರದೇಶ ಮತ್ತು ಭಾಷೆ ಸಿದ್ಧತೆಗಳು" msgstr "ಪ್ರದೇಶ ಮತ್ತು ಭಾಷೆ ಸಿದ್ಧತೆಗಳು"
#: ../js/ui/status/lockScreenMenu.js:18 #: ../js/ui/status/lockScreenMenu.js:18
msgid "Volume, network, battery" msgid "Volume, network, battery"
msgstr "ಧ್ವನಿಪ್ರಮಾಣ, ಜಾಲಬಂಧ, ಬ್ಯಾಟರಿ" msgstr ""
#: ../js/ui/status/network.js:94 #: ../js/ui/status/network.js:94
msgid "<unknown>" msgid "<unknown>"
@@ -1616,12 +1580,13 @@ msgid "Computer"
msgstr "ಗಣಕ" msgstr "ಗಣಕ"
#: ../js/ui/status/power.js:217 #: ../js/ui/status/power.js:217
#| msgid "Unknown"
msgctxt "device" msgctxt "device"
msgid "Unknown" msgid "Unknown"
msgstr "ಗೊತ್ತಿಲ್ಲದ" msgstr "ಗೊತ್ತಿಲ್ಲದ"
#. Translators: This is the label for audio volume #. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:47 ../js/ui/status/volume.js:221 #: ../js/ui/status/volume.js:47 ../js/ui/status/volume.js:223
msgid "Volume" msgid "Volume"
msgstr "ಧ್ವನಿ ಪ್ರಮಾಣ" msgstr "ಧ್ವನಿ ಪ್ರಮಾಣ"
@@ -1629,71 +1594,75 @@ msgstr "ಧ್ವನಿ ಪ್ರಮಾಣ"
msgid "Microphone" msgid "Microphone"
msgstr "ಮೈಕ್ರೊಫೋನ್" msgstr "ಮೈಕ್ರೊಫೋನ್"
#: ../js/ui/unlockDialog.js:178 #: ../js/ui/unlockDialog.js:176
msgid "Log in as another user" msgid "Log in as another user"
msgstr "ಇನ್ನೊಬ್ಬ ಬಳಕೆದಾರನಾಗಿ ಪ್ರವೇಶಿಸಿ" msgstr ""
#: ../js/ui/userMenu.js:181 #: ../js/ui/userMenu.js:175
msgid "Available" msgid "Available"
msgstr "ಲಭ್ಯ" msgstr "ಲಭ್ಯ"
#: ../js/ui/userMenu.js:184 #: ../js/ui/userMenu.js:178
msgid "Busy" msgid "Busy"
msgstr "ಕಾರ್ಯನಿರತ" msgstr "ಕಾರ್ಯನಿರತ"
#: ../js/ui/userMenu.js:187 #: ../js/ui/userMenu.js:181
msgid "Invisible" msgid "Invisible"
msgstr "ಅಗೋಚರ" msgstr "ಅಗೋಚರ"
#: ../js/ui/userMenu.js:190 #: ../js/ui/userMenu.js:184
msgid "Away" msgid "Away"
msgstr "ಹೊರಗೆ ಹೋಗಿದ್ದೇನೆ" msgstr "ಹೊರಗೆ ಹೋಗಿದ್ದೇನೆ"
#: ../js/ui/userMenu.js:193 #: ../js/ui/userMenu.js:187
msgid "Idle" msgid "Idle"
msgstr "ಜಡ" msgstr "ಜಡ"
#: ../js/ui/userMenu.js:196 #: ../js/ui/userMenu.js:190
msgid "Unavailable" msgid "Unavailable"
msgstr "ಅಲಭ್ಯ" msgstr "ಅಲಭ್ಯ"
#: ../js/ui/userMenu.js:744 #: ../js/ui/userMenu.js:613 ../js/ui/userMenu.js:754
msgid "Notifications"
msgstr "ಸೂಚನೆಗಳು"
#: ../js/ui/userMenu.js:752
msgid "System Settings"
msgstr "ವ್ಯವಸ್ಥೆಯ ಸಿದ್ಧತೆಗಳು"
#: ../js/ui/userMenu.js:760
msgid "Switch User" msgid "Switch User"
msgstr "ಬಳಕೆದಾರನನ್ನು ಬದಲಿಸು" msgstr "ಬಳಕೆದಾರನನ್ನು ಬದಲಿಸು"
#: ../js/ui/userMenu.js:765 #: ../js/ui/userMenu.js:614
#, fuzzy
#| msgid "Switch User"
msgid "Switch Session"
msgstr "ಬಳಕೆದಾರನನ್ನು ಬದಲಿಸು"
#: ../js/ui/userMenu.js:738
msgid "Notifications"
msgstr "ಸೂಚನೆಗಳು"
#: ../js/ui/userMenu.js:746
msgid "System Settings"
msgstr "ವ್ಯವಸ್ಥೆಯ ಸಿದ್ಧತೆಗಳು"
#: ../js/ui/userMenu.js:759
#| msgctxt "title"
#| msgid "Log Out"
msgid "Log Out" msgid "Log Out"
msgstr "ನಿರ್ಗಮಿಸು" msgstr "ನಿರ್ಗಮಿಸು"
#: ../js/ui/userMenu.js:770 #: ../js/ui/userMenu.js:764
msgid "Lock" msgid "Lock"
msgstr "ಲಾಕ್ ಮಾಡು" msgstr ""
#: ../js/ui/userMenu.js:785 #: ../js/ui/userMenu.js:779
msgid "Install Updates & Restart" msgid "Install Updates & Restart"
msgstr "ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಅನುಸ್ಥಾಪಿಸು ಮತ್ತು ಮರಳಿಸ್ಥಾಪಿಸು" msgstr ""
#: ../js/ui/userMenu.js:803 #: ../js/ui/userMenu.js:797
msgid "Your chat status will be set to busy" msgid "Your chat status will be set to busy"
msgstr "ನಿಮ್ಮ ಹರಟೆಯ ಸ್ಥಿತಿಯನ್ನು ಕಾರ್ಯನಿರತರಾಗಿದ್ದಾರೆ ಎಂದು ಬದಲಾಯಿಸಲಾಗಿದೆ." msgstr "ನಿಮ್ಮ ಹರಟೆಯ ಸ್ಥಿತಿಯನ್ನು ಕಾರ್ಯನಿರತರಾಗಿದ್ದಾರೆ ಎಂದು ಬದಲಾಯಿಸಲಾಗಿದೆ."
#: ../js/ui/userMenu.js:804 #: ../js/ui/userMenu.js:798
msgid "" msgid ""
"Notifications are now disabled, including chat messages. Your online status " "Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages." "has been adjusted to let others know that you might not see their messages."
msgstr "" msgstr ""
"ಸಂಭಾಷಣೆಯ ಸಂದೇಶಗಳೂ ಸಹ ಸೇರಿದಂತೆ ಸೂಚನೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿರುತ್ತದೆ. ನೀವು "
"ಬೇರೆಯವರಿಂದ ಬಂದ ಸಂದೇಶಗಳನ್ನು ನೀವು ನೋಡಿಲ್ಲ ಎಂದು ಅವರಿಗೆ ಗೊತ್ತಾಗುವಂತೆ ನಿಮ್ಮ "
"ಆನ್‌ಲೈನ್ "
"ಸ್ಥಿತಿಯನ್ನು ಹೊಂದಿಸಲಾಗಿರುತ್ತದೆ."
#: ../js/ui/viewSelector.js:85 #: ../js/ui/viewSelector.js:85
msgid "Windows" msgid "Windows"
@@ -1707,7 +1676,7 @@ msgstr "ಅನ್ವಯಗಳು"
msgid "Search" msgid "Search"
msgstr "ಹುಡುಕು" msgstr "ಹುಡುಕು"
#: ../js/ui/wanda.js:117 #: ../js/ui/wanda.js:119
#, c-format #, c-format
msgid "" msgid ""
"Sorry, no wisdom for you today:\n" "Sorry, no wisdom for you today:\n"
@@ -1716,12 +1685,12 @@ msgstr ""
"ಕ್ಷಮಿಸಿ, ನಿಮಗಾಗಿ ಯಾವುದೆ ವಿವೇಕವಾಣಿ ಇಲ್ಲ :\n" "ಕ್ಷಮಿಸಿ, ನಿಮಗಾಗಿ ಯಾವುದೆ ವಿವೇಕವಾಣಿ ಇಲ್ಲ :\n"
"%s" "%s"
#: ../js/ui/wanda.js:121 #: ../js/ui/wanda.js:123
#, c-format #, c-format
msgid "%s the Oracle says" msgid "%s the Oracle says"
msgstr "%s Oracle ಹೇಳುವಂತೆ" msgstr "%s Oracle ಹೇಳುವಂತೆ"
#: ../js/ui/wanda.js:162 #: ../js/ui/wanda.js:164
msgid "Your favorite Easter Egg" msgid "Your favorite Easter Egg"
msgstr "ನಿಮ್ಮ ಮೆಚ್ಚಿನ ಈಸ್ಟರ್ ಮೊಟ್ಟೆ" msgstr "ನಿಮ್ಮ ಮೆಚ್ಚಿನ ಈಸ್ಟರ್ ಮೊಟ್ಟೆ"
@@ -1731,6 +1700,7 @@ msgid "'%s' is ready"
msgstr "'%s' ಸಿದ್ಧಗೊಂಡಿದೆ" msgstr "'%s' ಸಿದ್ಧಗೊಂಡಿದೆ"
#: ../src/calendar-server/evolution-calendar.desktop.in.in.h:1 #: ../src/calendar-server/evolution-calendar.desktop.in.in.h:1
#| msgid "Open Calendar"
msgid "Evolution Calendar" msgid "Evolution Calendar"
msgstr "Evolution ಕ್ಯಾಲೆಂಡರ್" msgstr "Evolution ಕ್ಯಾಲೆಂಡರ್"
@@ -1756,23 +1726,23 @@ msgstr[1] "%u ಇನ್‌ಪುಟ್‌ಗಳು"
msgid "System Sounds" msgid "System Sounds"
msgstr "ವ್ಯವಸ್ಥೆಯ ಧ್ವನಿಗಳು" msgstr "ವ್ಯವಸ್ಥೆಯ ಧ್ವನಿಗಳು"
#: ../src/main.c:332 #: ../src/main.c:330
msgid "Print version" msgid "Print version"
msgstr "ಮುದ್ರಿಸಬಹುದಾದ ಆವೃತ್ತಿ" msgstr "ಮುದ್ರಿಸಬಹುದಾದ ಆವೃತ್ತಿ"
#: ../src/main.c:338 #: ../src/main.c:336
msgid "Mode used by GDM for login screen" msgid "Mode used by GDM for login screen"
msgstr "ಪ್ರವೇಶದ ತೆರೆಗಾಗಿ GDM ಬಳಸಿದ ಪ್ರಕಾರ" msgstr "ಪ್ರವೇಶದ ತೆರೆಗಾಗಿ GDM ಬಳಸಿದ ಪ್ರಕಾರ"
#: ../src/main.c:344 #: ../src/main.c:342
msgid "Use a specific mode, e.g. \"gdm\" for login screen" msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "ನಿಶ್ಚಿತ ಸ್ಥಿತಿಯನ್ನು ಬಳಸು, ಉದಾ. ಪ್ರವೇಶ ತೆರೆಗಾಗಿ \"gdm\"" msgstr ""
#: ../src/main.c:350 #: ../src/main.c:348
msgid "List possible modes" msgid "List possible modes"
msgstr "ಸಾಧ್ಯವಿರುವ ಸ್ಥಿತಿಗಳನ್ನು ಪಟ್ಟಿ ಮಾಡು" msgstr ""
#: ../src/shell-app.c:622 #: ../src/shell-app.c:621
#, c-format #, c-format
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "'%s' ಅನ್ನು ಆರಂಭಿಸುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ" msgstr "'%s' ಅನ್ನು ಆರಂಭಿಸುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ"
@@ -1797,10 +1767,6 @@ msgstr "ಪೂರ್ವನಿಯೋಜಿತ"
msgid "Authentication dialog was dismissed by the user" msgid "Authentication dialog was dismissed by the user"
msgstr "ದೃಢೀಕರಣದ ಸಂವಾದವನ್ನು ಬಳಕೆದಾರರಿಂದ ತಿರಸ್ಕರಿಸಲಾಗಿದೆ" msgstr "ದೃಢೀಕರಣದ ಸಂವಾದವನ್ನು ಬಳಕೆದಾರರಿಂದ ತಿರಸ್ಕರಿಸಲಾಗಿದೆ"
#~| msgid "Switch User"
#~ msgid "Switch Session"
#~ msgstr "ಅಧಿವೇಶನವನ್ನು ಬದಲಿಸು"
#~ msgid "disabled OpenSearch providers" #~ msgid "disabled OpenSearch providers"
#~ msgstr "ಅಶಕ್ತಗೊಳಿಸಲಾದ OpenSearch ಒದಗಿಸುವವರು" #~ msgstr "ಅಶಕ್ತಗೊಳಿಸಲಾದ OpenSearch ಒದಗಿಸುವವರು"

599
po/nb.po

File diff suppressed because it is too large Load Diff

732
po/pa.po

File diff suppressed because it is too large Load Diff

707
po/sk.po

File diff suppressed because it is too large Load Diff

946
po/ta.po

File diff suppressed because it is too large Load Diff

52
src/Makefile-gvc.am Normal file
View File

@@ -0,0 +1,52 @@
noinst_LTLIBRARIES += libgvc.la
libgvc_la_CPPFLAGS = \
$(WARN_CFLAGS) \
$(GVC_CFLAGS) \
-I$(srcdir)/gvc/ \
-DWITH_INTROSPECTION \
-DG_LOG_DOMAIN="\"Gvc\""
libgvc_la_LIBADD = \
$(GVC_LIBS)
libgvc_la_LDFLAGS = -avoid-version
libgvc_la_gir_sources = \
gvc/gvc-mixer-stream.h \
gvc/gvc-mixer-stream.c \
gvc/gvc-channel-map.h \
gvc/gvc-channel-map.c \
gvc/gvc-mixer-card.c \
gvc/gvc-mixer-card.h \
gvc/gvc-mixer-sink.h \
gvc/gvc-mixer-sink.c \
gvc/gvc-mixer-source.h \
gvc/gvc-mixer-source.c \
gvc/gvc-mixer-sink-input.h \
gvc/gvc-mixer-sink-input.c \
gvc/gvc-mixer-source-output.h \
gvc/gvc-mixer-source-output.c \
gvc/gvc-mixer-event-role.h \
gvc/gvc-mixer-event-role.c \
gvc/gvc-mixer-control.h \
gvc/gvc-mixer-control.c
libgvc_la_private_sources = \
gvc/gvc-mixer-stream-private.h \
gvc/gvc-channel-map-private.h \
gvc/gvc-mixer-card-private.h \
gvc/gvc-mixer-control-private.h \
gvc/gvc-pulseaudio-fake.h
libgvc_la_SOURCES = \
$(libgvc_la_gir_sources) \
$(libgvc_la_private_sources)
Gvc-1.0.gir: libgvc.la
Gvc_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0
Gvc_1_0_gir_CFLAGS = $(INCLUDES) -I$(srcdir)/gvc -DWITH_INTROSPECTION
Gvc_1_0_gir_LIBS = libgvc.la
Gvc_1_0_gir_FILES = $(addprefix $(srcdir)/,$(libgvc_la_gir_sources))
INTROSPECTION_GIRS += Gvc-1.0.gir
CLEANFILES += Gvc-1.0.gir

View File

@@ -87,21 +87,6 @@ stamp-st.h: Makefile
BUILT_SOURCES += st.h BUILT_SOURCES += st.h
CLEANFILES += stamp-st.h CLEANFILES += stamp-st.h
st-scroll-view-fade-generated.c: stamp-st-scroll-view-fade-generated.c
@true
stamp-st-scroll-view-fade-generated.c: $(srcdir)/st/st-scroll-view-fade.glsl $(srcdir)/data-to-c.pl
$(AM_V_GEN) $(srcdir)/data-to-c.pl $(srcdir)/st/st-scroll-view-fade.glsl st_scroll_view_fade_glsl > $@.tmp && \
(cmp -s $@.tmp st-scroll-view-fade-generated.c || cp $@.tmp st-scroll-view-fade-generated.c) && \
rm -f $@.tmp && \
echo timestamp > $(@F)
BUILT_SOURCES += st-scroll-view-fade-generated.c
CLEANFILES += stamp-st-scroll-view-fade-generated.c
EXTRA_DIST += \
st/st-scroll-view-fade.glsl \
data-to-c.pl \
$(NULL)
st_source_private_h = \ st_source_private_h = \
st/st-private.h \ st/st-private.h \
st/st-table-private.h \ st/st-table-private.h \

View File

@@ -8,8 +8,6 @@ noinst_LTLIBRARIES =
noinst_PROGRAMS = noinst_PROGRAMS =
service_in_files = service_in_files =
SUBDIRS = gvc
-include $(INTROSPECTION_MAKEFILE) -include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS = INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --warn-all --warn-error --add-include-path=$(srcdir) INTROSPECTION_SCANNER_ARGS = --warn-all --warn-error --add-include-path=$(srcdir)
@@ -81,6 +79,7 @@ CLEANFILES += gnome-shell $(bin_SCRIPTS)
include Makefile-st.am include Makefile-st.am
include Makefile-tray.am include Makefile-tray.am
include Makefile-gvc.am
include Makefile-calendar-server.am include Makefile-calendar-server.am
include Makefile-hotplug-sniffer.am include Makefile-hotplug-sniffer.am
@@ -285,7 +284,7 @@ libgnome_shell_la_LIBADD = \
$(BLUETOOTH_LIBS) \ $(BLUETOOTH_LIBS) \
libst-1.0.la \ libst-1.0.la \
libtray.la \ libtray.la \
gvc/libgvc.la \ libgvc.la \
$(NULL) $(NULL)
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)

View File

@@ -1,39 +0,0 @@
#!/usr/bin/perl
# Copyright © 2011 Red Hat, Inc
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the licence, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# Author: Kalev Lember <kalevlember@gmail.com>
if (@ARGV != 2) {
die "Usage: data-to-c.pl <filename> <variable>\n";
}
$file = $ARGV[0];
open (FILE, $file) || die "Cannot open $file: $!\n";
printf ("const char %s[] = \"", $ARGV[1]);
while (my $line = <FILE>) {
foreach my $c (split //, $line) {
printf ("\\x%02x", ord ($c));
}
}
print "\";\n";
close (FILE);

View File

@@ -93,7 +93,6 @@ def start_shell():
args.append('--replace') args.append('--replace')
if options.sync: if options.sync:
args.append('--sync') args.append('--sync')
args += params
return subprocess.Popen(args, env=env) return subprocess.Popen(args, env=env)
def run_shell(): def run_shell():
@@ -157,7 +156,11 @@ parser.add_option("", "--sync", action="store_true")
parser.add_option("", "--version", action="callback", callback=show_version, parser.add_option("", "--version", action="callback", callback=show_version,
help="Display version and exit") help="Display version and exit")
options, params = parser.parse_args() options, args = parser.parse_args()
if args:
parser.print_usage()
sys.exit(1)
# Handle ssh logins # Handle ssh logins
if 'DISPLAY' not in os.environ: if 'DISPLAY' not in os.environ:

Submodule src/gvc deleted from 03894efbcd

View File

@@ -0,0 +1,39 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_CHANNEL_MAP_PRIVATE_H
#define __GVC_CHANNEL_MAP_PRIVATE_H
#include <glib-object.h>
#include <pulse/pulseaudio.h>
G_BEGIN_DECLS
GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *map);
const pa_channel_map * gvc_channel_map_get_pa_channel_map (const GvcChannelMap *map);
void gvc_channel_map_volume_changed (GvcChannelMap *map,
const pa_cvolume *cv,
gboolean set);
const pa_cvolume * gvc_channel_map_get_cvolume (const GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_CHANNEL_MAP_PRIVATE_H */

252
src/gvc/gvc-channel-map.c Normal file
View File

@@ -0,0 +1,252 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-channel-map.h"
#include "gvc-channel-map-private.h"
#define GVC_CHANNEL_MAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapPrivate))
struct GvcChannelMapPrivate
{
pa_channel_map pa_map;
gboolean pa_volume_is_set;
pa_cvolume pa_volume;
gdouble extern_volume[NUM_TYPES]; /* volume, balance, fade, lfe */
gboolean can_balance;
gboolean can_fade;
};
enum {
VOLUME_CHANGED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0, };
static void gvc_channel_map_class_init (GvcChannelMapClass *klass);
static void gvc_channel_map_init (GvcChannelMap *channel_map);
static void gvc_channel_map_finalize (GObject *object);
G_DEFINE_TYPE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT)
guint
gvc_channel_map_get_num_channels (const GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), 0);
if (!pa_channel_map_valid(&map->priv->pa_map))
return 0;
return map->priv->pa_map.channels;
}
const gdouble *
gvc_channel_map_get_volume (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
if (!pa_channel_map_valid(&map->priv->pa_map))
return NULL;
map->priv->extern_volume[VOLUME] = (gdouble) pa_cvolume_max (&map->priv->pa_volume);
if (gvc_channel_map_can_balance (map))
map->priv->extern_volume[BALANCE] = (gdouble) pa_cvolume_get_balance (&map->priv->pa_volume, &map->priv->pa_map);
else
map->priv->extern_volume[BALANCE] = 0;
if (gvc_channel_map_can_fade (map))
map->priv->extern_volume[FADE] = (gdouble) pa_cvolume_get_fade (&map->priv->pa_volume, &map->priv->pa_map);
else
map->priv->extern_volume[FADE] = 0;
if (gvc_channel_map_has_lfe (map))
map->priv->extern_volume[LFE] = (gdouble) pa_cvolume_get_position (&map->priv->pa_volume, &map->priv->pa_map, PA_CHANNEL_POSITION_LFE);
else
map->priv->extern_volume[LFE] = 0;
return map->priv->extern_volume;
}
gboolean
gvc_channel_map_can_balance (const GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
return map->priv->can_balance;
}
gboolean
gvc_channel_map_can_fade (const GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
return map->priv->can_fade;
}
const char *
gvc_channel_map_get_mapping (const GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
if (!pa_channel_map_valid(&map->priv->pa_map))
return NULL;
return pa_channel_map_to_pretty_name (&map->priv->pa_map);
}
/**
* gvc_channel_map_has_position: (skip)
* @map:
* @position:
*
* Returns:
*/
gboolean
gvc_channel_map_has_position (const GvcChannelMap *map,
pa_channel_position_t position)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
return pa_channel_map_has_position (&(map->priv->pa_map), position);
}
const pa_channel_map *
gvc_channel_map_get_pa_channel_map (const GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
if (!pa_channel_map_valid(&map->priv->pa_map))
return NULL;
return &map->priv->pa_map;
}
const pa_cvolume *
gvc_channel_map_get_cvolume (const GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
if (!pa_channel_map_valid(&map->priv->pa_map))
return NULL;
return &map->priv->pa_volume;
}
static void
gvc_channel_map_class_init (GvcChannelMapClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gvc_channel_map_finalize;
signals [VOLUME_CHANGED] =
g_signal_new ("volume-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
g_type_class_add_private (klass, sizeof (GvcChannelMapPrivate));
}
void
gvc_channel_map_volume_changed (GvcChannelMap *map,
const pa_cvolume *cv,
gboolean set)
{
g_return_if_fail (GVC_IS_CHANNEL_MAP (map));
g_return_if_fail (cv != NULL);
g_return_if_fail (pa_cvolume_compatible_with_channel_map(cv, &map->priv->pa_map));
if (pa_cvolume_equal(cv, &map->priv->pa_volume))
return;
map->priv->pa_volume = *cv;
if (map->priv->pa_volume_is_set == FALSE) {
map->priv->pa_volume_is_set = TRUE;
return;
}
g_signal_emit (map, signals[VOLUME_CHANGED], 0, set);
}
static void
gvc_channel_map_init (GvcChannelMap *map)
{
map->priv = GVC_CHANNEL_MAP_GET_PRIVATE (map);
map->priv->pa_volume_is_set = FALSE;
}
static void
gvc_channel_map_finalize (GObject *object)
{
GvcChannelMap *channel_map;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_CHANNEL_MAP (object));
channel_map = GVC_CHANNEL_MAP (object);
g_return_if_fail (channel_map->priv != NULL);
G_OBJECT_CLASS (gvc_channel_map_parent_class)->finalize (object);
}
GvcChannelMap *
gvc_channel_map_new (void)
{
GObject *map;
map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL);
return GVC_CHANNEL_MAP (map);
}
static void
set_from_pa_map (GvcChannelMap *map,
const pa_channel_map *pa_map)
{
g_assert (pa_channel_map_valid(pa_map));
map->priv->can_balance = pa_channel_map_can_balance (pa_map);
map->priv->can_fade = pa_channel_map_can_fade (pa_map);
map->priv->pa_map = *pa_map;
pa_cvolume_set(&map->priv->pa_volume, pa_map->channels, PA_VOLUME_NORM);
}
GvcChannelMap *
gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *pa_map)
{
GObject *map;
map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL);
set_from_pa_map (GVC_CHANNEL_MAP (map), pa_map);
return GVC_CHANNEL_MAP (map);
}

73
src/gvc/gvc-channel-map.h Normal file
View File

@@ -0,0 +1,73 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_CHANNEL_MAP_H
#define __GVC_CHANNEL_MAP_H
#include <glib-object.h>
#include <gvc-pulseaudio-fake.h>
G_BEGIN_DECLS
#define GVC_TYPE_CHANNEL_MAP (gvc_channel_map_get_type ())
#define GVC_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMap))
#define GVC_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass))
#define GVC_IS_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_CHANNEL_MAP))
#define GVC_IS_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_CHANNEL_MAP))
#define GVC_CHANNEL_MAP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass))
typedef struct GvcChannelMapPrivate GvcChannelMapPrivate;
typedef struct
{
GObject parent;
GvcChannelMapPrivate *priv;
} GvcChannelMap;
typedef struct
{
GObjectClass parent_class;
void (*volume_changed) (GvcChannelMap *channel_map, gboolean set);
} GvcChannelMapClass;
enum {
VOLUME,
BALANCE,
FADE,
LFE,
NUM_TYPES
};
GType gvc_channel_map_get_type (void);
GvcChannelMap * gvc_channel_map_new (void);
guint gvc_channel_map_get_num_channels (const GvcChannelMap *map);
const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map);
gboolean gvc_channel_map_can_balance (const GvcChannelMap *map);
gboolean gvc_channel_map_can_fade (const GvcChannelMap *map);
gboolean gvc_channel_map_has_position (const GvcChannelMap *map,
pa_channel_position_t position);
#define gvc_channel_map_has_lfe(x) gvc_channel_map_has_position (x, PA_CHANNEL_POSITION_LFE)
const char * gvc_channel_map_get_mapping (const GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_CHANNEL_MAP_H */

View File

@@ -0,0 +1,35 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008-2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_CARD_PRIVATE_H
#define __GVC_MIXER_CARD_PRIVATE_H
#include <pulse/pulseaudio.h>
#include "gvc-mixer-card.h"
G_BEGIN_DECLS
GvcMixerCard * gvc_mixer_card_new (pa_context *context,
guint index);
pa_context * gvc_mixer_card_get_pa_context (GvcMixerCard *card);
G_END_DECLS
#endif /* __GVC_MIXER_CARD_PRIVATE_H */

514
src/gvc/gvc-mixer-card.c Normal file
View File

@@ -0,0 +1,514 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
* Copyright (C) 2009 Bastien Nocera
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-card.h"
#include "gvc-mixer-card-private.h"
#define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate))
static guint32 card_serial = 1;
struct GvcMixerCardPrivate
{
pa_context *pa_context;
guint id;
guint index;
char *name;
char *icon_name;
char *profile;
char *target_profile;
char *human_profile;
GList *profiles;
pa_operation *profile_op;
};
enum
{
PROP_0,
PROP_ID,
PROP_PA_CONTEXT,
PROP_INDEX,
PROP_NAME,
PROP_ICON_NAME,
PROP_PROFILE,
PROP_HUMAN_PROFILE,
};
static void gvc_mixer_card_class_init (GvcMixerCardClass *klass);
static void gvc_mixer_card_init (GvcMixerCard *mixer_card);
static void gvc_mixer_card_finalize (GObject *object);
G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT)
static guint32
get_next_card_serial (void)
{
guint32 serial;
serial = card_serial++;
if ((gint32)card_serial < 0) {
card_serial = 1;
}
return serial;
}
pa_context *
gvc_mixer_card_get_pa_context (GvcMixerCard *card)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
return card->priv->pa_context;
}
guint
gvc_mixer_card_get_index (GvcMixerCard *card)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
return card->priv->index;
}
guint
gvc_mixer_card_get_id (GvcMixerCard *card)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
return card->priv->id;
}
const char *
gvc_mixer_card_get_name (GvcMixerCard *card)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
return card->priv->name;
}
gboolean
gvc_mixer_card_set_name (GvcMixerCard *card,
const char *name)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
g_free (card->priv->name);
card->priv->name = g_strdup (name);
g_object_notify (G_OBJECT (card), "name");
return TRUE;
}
const char *
gvc_mixer_card_get_icon_name (GvcMixerCard *card)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
return card->priv->icon_name;
}
gboolean
gvc_mixer_card_set_icon_name (GvcMixerCard *card,
const char *icon_name)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
g_free (card->priv->icon_name);
card->priv->icon_name = g_strdup (icon_name);
g_object_notify (G_OBJECT (card), "icon-name");
return TRUE;
}
/**
* gvc_mixer_card_get_profile: (skip)
* @card:
*
* Returns:
*/
GvcMixerCardProfile *
gvc_mixer_card_get_profile (GvcMixerCard *card)
{
GList *l;
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
g_return_val_if_fail (card->priv->profiles != NULL, NULL);
for (l = card->priv->profiles; l != NULL; l = l->next) {
GvcMixerCardProfile *p = l->data;
if (g_str_equal (card->priv->profile, p->profile)) {
return p;
}
}
g_assert_not_reached ();
return NULL;
}
gboolean
gvc_mixer_card_set_profile (GvcMixerCard *card,
const char *profile)
{
GList *l;
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
g_free (card->priv->profile);
card->priv->profile = g_strdup (profile);
g_free (card->priv->human_profile);
card->priv->human_profile = NULL;
for (l = card->priv->profiles; l != NULL; l = l->next) {
GvcMixerCardProfile *p = l->data;
if (g_str_equal (card->priv->profile, p->profile)) {
card->priv->human_profile = g_strdup (p->human_profile);
break;
}
}
g_object_notify (G_OBJECT (card), "profile");
return TRUE;
}
static void
_pa_context_set_card_profile_by_index_cb (pa_context *context,
int success,
void *userdata)
{
GvcMixerCard *card = GVC_MIXER_CARD (userdata);
g_assert (card->priv->target_profile);
if (success > 0) {
gvc_mixer_card_set_profile (card, card->priv->target_profile);
} else {
g_debug ("Failed to switch profile on '%s' from '%s' to '%s'",
card->priv->name,
card->priv->profile,
card->priv->target_profile);
}
g_free (card->priv->target_profile);
card->priv->target_profile = NULL;
pa_operation_unref (card->priv->profile_op);
card->priv->profile_op = NULL;
}
gboolean
gvc_mixer_card_change_profile (GvcMixerCard *card,
const char *profile)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
/* Same profile, or already requested? */
if (g_strcmp0 (card->priv->profile, profile) == 0)
return TRUE;
if (g_strcmp0 (profile, card->priv->target_profile) == 0)
return TRUE;
if (card->priv->profile_op != NULL) {
pa_operation_cancel (card->priv->profile_op);
pa_operation_unref (card->priv->profile_op);
card->priv->profile_op = NULL;
}
if (card->priv->profile != NULL) {
g_free (card->priv->target_profile);
card->priv->target_profile = g_strdup (profile);
card->priv->profile_op = pa_context_set_card_profile_by_index (card->priv->pa_context,
card->priv->index,
card->priv->target_profile,
_pa_context_set_card_profile_by_index_cb,
card);
if (card->priv->profile_op == NULL) {
g_warning ("pa_context_set_card_profile_by_index() failed");
return FALSE;
}
} else {
g_assert (card->priv->human_profile == NULL);
card->priv->profile = g_strdup (profile);
}
return TRUE;
}
/**
* gvc_mixer_card_get_profiles:
*
* Return value: (transfer none) (element-type GvcMixerCardProfile):
*/
const GList *
gvc_mixer_card_get_profiles (GvcMixerCard *card)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
return card->priv->profiles;
}
static int
sort_profiles (GvcMixerCardProfile *a,
GvcMixerCardProfile *b)
{
if (a->priority == b->priority)
return 0;
if (a->priority > b->priority)
return 1;
return -1;
}
/**
* gvc_mixer_card_set_profiles:
* @profiles: (transfer full) (element-type GvcMixerCardProfile):
*/
gboolean
gvc_mixer_card_set_profiles (GvcMixerCard *card,
GList *profiles)
{
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
g_return_val_if_fail (card->priv->profiles == NULL, FALSE);
card->priv->profiles = g_list_sort (profiles, (GCompareFunc) sort_profiles);
return TRUE;
}
static void
gvc_mixer_card_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GvcMixerCard *self = GVC_MIXER_CARD (object);
switch (prop_id) {
case PROP_PA_CONTEXT:
self->priv->pa_context = g_value_get_pointer (value);
break;
case PROP_INDEX:
self->priv->index = g_value_get_ulong (value);
break;
case PROP_ID:
self->priv->id = g_value_get_ulong (value);
break;
case PROP_NAME:
gvc_mixer_card_set_name (self, g_value_get_string (value));
break;
case PROP_ICON_NAME:
gvc_mixer_card_set_icon_name (self, g_value_get_string (value));
break;
case PROP_PROFILE:
gvc_mixer_card_set_profile (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gvc_mixer_card_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GvcMixerCard *self = GVC_MIXER_CARD (object);
switch (prop_id) {
case PROP_PA_CONTEXT:
g_value_set_pointer (value, self->priv->pa_context);
break;
case PROP_INDEX:
g_value_set_ulong (value, self->priv->index);
break;
case PROP_ID:
g_value_set_ulong (value, self->priv->id);
break;
case PROP_NAME:
g_value_set_string (value, self->priv->name);
break;
case PROP_ICON_NAME:
g_value_set_string (value, self->priv->icon_name);
break;
case PROP_PROFILE:
g_value_set_string (value, self->priv->profile);
break;
case PROP_HUMAN_PROFILE:
g_value_set_string (value, self->priv->human_profile);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GObject *
gvc_mixer_card_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
GObject *object;
GvcMixerCard *self;
object = G_OBJECT_CLASS (gvc_mixer_card_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_CARD (object);
self->priv->id = get_next_card_serial ();
return object;
}
static void
gvc_mixer_card_class_init (GvcMixerCardClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructor = gvc_mixer_card_constructor;
gobject_class->finalize = gvc_mixer_card_finalize;
gobject_class->set_property = gvc_mixer_card_set_property;
gobject_class->get_property = gvc_mixer_card_get_property;
g_object_class_install_property (gobject_class,
PROP_INDEX,
g_param_spec_ulong ("index",
"Index",
"The index for this card",
0, G_MAXULONG, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_ID,
g_param_spec_ulong ("id",
"id",
"The id for this card",
0, G_MAXULONG, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_PA_CONTEXT,
g_param_spec_pointer ("pa-context",
"PulseAudio context",
"The PulseAudio context for this card",
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_NAME,
g_param_spec_string ("name",
"Name",
"Name to display for this card",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_ICON_NAME,
g_param_spec_string ("icon-name",
"Icon Name",
"Name of icon to display for this card",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_PROFILE,
g_param_spec_string ("profile",
"Profile",
"Name of current profile for this card",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_HUMAN_PROFILE,
g_param_spec_string ("human-profile",
"Profile (Human readable)",
"Name of current profile for this card in human readable form",
NULL,
G_PARAM_READABLE));
g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate));
}
static void
gvc_mixer_card_init (GvcMixerCard *card)
{
card->priv = GVC_MIXER_CARD_GET_PRIVATE (card);
}
GvcMixerCard *
gvc_mixer_card_new (pa_context *context,
guint index)
{
GObject *object;
object = g_object_new (GVC_TYPE_MIXER_CARD,
"index", index,
"pa-context", context,
NULL);
return GVC_MIXER_CARD (object);
}
static void
free_profile (GvcMixerCardProfile *p)
{
g_free (p->profile);
g_free (p->human_profile);
g_free (p->status);
g_free (p);
}
static void
gvc_mixer_card_finalize (GObject *object)
{
GvcMixerCard *mixer_card;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_CARD (object));
mixer_card = GVC_MIXER_CARD (object);
g_return_if_fail (mixer_card->priv != NULL);
g_free (mixer_card->priv->name);
mixer_card->priv->name = NULL;
g_free (mixer_card->priv->icon_name);
mixer_card->priv->icon_name = NULL;
g_free (mixer_card->priv->target_profile);
mixer_card->priv->target_profile = NULL;
g_free (mixer_card->priv->profile);
mixer_card->priv->profile = NULL;
g_free (mixer_card->priv->human_profile);
mixer_card->priv->human_profile = NULL;
g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL);
g_list_free (mixer_card->priv->profiles);
mixer_card->priv->profiles = NULL;
G_OBJECT_CLASS (gvc_mixer_card_parent_class)->finalize (object);
}

83
src/gvc/gvc-mixer-card.h Normal file
View File

@@ -0,0 +1,83 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008-2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_CARD_H
#define __GVC_MIXER_CARD_H
#include <glib-object.h>
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_CARD (gvc_mixer_card_get_type ())
#define GVC_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CARD, GvcMixerCard))
#define GVC_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CARD, GvcMixerCardClass))
#define GVC_IS_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CARD))
#define GVC_IS_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CARD))
#define GVC_MIXER_CARD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardClass))
typedef struct GvcMixerCardPrivate GvcMixerCardPrivate;
typedef struct
{
GObject parent;
GvcMixerCardPrivate *priv;
} GvcMixerCard;
typedef struct
{
GObjectClass parent_class;
/* vtable */
} GvcMixerCardClass;
typedef struct
{
char *profile;
char *human_profile;
char *status;
guint priority;
guint n_sinks, n_sources;
} GvcMixerCardProfile;
GType gvc_mixer_card_get_type (void);
guint gvc_mixer_card_get_id (GvcMixerCard *card);
guint gvc_mixer_card_get_index (GvcMixerCard *card);
const char * gvc_mixer_card_get_name (GvcMixerCard *card);
const char * gvc_mixer_card_get_icon_name (GvcMixerCard *card);
GvcMixerCardProfile * gvc_mixer_card_get_profile (GvcMixerCard *card);
const GList * gvc_mixer_card_get_profiles (GvcMixerCard *card);
gboolean gvc_mixer_card_change_profile (GvcMixerCard *card,
const char *profile);
/* private */
gboolean gvc_mixer_card_set_name (GvcMixerCard *card,
const char *name);
gboolean gvc_mixer_card_set_icon_name (GvcMixerCard *card,
const char *name);
gboolean gvc_mixer_card_set_profile (GvcMixerCard *card,
const char *profile);
gboolean gvc_mixer_card_set_profiles (GvcMixerCard *card,
GList *profiles);
G_END_DECLS
#endif /* __GVC_MIXER_CARD_H */

View File

@@ -0,0 +1,35 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_CONTROL_PRIVATE_H
#define __GVC_MIXER_CONTROL_PRIVATE_H
#include <glib-object.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-stream.h"
#include "gvc-mixer-card.h"
G_BEGIN_DECLS
pa_context * gvc_mixer_control_get_pa_context (GvcMixerControl *control);
G_END_DECLS
#endif /* __GVC_MIXER_CONTROL_PRIVATE_H */

2241
src/gvc/gvc-mixer-control.c Normal file

File diff suppressed because it is too large Load Diff

108
src/gvc/gvc-mixer-control.h Normal file
View File

@@ -0,0 +1,108 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_CONTROL_H
#define __GVC_MIXER_CONTROL_H
#include <glib-object.h>
#include "gvc-mixer-stream.h"
#include "gvc-mixer-card.h"
G_BEGIN_DECLS
typedef enum
{
GVC_STATE_CLOSED,
GVC_STATE_READY,
GVC_STATE_CONNECTING,
GVC_STATE_FAILED
} GvcMixerControlState;
#define GVC_TYPE_MIXER_CONTROL (gvc_mixer_control_get_type ())
#define GVC_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControl))
#define GVC_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass))
#define GVC_IS_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CONTROL))
#define GVC_IS_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CONTROL))
#define GVC_MIXER_CONTROL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass))
typedef struct GvcMixerControlPrivate GvcMixerControlPrivate;
typedef struct
{
GObject parent;
GvcMixerControlPrivate *priv;
} GvcMixerControl;
typedef struct
{
GObjectClass parent_class;
void (*state_changed) (GvcMixerControl *control,
GvcMixerControlState new_state);
void (*stream_added) (GvcMixerControl *control,
guint id);
void (*stream_removed) (GvcMixerControl *control,
guint id);
void (*card_added) (GvcMixerControl *control,
guint id);
void (*card_removed) (GvcMixerControl *control,
guint id);
void (*default_sink_changed) (GvcMixerControl *control,
guint id);
void (*default_source_changed) (GvcMixerControl *control,
guint id);
} GvcMixerControlClass;
GType gvc_mixer_control_get_type (void);
GvcMixerControl * gvc_mixer_control_new (const char *name);
gboolean gvc_mixer_control_open (GvcMixerControl *control);
gboolean gvc_mixer_control_close (GvcMixerControl *control);
GSList * gvc_mixer_control_get_cards (GvcMixerControl *control);
GSList * gvc_mixer_control_get_streams (GvcMixerControl *control);
GSList * gvc_mixer_control_get_sinks (GvcMixerControl *control);
GSList * gvc_mixer_control_get_sources (GvcMixerControl *control);
GSList * gvc_mixer_control_get_sink_inputs (GvcMixerControl *control);
GSList * gvc_mixer_control_get_source_outputs (GvcMixerControl *control);
GvcMixerStream * gvc_mixer_control_lookup_stream_id (GvcMixerControl *control,
guint id);
GvcMixerCard * gvc_mixer_control_lookup_card_id (GvcMixerControl *control,
guint id);
GvcMixerStream * gvc_mixer_control_get_default_sink (GvcMixerControl *control);
GvcMixerStream * gvc_mixer_control_get_default_source (GvcMixerControl *control);
GvcMixerStream * gvc_mixer_control_get_event_sink_input (GvcMixerControl *control);
gboolean gvc_mixer_control_set_default_sink (GvcMixerControl *control,
GvcMixerStream *stream);
gboolean gvc_mixer_control_set_default_source (GvcMixerControl *control,
GvcMixerStream *stream);
gdouble gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control);
gdouble gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control);
GvcMixerControlState gvc_mixer_control_get_state (GvcMixerControl *control);
G_END_DECLS
#endif /* __GVC_MIXER_CONTROL_H */

View File

@@ -0,0 +1,230 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include <pulse/ext-stream-restore.h>
#include "gvc-mixer-event-role.h"
#include "gvc-mixer-stream-private.h"
#include "gvc-channel-map-private.h"
#define GVC_MIXER_EVENT_ROLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRolePrivate))
struct GvcMixerEventRolePrivate
{
char *device;
};
enum
{
PROP_0,
PROP_DEVICE
};
static void gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass);
static void gvc_mixer_event_role_init (GvcMixerEventRole *mixer_event_role);
static void gvc_mixer_event_role_finalize (GObject *object);
G_DEFINE_TYPE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM)
static gboolean
update_settings (GvcMixerEventRole *role,
gboolean is_muted,
gpointer *op)
{
pa_operation *o;
const GvcChannelMap *map;
pa_context *context;
pa_ext_stream_restore_info info;
map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role));
info.volume = *gvc_channel_map_get_cvolume(map);
info.name = "sink-input-by-media-role:event";
info.channel_map = *gvc_channel_map_get_pa_channel_map(map);
info.device = role->priv->device;
info.mute = is_muted;
context = gvc_mixer_stream_get_pa_context (GVC_MIXER_STREAM (role));
o = pa_ext_stream_restore_write (context,
PA_UPDATE_REPLACE,
&info,
1,
TRUE,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_ext_stream_restore_write() failed");
return FALSE;
}
if (op != NULL)
*op = o;
return TRUE;
}
static gboolean
gvc_mixer_event_role_push_volume (GvcMixerStream *stream, gpointer *op)
{
return update_settings (GVC_MIXER_EVENT_ROLE (stream),
gvc_mixer_stream_get_is_muted (stream), op);
}
static gboolean
gvc_mixer_event_role_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
return update_settings (GVC_MIXER_EVENT_ROLE (stream),
is_muted, NULL);
}
static gboolean
gvc_mixer_event_role_set_device (GvcMixerEventRole *role,
const char *device)
{
g_return_val_if_fail (GVC_IS_MIXER_EVENT_ROLE (role), FALSE);
g_free (role->priv->device);
role->priv->device = g_strdup (device);
g_object_notify (G_OBJECT (role), "device");
return TRUE;
}
static void
gvc_mixer_event_role_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object);
switch (prop_id) {
case PROP_DEVICE:
gvc_mixer_event_role_set_device (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gvc_mixer_event_role_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object);
switch (prop_id) {
case PROP_DEVICE:
g_value_set_string (value, self->priv->device);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->finalize = gvc_mixer_event_role_finalize;
object_class->set_property = gvc_mixer_event_role_set_property;
object_class->get_property = gvc_mixer_event_role_get_property;
stream_class->push_volume = gvc_mixer_event_role_push_volume;
stream_class->change_is_muted = gvc_mixer_event_role_change_is_muted;
g_object_class_install_property (object_class,
PROP_DEVICE,
g_param_spec_string ("device",
"Device",
"Device",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GvcMixerEventRolePrivate));
}
static void
gvc_mixer_event_role_init (GvcMixerEventRole *event_role)
{
event_role->priv = GVC_MIXER_EVENT_ROLE_GET_PRIVATE (event_role);
}
static void
gvc_mixer_event_role_finalize (GObject *object)
{
GvcMixerEventRole *mixer_event_role;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_EVENT_ROLE (object));
mixer_event_role = GVC_MIXER_EVENT_ROLE (object);
g_return_if_fail (mixer_event_role->priv != NULL);
g_free (mixer_event_role->priv->device);
G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->finalize (object);
}
/**
* gvc_mixer_event_role_new: (skip)
* @context:
* @device:
* @channel_map:
*
* Returns:
*/
GvcMixerStream *
gvc_mixer_event_role_new (pa_context *context,
const char *device,
GvcChannelMap *channel_map)
{
GObject *object;
object = g_object_new (GVC_TYPE_MIXER_EVENT_ROLE,
"pa-context", context,
"index", 0,
"device", device,
"channel-map", channel_map,
NULL);
return GVC_MIXER_STREAM (object);
}

View File

@@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_EVENT_ROLE_H
#define __GVC_MIXER_EVENT_ROLE_H
#include <glib-object.h>
#include "gvc-mixer-stream.h"
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_EVENT_ROLE (gvc_mixer_event_role_get_type ())
#define GVC_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRole))
#define GVC_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass))
#define GVC_IS_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_EVENT_ROLE))
#define GVC_IS_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_EVENT_ROLE))
#define GVC_MIXER_EVENT_ROLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass))
typedef struct GvcMixerEventRolePrivate GvcMixerEventRolePrivate;
typedef struct
{
GvcMixerStream parent;
GvcMixerEventRolePrivate *priv;
} GvcMixerEventRole;
typedef struct
{
GvcMixerStreamClass parent_class;
} GvcMixerEventRoleClass;
GType gvc_mixer_event_role_get_type (void);
GvcMixerStream * gvc_mixer_event_role_new (pa_context *context,
const char *device,
GvcChannelMap *channel_map);
G_END_DECLS
#endif /* __GVC_MIXER_EVENT_ROLE_H */

View File

@@ -0,0 +1,165 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-sink-input.h"
#include "gvc-mixer-stream-private.h"
#include "gvc-channel-map-private.h"
#define GVC_MIXER_SINK_INPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputPrivate))
struct GvcMixerSinkInputPrivate
{
gpointer dummy;
};
static void gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass);
static void gvc_mixer_sink_input_init (GvcMixerSinkInput *mixer_sink_input);
static void gvc_mixer_sink_input_finalize (GObject *object);
G_DEFINE_TYPE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM)
static gboolean
gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op)
{
pa_operation *o;
guint index;
const GvcChannelMap *map;
pa_context *context;
const pa_cvolume *cv;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
cv = gvc_channel_map_get_cvolume(map);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_input_volume (context,
index,
cv,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_sink_input_volume() failed");
return FALSE;
}
*op = o;
return TRUE;
}
static gboolean
gvc_mixer_sink_input_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
pa_operation *o;
guint index;
pa_context *context;
index = gvc_mixer_stream_get_index (stream);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_input_mute (context,
index,
is_muted,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_sink_input_mute_by_index() failed");
return FALSE;
}
pa_operation_unref(o);
return TRUE;
}
static void
gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->finalize = gvc_mixer_sink_input_finalize;
stream_class->push_volume = gvc_mixer_sink_input_push_volume;
stream_class->change_is_muted = gvc_mixer_sink_input_change_is_muted;
g_type_class_add_private (klass, sizeof (GvcMixerSinkInputPrivate));
}
static void
gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input)
{
sink_input->priv = GVC_MIXER_SINK_INPUT_GET_PRIVATE (sink_input);
}
static void
gvc_mixer_sink_input_finalize (GObject *object)
{
GvcMixerSinkInput *mixer_sink_input;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object));
mixer_sink_input = GVC_MIXER_SINK_INPUT (object);
g_return_if_fail (mixer_sink_input->priv != NULL);
G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->finalize (object);
}
/**
* gvc_mixer_sink_input_new: (skip)
* @context:
* @index:
* @map:
*
* Returns:
*/
GvcMixerStream *
gvc_mixer_sink_input_new (pa_context *context,
guint index,
GvcChannelMap *channel_map)
{
GObject *object;
object = g_object_new (GVC_TYPE_MIXER_SINK_INPUT,
"pa-context", context,
"index", index,
"channel-map", channel_map,
NULL);
return GVC_MIXER_STREAM (object);
}

View File

@@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_SINK_INPUT_H
#define __GVC_MIXER_SINK_INPUT_H
#include <glib-object.h>
#include "gvc-mixer-stream.h"
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_SINK_INPUT (gvc_mixer_sink_input_get_type ())
#define GVC_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInput))
#define GVC_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass))
#define GVC_IS_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK_INPUT))
#define GVC_IS_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK_INPUT))
#define GVC_MIXER_SINK_INPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass))
typedef struct GvcMixerSinkInputPrivate GvcMixerSinkInputPrivate;
typedef struct
{
GvcMixerStream parent;
GvcMixerSinkInputPrivate *priv;
} GvcMixerSinkInput;
typedef struct
{
GvcMixerStreamClass parent_class;
} GvcMixerSinkInputClass;
GType gvc_mixer_sink_input_get_type (void);
GvcMixerStream * gvc_mixer_sink_input_new (pa_context *context,
guint index,
GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_MIXER_SINK_INPUT_H */

199
src/gvc/gvc-mixer-sink.c Normal file
View File

@@ -0,0 +1,199 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-sink.h"
#include "gvc-mixer-stream-private.h"
#include "gvc-channel-map-private.h"
#define GVC_MIXER_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkPrivate))
struct GvcMixerSinkPrivate
{
gpointer dummy;
};
static void gvc_mixer_sink_class_init (GvcMixerSinkClass *klass);
static void gvc_mixer_sink_init (GvcMixerSink *mixer_sink);
static void gvc_mixer_sink_finalize (GObject *object);
G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM)
static gboolean
gvc_mixer_sink_push_volume (GvcMixerStream *stream, gpointer *op)
{
pa_operation *o;
guint index;
const GvcChannelMap *map;
pa_context *context;
const pa_cvolume *cv;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
/* set the volume */
cv = gvc_channel_map_get_cvolume(map);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_volume_by_index (context,
index,
cv,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_sink_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
*op = o;
return TRUE;
}
static gboolean
gvc_mixer_sink_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
pa_operation *o;
guint index;
pa_context *context;
index = gvc_mixer_stream_get_index (stream);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_mute_by_index (context,
index,
is_muted,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_sink_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
pa_operation_unref(o);
return TRUE;
}
static gboolean
gvc_mixer_sink_change_port (GvcMixerStream *stream,
const char *port)
{
#if PA_MICRO > 15
pa_operation *o;
guint index;
pa_context *context;
index = gvc_mixer_stream_get_index (stream);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_sink_port_by_index (context,
index,
port,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_sink_port_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
pa_operation_unref(o);
return TRUE;
#else
return FALSE;
#endif /* PA_MICRO > 15 */
}
static void
gvc_mixer_sink_class_init (GvcMixerSinkClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->finalize = gvc_mixer_sink_finalize;
stream_class->push_volume = gvc_mixer_sink_push_volume;
stream_class->change_port = gvc_mixer_sink_change_port;
stream_class->change_is_muted = gvc_mixer_sink_change_is_muted;
g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate));
}
static void
gvc_mixer_sink_init (GvcMixerSink *sink)
{
sink->priv = GVC_MIXER_SINK_GET_PRIVATE (sink);
}
static void
gvc_mixer_sink_finalize (GObject *object)
{
GvcMixerSink *mixer_sink;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SINK (object));
mixer_sink = GVC_MIXER_SINK (object);
g_return_if_fail (mixer_sink->priv != NULL);
G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->finalize (object);
}
/**
* gvc_mixer_sink_new: (skip)
* @context:
* @index:
* @map:
*
* Returns:
*/
GvcMixerStream *
gvc_mixer_sink_new (pa_context *context,
guint index,
GvcChannelMap *channel_map)
{
GObject *object;
object = g_object_new (GVC_TYPE_MIXER_SINK,
"pa-context", context,
"index", index,
"channel-map", channel_map,
NULL);
return GVC_MIXER_STREAM (object);
}

57
src/gvc/gvc-mixer-sink.h Normal file
View File

@@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_SINK_H
#define __GVC_MIXER_SINK_H
#include <glib-object.h>
#include "gvc-mixer-stream.h"
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_SINK (gvc_mixer_sink_get_type ())
#define GVC_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK, GvcMixerSink))
#define GVC_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass))
#define GVC_IS_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK))
#define GVC_IS_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK))
#define GVC_MIXER_SINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass))
typedef struct GvcMixerSinkPrivate GvcMixerSinkPrivate;
typedef struct
{
GvcMixerStream parent;
GvcMixerSinkPrivate *priv;
} GvcMixerSink;
typedef struct
{
GvcMixerStreamClass parent_class;
} GvcMixerSinkClass;
GType gvc_mixer_sink_get_type (void);
GvcMixerStream * gvc_mixer_sink_new (pa_context *context,
guint index,
GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_MIXER_SINK_H */

View File

@@ -0,0 +1,120 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-source-output.h"
#define GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputPrivate))
struct GvcMixerSourceOutputPrivate
{
gpointer dummy;
};
static void gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass);
static void gvc_mixer_source_output_init (GvcMixerSourceOutput *mixer_source_output);
static void gvc_mixer_source_output_finalize (GObject *object);
G_DEFINE_TYPE (GvcMixerSourceOutput, gvc_mixer_source_output, GVC_TYPE_MIXER_STREAM)
static gboolean
gvc_mixer_source_output_push_volume (GvcMixerStream *stream, gpointer *op)
{
/* FIXME: */
*op = NULL;
return TRUE;
}
static gboolean
gvc_mixer_source_output_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
/* FIXME: */
return TRUE;
}
static void
gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->finalize = gvc_mixer_source_output_finalize;
stream_class->push_volume = gvc_mixer_source_output_push_volume;
stream_class->change_is_muted = gvc_mixer_source_output_change_is_muted;
g_type_class_add_private (klass, sizeof (GvcMixerSourceOutputPrivate));
}
static void
gvc_mixer_source_output_init (GvcMixerSourceOutput *source_output)
{
source_output->priv = GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE (source_output);
}
static void
gvc_mixer_source_output_finalize (GObject *object)
{
GvcMixerSourceOutput *mixer_source_output;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SOURCE_OUTPUT (object));
mixer_source_output = GVC_MIXER_SOURCE_OUTPUT (object);
g_return_if_fail (mixer_source_output->priv != NULL);
G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->finalize (object);
}
/**
* gvc_mixer_source_output_new: (skip)
* @context:
* @index:
* @map:
*
* Returns:
*/
GvcMixerStream *
gvc_mixer_source_output_new (pa_context *context,
guint index,
GvcChannelMap *channel_map)
{
GObject *object;
object = g_object_new (GVC_TYPE_MIXER_SOURCE_OUTPUT,
"pa-context", context,
"index", index,
"channel-map", channel_map,
NULL);
return GVC_MIXER_STREAM (object);
}

View File

@@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_SOURCE_OUTPUT_H
#define __GVC_MIXER_SOURCE_OUTPUT_H
#include <glib-object.h>
#include "gvc-mixer-stream.h"
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_SOURCE_OUTPUT (gvc_mixer_source_output_get_type ())
#define GVC_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutput))
#define GVC_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass))
#define GVC_IS_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT))
#define GVC_IS_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE_OUTPUT))
#define GVC_MIXER_SOURCE_OUTPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass))
typedef struct GvcMixerSourceOutputPrivate GvcMixerSourceOutputPrivate;
typedef struct
{
GvcMixerStream parent;
GvcMixerSourceOutputPrivate *priv;
} GvcMixerSourceOutput;
typedef struct
{
GvcMixerStreamClass parent_class;
} GvcMixerSourceOutputClass;
GType gvc_mixer_source_output_get_type (void);
GvcMixerStream * gvc_mixer_source_output_new (pa_context *context,
guint index,
GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_MIXER_SOURCE_OUTPUT_H */

199
src/gvc/gvc-mixer-source.c Normal file
View File

@@ -0,0 +1,199 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-source.h"
#include "gvc-mixer-stream-private.h"
#include "gvc-channel-map-private.h"
#define GVC_MIXER_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourcePrivate))
struct GvcMixerSourcePrivate
{
gpointer dummy;
};
static void gvc_mixer_source_class_init (GvcMixerSourceClass *klass);
static void gvc_mixer_source_init (GvcMixerSource *mixer_source);
static void gvc_mixer_source_finalize (GObject *object);
G_DEFINE_TYPE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM)
static gboolean
gvc_mixer_source_push_volume (GvcMixerStream *stream, gpointer *op)
{
pa_operation *o;
guint index;
const GvcChannelMap *map;
pa_context *context;
const pa_cvolume *cv;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
/* set the volume */
cv = gvc_channel_map_get_cvolume (map);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_source_volume_by_index (context,
index,
cv,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_source_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
*op = o;
return TRUE;
}
static gboolean
gvc_mixer_source_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
pa_operation *o;
guint index;
pa_context *context;
index = gvc_mixer_stream_get_index (stream);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_source_mute_by_index (context,
index,
is_muted,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_source_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
pa_operation_unref(o);
return TRUE;
}
static gboolean
gvc_mixer_source_change_port (GvcMixerStream *stream,
const char *port)
{
#if PA_MICRO > 15
pa_operation *o;
guint index;
pa_context *context;
index = gvc_mixer_stream_get_index (stream);
context = gvc_mixer_stream_get_pa_context (stream);
o = pa_context_set_source_port_by_index (context,
index,
port,
NULL,
NULL);
if (o == NULL) {
g_warning ("pa_context_set_source_port_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
pa_operation_unref(o);
return TRUE;
#else
return FALSE;
#endif /* PA_MICRO > 15 */
}
static void
gvc_mixer_source_class_init (GvcMixerSourceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->finalize = gvc_mixer_source_finalize;
stream_class->push_volume = gvc_mixer_source_push_volume;
stream_class->change_is_muted = gvc_mixer_source_change_is_muted;
stream_class->change_port = gvc_mixer_source_change_port;
g_type_class_add_private (klass, sizeof (GvcMixerSourcePrivate));
}
static void
gvc_mixer_source_init (GvcMixerSource *source)
{
source->priv = GVC_MIXER_SOURCE_GET_PRIVATE (source);
}
static void
gvc_mixer_source_finalize (GObject *object)
{
GvcMixerSource *mixer_source;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SOURCE (object));
mixer_source = GVC_MIXER_SOURCE (object);
g_return_if_fail (mixer_source->priv != NULL);
G_OBJECT_CLASS (gvc_mixer_source_parent_class)->finalize (object);
}
/**
* gvc_mixer_source_new: (skip)
* @context:
* @index:
* @map:
*
* Returns:
*/
GvcMixerStream *
gvc_mixer_source_new (pa_context *context,
guint index,
GvcChannelMap *channel_map)
{
GObject *object;
object = g_object_new (GVC_TYPE_MIXER_SOURCE,
"pa-context", context,
"index", index,
"channel-map", channel_map,
NULL);
return GVC_MIXER_STREAM (object);
}

View File

@@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_SOURCE_H
#define __GVC_MIXER_SOURCE_H
#include <glib-object.h>
#include "gvc-mixer-stream.h"
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_SOURCE (gvc_mixer_source_get_type ())
#define GVC_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSource))
#define GVC_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass))
#define GVC_IS_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE))
#define GVC_IS_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE))
#define GVC_MIXER_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass))
typedef struct GvcMixerSourcePrivate GvcMixerSourcePrivate;
typedef struct
{
GvcMixerStream parent;
GvcMixerSourcePrivate *priv;
} GvcMixerSource;
typedef struct
{
GvcMixerStreamClass parent_class;
} GvcMixerSourceClass;
GType gvc_mixer_source_get_type (void);
GvcMixerStream * gvc_mixer_source_new (pa_context *context,
guint index,
GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_MIXER_SOURCE_H */

View File

@@ -0,0 +1,34 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_STREAM_PRIVATE_H
#define __GVC_MIXER_STREAM_PRIVATE_H
#include <glib-object.h>
#include "gvc-channel-map.h"
G_BEGIN_DECLS
pa_context * gvc_mixer_stream_get_pa_context (GvcMixerStream *stream);
G_END_DECLS
#endif /* __GVC_MIXER_STREAM_PRIVATE_H */

964
src/gvc/gvc-mixer-stream.c Normal file
View File

@@ -0,0 +1,964 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <pulse/pulseaudio.h>
#include "gvc-mixer-stream.h"
#include "gvc-mixer-stream-private.h"
#include "gvc-channel-map-private.h"
#define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate))
static guint32 stream_serial = 1;
struct GvcMixerStreamPrivate
{
pa_context *pa_context;
guint id;
guint index;
gint card_index;
GvcChannelMap *channel_map;
char *name;
char *description;
char *application_id;
char *icon_name;
gboolean is_muted;
gboolean can_decibel;
gboolean is_event_stream;
gboolean is_virtual;
pa_volume_t base_volume;
pa_operation *change_volume_op;
char *port;
char *human_port;
GList *ports;
};
enum
{
PROP_0,
PROP_ID,
PROP_PA_CONTEXT,
PROP_CHANNEL_MAP,
PROP_INDEX,
PROP_NAME,
PROP_DESCRIPTION,
PROP_APPLICATION_ID,
PROP_ICON_NAME,
PROP_VOLUME,
PROP_DECIBEL,
PROP_IS_MUTED,
PROP_CAN_DECIBEL,
PROP_IS_EVENT_STREAM,
PROP_IS_VIRTUAL,
PROP_CARD_INDEX,
PROP_PORT,
};
static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass);
static void gvc_mixer_stream_init (GvcMixerStream *mixer_stream);
static void gvc_mixer_stream_finalize (GObject *object);
G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
static guint32
get_next_stream_serial (void)
{
guint32 serial;
serial = stream_serial++;
if ((gint32)stream_serial < 0) {
stream_serial = 1;
}
return serial;
}
pa_context *
gvc_mixer_stream_get_pa_context (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
return stream->priv->pa_context;
}
guint
gvc_mixer_stream_get_index (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
return stream->priv->index;
}
guint
gvc_mixer_stream_get_id (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
return stream->priv->id;
}
const GvcChannelMap *
gvc_mixer_stream_get_channel_map (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
return stream->priv->channel_map;
}
/**
* gvc_mixer_stream_get_volume:
* @stream:
*
* Returns: (type guint32) (transfer none):
*/
pa_volume_t
gvc_mixer_stream_get_volume (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME];
}
gdouble
gvc_mixer_stream_get_decibel (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
return pa_sw_volume_to_dB(
(pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
}
/**
* gvc_mixer_stream_set_volume:
* @stream:
* @volume: (type guint32):
*
* Returns:
*/
gboolean
gvc_mixer_stream_set_volume (GvcMixerStream *stream,
pa_volume_t volume)
{
pa_cvolume cv;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
pa_cvolume_scale(&cv, volume);
if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
g_object_notify (G_OBJECT (stream), "volume");
return TRUE;
}
return FALSE;
}
gboolean
gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
gdouble db)
{
pa_cvolume cv;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db));
if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
g_object_notify (G_OBJECT (stream), "volume");
}
return TRUE;
}
gboolean
gvc_mixer_stream_get_is_muted (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
return stream->priv->is_muted;
}
gboolean
gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
return stream->priv->can_decibel;
}
gboolean
gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
if (is_muted != stream->priv->is_muted) {
stream->priv->is_muted = is_muted;
g_object_notify (G_OBJECT (stream), "is-muted");
}
return TRUE;
}
gboolean
gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream,
gboolean can_decibel)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
if (can_decibel != stream->priv->can_decibel) {
stream->priv->can_decibel = can_decibel;
g_object_notify (G_OBJECT (stream), "can-decibel");
}
return TRUE;
}
const char *
gvc_mixer_stream_get_name (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
return stream->priv->name;
}
const char *
gvc_mixer_stream_get_description (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
return stream->priv->description;
}
gboolean
gvc_mixer_stream_set_name (GvcMixerStream *stream,
const char *name)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
g_free (stream->priv->name);
stream->priv->name = g_strdup (name);
g_object_notify (G_OBJECT (stream), "name");
return TRUE;
}
gboolean
gvc_mixer_stream_set_description (GvcMixerStream *stream,
const char *description)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
g_free (stream->priv->description);
stream->priv->description = g_strdup (description);
g_object_notify (G_OBJECT (stream), "description");
return TRUE;
}
gboolean
gvc_mixer_stream_is_event_stream (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
return stream->priv->is_event_stream;
}
gboolean
gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
gboolean is_event_stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
stream->priv->is_event_stream = is_event_stream;
g_object_notify (G_OBJECT (stream), "is-event-stream");
return TRUE;
}
gboolean
gvc_mixer_stream_is_virtual (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
return stream->priv->is_virtual;
}
gboolean
gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
gboolean is_virtual)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
stream->priv->is_virtual = is_virtual;
g_object_notify (G_OBJECT (stream), "is-virtual");
return TRUE;
}
const char *
gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
return stream->priv->application_id;
}
gboolean
gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
const char *application_id)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
g_free (stream->priv->application_id);
stream->priv->application_id = g_strdup (application_id);
g_object_notify (G_OBJECT (stream), "application-id");
return TRUE;
}
static void
on_channel_map_volume_changed (GvcChannelMap *channel_map,
gboolean set,
GvcMixerStream *stream)
{
if (set == TRUE)
gvc_mixer_stream_push_volume (stream);
g_object_notify (G_OBJECT (stream), "volume");
}
static gboolean
gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
GvcChannelMap *channel_map)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
if (channel_map != NULL) {
g_object_ref (channel_map);
}
if (stream->priv->channel_map != NULL) {
g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
on_channel_map_volume_changed,
stream);
g_object_unref (stream->priv->channel_map);
}
stream->priv->channel_map = channel_map;
if (stream->priv->channel_map != NULL) {
g_signal_connect (stream->priv->channel_map,
"volume-changed",
G_CALLBACK (on_channel_map_volume_changed),
stream);
g_object_notify (G_OBJECT (stream), "channel-map");
}
return TRUE;
}
const char *
gvc_mixer_stream_get_icon_name (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
return stream->priv->icon_name;
}
/**
* gvc_mixer_stream_get_gicon:
* @stream: a #GvcMixerStream
*
* Returns: (transfer full): a new #GIcon
*/
GIcon *
gvc_mixer_stream_get_gicon (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
if (stream->priv->icon_name == NULL)
return NULL;
return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name);
}
gboolean
gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
const char *icon_name)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
g_free (stream->priv->icon_name);
stream->priv->icon_name = g_strdup (icon_name);
g_object_notify (G_OBJECT (stream), "icon-name");
return TRUE;
}
/**
* gvc_mixer_stream_get_base_volume:
* @stream:
*
* Returns: (type guint32) (transfer none):
*/
pa_volume_t
gvc_mixer_stream_get_base_volume (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
return stream->priv->base_volume;
}
/**
* gvc_mixer_stream_set_base_volume:
* @stream:
* @base_volume: (type guint32):
*
* Returns:
*/
gboolean
gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
pa_volume_t base_volume)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
stream->priv->base_volume = base_volume;
return TRUE;
}
const GvcMixerStreamPort *
gvc_mixer_stream_get_port (GvcMixerStream *stream)
{
GList *l;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
g_return_val_if_fail (stream->priv->ports != NULL, NULL);
for (l = stream->priv->ports; l != NULL; l = l->next) {
GvcMixerStreamPort *p = l->data;
if (g_strcmp0 (stream->priv->port, p->port) == 0) {
return p;
}
}
g_assert_not_reached ();
return NULL;
}
gboolean
gvc_mixer_stream_set_port (GvcMixerStream *stream,
const char *port)
{
GList *l;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
g_return_val_if_fail (stream->priv->ports != NULL, FALSE);
g_free (stream->priv->port);
stream->priv->port = g_strdup (port);
g_free (stream->priv->human_port);
stream->priv->human_port = NULL;
for (l = stream->priv->ports; l != NULL; l = l->next) {
GvcMixerStreamPort *p = l->data;
if (g_str_equal (stream->priv->port, p->port)) {
stream->priv->human_port = g_strdup (p->human_port);
break;
}
}
g_object_notify (G_OBJECT (stream), "port");
return TRUE;
}
gboolean
gvc_mixer_stream_change_port (GvcMixerStream *stream,
const char *port)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port);
}
/**
* gvc_mixer_stream_get_ports:
*
* Return value: (transfer none) (element-type GvcMixerStreamPort):
*/
const GList *
gvc_mixer_stream_get_ports (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
return stream->priv->ports;
}
static int
sort_ports (GvcMixerStreamPort *a,
GvcMixerStreamPort *b)
{
if (a->priority == b->priority)
return 0;
if (a->priority > b->priority)
return 1;
return -1;
}
/**
* gvc_mixer_stream_set_ports:
* @ports: (transfer full) (element-type GvcMixerStreamPort):
*/
gboolean
gvc_mixer_stream_set_ports (GvcMixerStream *stream,
GList *ports)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
return TRUE;
}
gint
gvc_mixer_stream_get_card_index (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX);
return stream->priv->card_index;
}
gboolean
gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
gint card_index)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
stream->priv->card_index = card_index;
g_object_notify (G_OBJECT (stream), "card-index");
return TRUE;
}
static void
gvc_mixer_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GvcMixerStream *self = GVC_MIXER_STREAM (object);
switch (prop_id) {
case PROP_PA_CONTEXT:
self->priv->pa_context = g_value_get_pointer (value);
break;
case PROP_INDEX:
self->priv->index = g_value_get_ulong (value);
break;
case PROP_ID:
self->priv->id = g_value_get_ulong (value);
break;
case PROP_CHANNEL_MAP:
gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
break;
case PROP_NAME:
gvc_mixer_stream_set_name (self, g_value_get_string (value));
break;
case PROP_DESCRIPTION:
gvc_mixer_stream_set_description (self, g_value_get_string (value));
break;
case PROP_APPLICATION_ID:
gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
break;
case PROP_ICON_NAME:
gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
break;
case PROP_VOLUME:
gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
break;
case PROP_DECIBEL:
gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
break;
case PROP_IS_MUTED:
gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
break;
case PROP_IS_EVENT_STREAM:
gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
break;
case PROP_IS_VIRTUAL:
gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
break;
case PROP_CAN_DECIBEL:
gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
break;
case PROP_PORT:
gvc_mixer_stream_set_port (self, g_value_get_string (value));
break;
case PROP_CARD_INDEX:
self->priv->card_index = g_value_get_long (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gvc_mixer_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GvcMixerStream *self = GVC_MIXER_STREAM (object);
switch (prop_id) {
case PROP_PA_CONTEXT:
g_value_set_pointer (value, self->priv->pa_context);
break;
case PROP_INDEX:
g_value_set_ulong (value, self->priv->index);
break;
case PROP_ID:
g_value_set_ulong (value, self->priv->id);
break;
case PROP_CHANNEL_MAP:
g_value_set_object (value, self->priv->channel_map);
break;
case PROP_NAME:
g_value_set_string (value, self->priv->name);
break;
case PROP_DESCRIPTION:
g_value_set_string (value, self->priv->description);
break;
case PROP_APPLICATION_ID:
g_value_set_string (value, self->priv->application_id);
break;
case PROP_ICON_NAME:
g_value_set_string (value, self->priv->icon_name);
break;
case PROP_VOLUME:
g_value_set_ulong (value,
pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
break;
case PROP_DECIBEL:
g_value_set_double (value,
pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
break;
case PROP_IS_MUTED:
g_value_set_boolean (value, self->priv->is_muted);
break;
case PROP_IS_EVENT_STREAM:
g_value_set_boolean (value, self->priv->is_event_stream);
break;
case PROP_IS_VIRTUAL:
g_value_set_boolean (value, self->priv->is_virtual);
break;
case PROP_CAN_DECIBEL:
g_value_set_boolean (value, self->priv->can_decibel);
break;
case PROP_PORT:
g_value_set_string (value, self->priv->port);
break;
case PROP_CARD_INDEX:
g_value_set_long (value, self->priv->card_index);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GObject *
gvc_mixer_stream_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
GObject *object;
GvcMixerStream *self;
object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_STREAM (object);
self->priv->id = get_next_stream_serial ();
return object;
}
static gboolean
gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
const char *port)
{
return FALSE;
}
static gboolean
gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
{
return FALSE;
}
static gboolean
gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
return FALSE;
}
gboolean
gvc_mixer_stream_push_volume (GvcMixerStream *stream)
{
pa_operation *op;
gboolean ret;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
if (stream->priv->is_event_stream != FALSE)
return TRUE;
g_debug ("Pushing new volume to stream '%s' (%s)",
stream->priv->description, stream->priv->name);
ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
if (ret) {
if (stream->priv->change_volume_op != NULL)
pa_operation_unref (stream->priv->change_volume_op);
stream->priv->change_volume_op = op;
}
return ret;
}
gboolean
gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
gboolean ret;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted);
return ret;
}
gboolean
gvc_mixer_stream_is_running (GvcMixerStream *stream)
{
if (stream->priv->change_volume_op == NULL)
return FALSE;
if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
return TRUE;
pa_operation_unref(stream->priv->change_volume_op);
stream->priv->change_volume_op = NULL;
return FALSE;
}
static void
gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructor = gvc_mixer_stream_constructor;
gobject_class->finalize = gvc_mixer_stream_finalize;
gobject_class->set_property = gvc_mixer_stream_set_property;
gobject_class->get_property = gvc_mixer_stream_get_property;
klass->push_volume = gvc_mixer_stream_real_push_volume;
klass->change_port = gvc_mixer_stream_real_change_port;
klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
g_object_class_install_property (gobject_class,
PROP_INDEX,
g_param_spec_ulong ("index",
"Index",
"The index for this stream",
0, G_MAXULONG, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_ID,
g_param_spec_ulong ("id",
"id",
"The id for this stream",
0, G_MAXULONG, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_CHANNEL_MAP,
g_param_spec_object ("channel-map",
"channel map",
"The channel map for this stream",
GVC_TYPE_CHANNEL_MAP,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_PA_CONTEXT,
g_param_spec_pointer ("pa-context",
"PulseAudio context",
"The PulseAudio context for this stream",
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_VOLUME,
g_param_spec_ulong ("volume",
"Volume",
"The volume for this stream",
0, G_MAXULONG, 0,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DECIBEL,
g_param_spec_double ("decibel",
"Decibel",
"The decibel level for this stream",
-G_MAXDOUBLE, G_MAXDOUBLE, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_NAME,
g_param_spec_string ("name",
"Name",
"Name to display for this stream",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_DESCRIPTION,
g_param_spec_string ("description",
"Description",
"Description to display for this stream",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_APPLICATION_ID,
g_param_spec_string ("application-id",
"Application identifier",
"Application identifier for this stream",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_ICON_NAME,
g_param_spec_string ("icon-name",
"Icon Name",
"Name of icon to display for this stream",
NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_IS_MUTED,
g_param_spec_boolean ("is-muted",
"is muted",
"Whether stream is muted",
FALSE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_CAN_DECIBEL,
g_param_spec_boolean ("can-decibel",
"can decibel",
"Whether stream volume can be converted to decibel units",
FALSE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_IS_EVENT_STREAM,
g_param_spec_boolean ("is-event-stream",
"is event stream",
"Whether stream's role is to play an event",
FALSE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_IS_VIRTUAL,
g_param_spec_boolean ("is-virtual",
"is virtual stream",
"Whether the stream is virtual",
FALSE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_PORT,
g_param_spec_string ("port",
"Port",
"The name of the current port for this stream",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_CARD_INDEX,
g_param_spec_long ("card-index",
"Card index",
"The index of the card for this stream",
PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
}
static void
gvc_mixer_stream_init (GvcMixerStream *stream)
{
stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
}
static void
free_port (GvcMixerStreamPort *p)
{
g_free (p->port);
g_free (p->human_port);
g_free (p);
}
static void
gvc_mixer_stream_finalize (GObject *object)
{
GvcMixerStream *mixer_stream;
g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_STREAM (object));
mixer_stream = GVC_MIXER_STREAM (object);
g_return_if_fail (mixer_stream->priv != NULL);
g_object_unref (mixer_stream->priv->channel_map);
mixer_stream->priv->channel_map = NULL;
g_free (mixer_stream->priv->name);
mixer_stream->priv->name = NULL;
g_free (mixer_stream->priv->description);
mixer_stream->priv->description = NULL;
g_free (mixer_stream->priv->application_id);
mixer_stream->priv->application_id = NULL;
g_free (mixer_stream->priv->icon_name);
mixer_stream->priv->icon_name = NULL;
g_free (mixer_stream->priv->port);
mixer_stream->priv->port = NULL;
g_free (mixer_stream->priv->human_port);
mixer_stream->priv->human_port = NULL;
g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
g_list_free (mixer_stream->priv->ports);
mixer_stream->priv->ports = NULL;
if (mixer_stream->priv->change_volume_op) {
pa_operation_unref(mixer_stream->priv->change_volume_op);
mixer_stream->priv->change_volume_op = NULL;
}
G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);
}

127
src/gvc/gvc-mixer-stream.h Normal file
View File

@@ -0,0 +1,127 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_MIXER_STREAM_H
#define __GVC_MIXER_STREAM_H
#include <glib-object.h>
#include "gvc-pulseaudio-fake.h"
#include "gvc-channel-map.h"
#include <gio/gio.h>
G_BEGIN_DECLS
#define GVC_TYPE_MIXER_STREAM (gvc_mixer_stream_get_type ())
#define GVC_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStream))
#define GVC_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass))
#define GVC_IS_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_STREAM))
#define GVC_IS_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_STREAM))
#define GVC_MIXER_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass))
typedef struct GvcMixerStreamPrivate GvcMixerStreamPrivate;
typedef struct
{
GObject parent;
GvcMixerStreamPrivate *priv;
} GvcMixerStream;
typedef struct
{
GObjectClass parent_class;
/* vtable */
gboolean (*push_volume) (GvcMixerStream *stream,
gpointer *operation);
gboolean (*change_is_muted) (GvcMixerStream *stream,
gboolean is_muted);
gboolean (*change_port) (GvcMixerStream *stream,
const char *port);
} GvcMixerStreamClass;
typedef struct
{
char *port;
char *human_port;
guint priority;
} GvcMixerStreamPort;
GType gvc_mixer_stream_get_type (void);
guint gvc_mixer_stream_get_index (GvcMixerStream *stream);
guint gvc_mixer_stream_get_id (GvcMixerStream *stream);
const GvcChannelMap *gvc_mixer_stream_get_channel_map(GvcMixerStream *stream);
const GvcMixerStreamPort *gvc_mixer_stream_get_port (GvcMixerStream *stream);
const GList * gvc_mixer_stream_get_ports (GvcMixerStream *stream);
gboolean gvc_mixer_stream_change_port (GvcMixerStream *stream,
const char *port);
pa_volume_t gvc_mixer_stream_get_volume (GvcMixerStream *stream);
gdouble gvc_mixer_stream_get_decibel (GvcMixerStream *stream);
gboolean gvc_mixer_stream_push_volume (GvcMixerStream *stream);
pa_volume_t gvc_mixer_stream_get_base_volume (GvcMixerStream *stream);
gboolean gvc_mixer_stream_get_is_muted (GvcMixerStream *stream);
gboolean gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream);
gboolean gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
gboolean is_muted);
gboolean gvc_mixer_stream_is_running (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_name (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_icon_name (GvcMixerStream *stream);
GIcon * gvc_mixer_stream_get_gicon (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_description (GvcMixerStream *stream);
const char * gvc_mixer_stream_get_application_id (GvcMixerStream *stream);
gboolean gvc_mixer_stream_is_event_stream (GvcMixerStream *stream);
gboolean gvc_mixer_stream_is_virtual (GvcMixerStream *stream);
gint gvc_mixer_stream_get_card_index (GvcMixerStream *stream);
/* private */
gboolean gvc_mixer_stream_set_volume (GvcMixerStream *stream,
pa_volume_t volume);
gboolean gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
gdouble db);
gboolean gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
gboolean is_muted);
gboolean gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream,
gboolean can_decibel);
gboolean gvc_mixer_stream_set_name (GvcMixerStream *stream,
const char *name);
gboolean gvc_mixer_stream_set_description (GvcMixerStream *stream,
const char *description);
gboolean gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
const char *name);
gboolean gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
gboolean is_event_stream);
gboolean gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
gboolean is_event_stream);
gboolean gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
const char *application_id);
gboolean gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
pa_volume_t base_volume);
gboolean gvc_mixer_stream_set_port (GvcMixerStream *stream,
const char *port);
gboolean gvc_mixer_stream_set_ports (GvcMixerStream *stream,
GList *ports);
gboolean gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
gint card_index);
G_END_DECLS
#endif /* __GVC_MIXER_STREAM_H */

View File

@@ -0,0 +1,34 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GVC_PULSEAUDIO_FAKE_H
#define __GVC_PULSEAUDIO_FAKE_H
#ifdef WITH_INTROSPECTION
#ifndef PA_API_VERSION
#define pa_channel_position_t int
#define pa_volume_t guint32
#define pa_context gpointer
#endif /* PA_API_VERSION */
#endif /* WITH_INTROSPECTION */
#endif /* __GVC_PULSEAUDIO_FAKE_H */

View File

@@ -174,8 +174,6 @@ shell_prefs_init (void)
OVERRIDES_SCHEMA); OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("workspaces-only-on-primary", meta_prefs_override_preference_schema ("workspaces-only-on-primary",
OVERRIDES_SCHEMA); OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("button-layout",
OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("edge-tiling", meta_prefs_override_preference_schema ("edge-tiling",
OVERRIDES_SCHEMA); OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("focus-change-on-pointer-rest", meta_prefs_override_preference_schema ("focus-change-on-pointer-rest",

View File

@@ -738,8 +738,7 @@ normalize_terms (GSList *terms)
for (iter = terms; iter; iter = iter->next) for (iter = terms; iter; iter = iter->next)
{ {
const char *term = iter->data; const char *term = iter->data;
normalized_terms = g_slist_prepend (normalized_terms, normalized_terms = g_slist_prepend (normalized_terms, shell_util_normalize_and_casefold (term));
shell_util_normalize_casefold_and_unaccent (term));
} }
return normalized_terms; return normalized_terms;
} }

View File

@@ -785,19 +785,16 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
} }
else if (strcmp (element_name, "context") == 0) else if (strcmp (element_name, "context") == 0)
{ {
char *id = NULL; char *context = NULL;
const char **attribute; const char **attribute;
const char **value; const char **value;
for (attribute = attribute_names, value = attribute_values; *attribute; attribute++, value++) for (attribute = attribute_names, value = attribute_values; *attribute; attribute++, value++)
{ {
if (strcmp (*attribute, "id") == 0) if (strcmp (*attribute, "id") == 0)
{ context = g_strdup (*value);
id = g_strdup (*value);
break;
}
} }
if (!id) if (context < 0)
{ {
g_set_error (error, g_set_error (error,
G_MARKUP_ERROR, G_MARKUP_ERROR,
@@ -806,7 +803,7 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
element_name); element_name);
return; return;
} }
data->context = id; data->context = context;
} }
else if (strcmp (element_name, "application") == 0) else if (strcmp (element_name, "application") == 0)
{ {
@@ -819,10 +816,7 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
for (attribute = attribute_names, value = attribute_values; *attribute; attribute++, value++) for (attribute = attribute_names, value = attribute_values; *attribute; attribute++, value++)
{ {
if (strcmp (*attribute, "id") == 0) if (strcmp (*attribute, "id") == 0)
{ appid = g_strdup (*value);
appid = g_strdup (*value);
break;
}
} }
if (!appid) if (!appid)

View File

@@ -1319,16 +1319,16 @@ shell_app_init_search_data (ShellApp *app)
appinfo = gmenu_tree_entry_get_app_info (app->entry); appinfo = gmenu_tree_entry_get_app_info (app->entry);
name = g_app_info_get_name (G_APP_INFO (appinfo)); name = g_app_info_get_name (G_APP_INFO (appinfo));
app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name); app->casefolded_name = shell_util_normalize_and_casefold (name);
generic_name = g_desktop_app_info_get_generic_name (appinfo); generic_name = g_desktop_app_info_get_generic_name (appinfo);
if (generic_name) if (generic_name)
app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name); app->casefolded_generic_name = shell_util_normalize_and_casefold (generic_name);
else else
app->casefolded_generic_name = NULL; app->casefolded_generic_name = NULL;
exec = g_app_info_get_executable (G_APP_INFO (appinfo)); exec = g_app_info_get_executable (G_APP_INFO (appinfo));
normalized_exec = shell_util_normalize_casefold_and_unaccent (exec); normalized_exec = shell_util_normalize_and_casefold (exec);
app->casefolded_exec = trim_exec_line (normalized_exec); app->casefolded_exec = trim_exec_line (normalized_exec);
g_free (normalized_exec); g_free (normalized_exec);
@@ -1343,7 +1343,7 @@ shell_app_init_search_data (ShellApp *app)
i = 0; i = 0;
while (keywords[i]) while (keywords[i])
{ {
app->casefolded_keywords[i] = shell_util_normalize_casefold_and_unaccent (keywords[i]); app->casefolded_keywords[i] = shell_util_normalize_and_casefold (keywords[i]);
++i; ++i;
} }
app->casefolded_keywords[i] = NULL; app->casefolded_keywords[i] = NULL;

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