Compare commits
171 Commits
3.7.2
...
wip/re-sea
Author | SHA1 | Date | |
---|---|---|---|
3124e82838 | |||
6c4daaaa71 | |||
3768e85673 | |||
d1c72e1e4c | |||
2498497cc1 | |||
7c3c6da368 | |||
09e7ab5611 | |||
53cff07eef | |||
cfed6e401d | |||
12b041a569 | |||
f2dd94776c | |||
c0f9c52ba6 | |||
2ee8b0e427 | |||
b250a72fcf | |||
cf08745f6c | |||
58023c81ad | |||
7e8968da52 | |||
fce1d8157e | |||
3b5de01ed6 | |||
a61da42aa7 | |||
81acfdbfc3 | |||
159b789443 | |||
c07b715a3a | |||
1bb09fd0f1 | |||
4441541da6 | |||
afee4d6925 | |||
b62bd0e62f | |||
13b83c95b7 | |||
e48dbe65f1 | |||
14fb51e6d7 | |||
b42af9aa99 | |||
ca2ee22827 | |||
13a2b28bf1 | |||
04bf75d137 | |||
76c589702f | |||
c11f89e72a | |||
cfacb05461 | |||
c4ba31cb23 | |||
db0eacddc5 | |||
62972f5138 | |||
6fe263f19f | |||
b6a87acb71 | |||
784b04b191 | |||
3af9f636af | |||
16c0585b95 | |||
fc9a96ac85 | |||
9dfc3af9d7 | |||
8dc63932fc | |||
066e5cddb5 | |||
27ffad2148 | |||
41db363b06 | |||
184ac11c93 | |||
673aa3c5f2 | |||
2dd1c04bf3 | |||
4df1222ce7 | |||
208121646c | |||
f47a11f792 | |||
36fc3a5c96 | |||
ed12c9d611 | |||
4153feeb15 | |||
349c642d10 | |||
4728105f43 | |||
1f46a0dc26 | |||
7ff7ced504 | |||
a43ee41b0b | |||
ec7ade4ee6 | |||
9b846cbb83 | |||
2cc7fd07f8 | |||
72d54d9915 | |||
b390b82e9d | |||
1ef9ee13a3 | |||
6822795bb8 | |||
187dec2816 | |||
31f75e4607 | |||
92083eaf76 | |||
6b40c3974d | |||
c528401b62 | |||
8a17f512f4 | |||
e725f8a0fe | |||
525d3c2619 | |||
aba46720c0 | |||
2fb1d707fe | |||
dd06aa98ad | |||
cfb66ca153 | |||
0b4660702b | |||
9760227c66 | |||
5faeaa2028 | |||
cd58f9f9e5 | |||
00338bbc4b | |||
31d14a2fb0 | |||
49fa0ddebc | |||
d50c3e6c67 | |||
b39f56e813 | |||
ead0286ca6 | |||
6eb05af306 | |||
6b1e632621 | |||
29cb10fed8 | |||
a88433dba6 | |||
7e5f1fe411 | |||
00c78d33e4 | |||
50fbf9982e | |||
71ad39b6e3 | |||
3d329cdf2d | |||
21af5c8f73 | |||
716d7bb93e | |||
98f4b99446 | |||
830e701d13 | |||
57d9e7d5aa | |||
5fc16bb05b | |||
cb08bd2e2e | |||
961dba7faa | |||
41f933b89e | |||
d4dc1c87c5 | |||
e58fbeea17 | |||
2492dc50db | |||
b4f5f1e461 | |||
69347fff09 | |||
5c439f4e9c | |||
c84236ed73 | |||
ae1a3a0cb2 | |||
b3fea016f1 | |||
7c93639e59 | |||
affcd5c7de | |||
e00eb06f66 | |||
5ecc204d57 | |||
2a5eed1eb4 | |||
d517c13d7a | |||
bb88265d78 | |||
858694f4cc | |||
a46321baa0 | |||
9808e8ab0d | |||
7bd7b53845 | |||
056cfc9dc6 | |||
b7b60d103e | |||
14fd0eb73e | |||
ca73017100 | |||
123fb350ce | |||
1a27d7dfc0 | |||
b0c6d44515 | |||
6092e01428 | |||
e20ff5ae45 | |||
621a0d70e2 | |||
855b238ec5 | |||
96f44e1959 | |||
242dc8cddd | |||
b8a2004872 | |||
63f08bf2c2 | |||
4734a9ac18 | |||
81cd1e6c40 | |||
0b9cdea7d2 | |||
f63fceb2ea | |||
f0f7165ab6 | |||
2511f60d39 | |||
c0f868dd56 | |||
a112bfdaa2 | |||
4535a70f08 | |||
b59529e579 | |||
393c23820a | |||
e6a3958e45 | |||
59a7fdd2c9 | |||
c3cab28c9b | |||
4c55a6f436 | |||
c10e4c3117 | |||
3b70094151 | |||
a370697385 | |||
8a7c0313f6 | |||
00201f7e6c | |||
5e3111bad8 | |||
a327c10c60 | |||
938bc07e3c | |||
d053d45a6d |
3
.gitignore
vendored
3
.gitignore
vendored
@ -38,6 +38,7 @@ docs/reference/*/*.txt
|
||||
docs/reference/*/*.types
|
||||
docs/reference/*/html/
|
||||
docs/reference/*/xml/
|
||||
docs/reference/shell/doc-gen-*
|
||||
gtk-doc.make
|
||||
js/misc/config.js
|
||||
intltool-extract.in
|
||||
@ -85,6 +86,8 @@ src/test-theme
|
||||
src/st.h
|
||||
src/stamp-st.h
|
||||
src/stamp-st.h.tmp
|
||||
src/st-scroll-view-fade-generated.c
|
||||
src/stamp-st-scroll-view-fade-generated.c
|
||||
stamp-h1
|
||||
tests/run-test.sh
|
||||
xmldocs.make
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "src/gvc"]
|
||||
path = src/gvc
|
||||
url = git://git.gnome.org/libgnome-volume-control
|
@ -13,6 +13,14 @@ PKG_NAME="gnome-shell"
|
||||
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 || {
|
||||
echo "You need to install gnome-common from GNOME Git (or from"
|
||||
echo "your OS vendor's package manager)."
|
||||
|
@ -269,6 +269,7 @@ AC_CONFIG_FILES([
|
||||
js/Makefile
|
||||
src/calendar-server/evolution-calendar.desktop.in
|
||||
src/Makefile
|
||||
src/gvc/Makefile
|
||||
browser-plugin/Makefile
|
||||
tests/Makefile
|
||||
po/Makefile.in
|
||||
|
@ -11,7 +11,9 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
introspectiondir = $(datadir)/dbus-1/interfaces
|
||||
introspection_DATA = org.gnome.ShellSearchProvider.xml
|
||||
introspection_DATA = \
|
||||
org.gnome.ShellSearchProvider.xml \
|
||||
org.gnome.ShellSearchProvider2.xml
|
||||
|
||||
themedir = $(pkgdatadir)/theme
|
||||
dist_theme_DATA = \
|
||||
@ -32,6 +34,7 @@ dist_theme_DATA = \
|
||||
theme/gnome-shell.css \
|
||||
theme/logged-in-indicator.svg \
|
||||
theme/message-tray-background.png \
|
||||
theme/more-results.svg \
|
||||
theme/noise-texture.png \
|
||||
theme/panel-button-border.svg \
|
||||
theme/panel-button-highlight-narrow.svg \
|
||||
|
@ -2,146 +2,72 @@
|
||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
|
||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
|
||||
<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">
|
||||
<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">
|
||||
<doc:doc>
|
||||
<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>
|
||||
<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">
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<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>
|
||||
<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).
|
||||
|
||||
Return an array of meta data used to display each given result
|
||||
-->
|
||||
<method name="GetResultMetas">
|
||||
<doc:doc>
|
||||
<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>
|
||||
<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()
|
||||
|
||||
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">
|
||||
<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>
|
||||
<arg type="s" name="identifier" direction="in" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
|
87
data/org.gnome.ShellSearchProvider2.xml
Normal file
87
data/org.gnome.ShellSearchProvider2.xml
Normal file
@ -0,0 +1,87 @@
|
||||
<!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>
|
@ -65,6 +65,21 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
||||
menuitem in single-user, single-session situations.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="show-full-name" type="b">
|
||||
<default>true</default>
|
||||
<_summary>Show full name in the user menu</_summary>
|
||||
<_description>Whether the users full name is shown in the user menu or not.</_description>
|
||||
</key>
|
||||
<key name="remember-mount-password" type="b">
|
||||
<default>false</default>
|
||||
<_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary>
|
||||
<_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="recorder" schema="org.gnome.shell.recorder"/>
|
||||
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
|
||||
@ -171,6 +186,33 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
||||
</key>
|
||||
</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/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="attach-modal-dialogs" type="b">
|
||||
|
@ -49,7 +49,7 @@ stage {
|
||||
.switcher-list,
|
||||
.app-well-app > .overview-icon,
|
||||
.show-apps > .overview-icon,
|
||||
.search-result-content > .overview-icon {
|
||||
.grid-search-result .overview-icon {
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
@ -405,11 +405,13 @@ StScrollBar StButton#vhandle:active {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.login-dialog-prompt-entry:insensitive {
|
||||
color: rgba(0,0,0,0.7);
|
||||
border: 2px solid #565656;
|
||||
background-gradient-start: rgb(200,200,200);
|
||||
background-gradient-end: rgb(210,210,210);
|
||||
.modal-dialog StEntry:insensitive {
|
||||
border-color: #666666;
|
||||
color: #9f9f9f;
|
||||
border: 2px solid #9f9f9f;
|
||||
background-gradient-direction: none;
|
||||
background-color: rgba(102, 102, 102, 0.15);
|
||||
box-shadow: inset 0 0 rgba(0,0,0,1.0);
|
||||
}
|
||||
|
||||
/* Panel */
|
||||
@ -418,6 +420,18 @@ StScrollBar StButton#vhandle:active {
|
||||
background-color: black;
|
||||
font-weight: bold;
|
||||
height: 1.86em;
|
||||
transition-duration: 250;
|
||||
}
|
||||
|
||||
#panel.lock-screen {
|
||||
height: 2em;
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
#panel.unlock-screen,
|
||||
#panel.login-screen {
|
||||
height: 2em;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#panelLeft, #panelCenter {
|
||||
@ -453,6 +467,13 @@ StScrollBar StButton#vhandle:active {
|
||||
-panel-corner-border-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
.panel-corner.lock-screen,
|
||||
.panel-corner.unlock-screen,
|
||||
.panel-corner.login-screen {
|
||||
-panel-corner-background-color: transparent;
|
||||
-panel-corner-border-color: transparent;
|
||||
}
|
||||
|
||||
#appMenu {
|
||||
spacing: 4px;
|
||||
}
|
||||
@ -485,6 +506,24 @@ StScrollBar StButton#vhandle:active {
|
||||
transition-duration: 100;
|
||||
}
|
||||
|
||||
#panel.unlock-screen .panel-button,
|
||||
#panel.lock-screen .panel-button,
|
||||
#panel.login-screen .panel-button {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
#panel.unlock-screen .panel-button:hover,
|
||||
#panel.lock-screen .panel-button:hover,
|
||||
#panel.login-screen .panel-button:hover,
|
||||
#panel.unlock-screen .panel-button:active,
|
||||
#panel.lock-screen .panel-button:active,
|
||||
#panel.login-screen .panel-button:active,
|
||||
#panel.unlock-screen .panel-button:focus,
|
||||
#panel.lock-screen .panel-button:focus,
|
||||
#panel.login-screen .panel-button:focus {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.panel-button:hover {
|
||||
color: white;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
@ -577,12 +616,12 @@ StScrollBar StButton#vhandle:active {
|
||||
spacing: 40px;
|
||||
}
|
||||
|
||||
.window-caption {
|
||||
spacing: 25px;
|
||||
#overview-group {
|
||||
spacing: 32px;
|
||||
}
|
||||
|
||||
.workspace-controls {
|
||||
visible-width: 32px; /* Amount visible before hovering */
|
||||
.window-caption {
|
||||
spacing: 25px;
|
||||
}
|
||||
|
||||
.workspace-thumbnails-background {
|
||||
@ -602,6 +641,7 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.workspace-thumbnails {
|
||||
spacing: 11px;
|
||||
visible-width: 96px;
|
||||
}
|
||||
|
||||
.workspace-thumbnail-indicator {
|
||||
@ -615,6 +655,7 @@ StScrollBar StButton#vhandle:active {
|
||||
border-radius: 8px;
|
||||
padding: 4px 12px;
|
||||
-shell-caption-spacing: 12px;
|
||||
border: 2px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.window-close, .notification-close {
|
||||
@ -625,7 +666,16 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.window-close {
|
||||
-shell-close-overlap: 20px;
|
||||
-shell-close-overlap: 16px;
|
||||
}
|
||||
|
||||
.window-caption:hover {
|
||||
border: 2px solid rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
.window-clone-border {
|
||||
border: 4px solid rgba(255, 255, 255, 0.5);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.notification-close {
|
||||
@ -705,25 +755,33 @@ StScrollBar StButton#vhandle:active {
|
||||
/* Search Results */
|
||||
|
||||
#searchResults {
|
||||
padding: 20px 10px 10px 10px;
|
||||
spacing: 18px;
|
||||
}
|
||||
|
||||
#searchResultsContent {
|
||||
padding-right: 20px;
|
||||
spacing: 36px;
|
||||
}
|
||||
spacing: 16px;
|
||||
|
||||
#searchResultsContent:rtl {
|
||||
padding-right: 0px;
|
||||
/* for scrollbars */
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.search-section-header {
|
||||
padding: 4px 12px;
|
||||
spacing: 4px;
|
||||
color: #6f6f6f;
|
||||
font-size: .8em;
|
||||
.search-section {
|
||||
/* This should be equal to #searchResultsContent spacing */
|
||||
spacing: 16px;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@ -732,16 +790,8 @@ StScrollBar StButton#vhandle:active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.search-section-results {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.search-section-list-results {
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.results-container {
|
||||
spacing: 4px;
|
||||
.list-search-results {
|
||||
spacing: 3px;
|
||||
}
|
||||
|
||||
/* Text labels are an odd number of pixels tall. The uneven top and bottom
|
||||
@ -770,7 +820,7 @@ StScrollBar StButton#vhandle:active {
|
||||
-x-offset: 8px;
|
||||
}
|
||||
|
||||
/* Application Launchers and Grid */
|
||||
/* Application Launchers, Grid and List results */
|
||||
|
||||
.icon-grid {
|
||||
spacing: 36px;
|
||||
@ -783,15 +833,10 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.all-app {
|
||||
padding: 16px 25px 16px 16px;
|
||||
padding: 16px;
|
||||
spacing: 20px;
|
||||
}
|
||||
|
||||
.all-app:rtl {
|
||||
padding-right: 16px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.app-filter {
|
||||
font-weight: bold;
|
||||
height: 2.85em;
|
||||
@ -822,9 +867,34 @@ StScrollBar StButton#vhandle:active {
|
||||
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,
|
||||
.show-apps > .overview-icon,
|
||||
.search-result-content > .overview-icon {
|
||||
.search-provider-icon,
|
||||
.list-search-result,
|
||||
.grid-search-result .overview-icon {
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
border: 1px rgba(0,0,0,0);
|
||||
@ -840,7 +910,9 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.app-well-app:hover > .overview-icon,
|
||||
.show-apps:hover > .overview-icon,
|
||||
.search-result-content:hover > .overview-icon {
|
||||
.search-provider-icon:hover,
|
||||
.list-search-result:hover,
|
||||
.grid-search-result:hover .overview-icon {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
text-shadow: black 0px 2px 2px;
|
||||
transition-duration: 100;
|
||||
@ -875,10 +947,14 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.app-well-app:focus > .overview-icon,
|
||||
.search-result-content:focus > .overview-icon,
|
||||
.grid-search-result:focus .overview-icon,
|
||||
.show-apps:focus > .overview-icon,
|
||||
.search-provider-icon:focus,
|
||||
.list-search-result:focus,
|
||||
.app-well-app:selected > .overview-icon,
|
||||
.search-result-content:selected > .overview-icon {
|
||||
.grid-search-result:selected .overview-icon,
|
||||
.search-provider-icon:selected,
|
||||
.list-search-result:selected {
|
||||
background-color: rgba(255,255,255,0.33);
|
||||
}
|
||||
|
||||
@ -1222,6 +1298,12 @@ StScrollBar StButton#vhandle:active {
|
||||
outline: 1px solid rgba(128, 128, 128, 0.3);
|
||||
}
|
||||
|
||||
.no-messages-label {
|
||||
font-family: cantarell, sans-serif;
|
||||
font-size: 11pt;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.notification {
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
@ -1255,7 +1337,7 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.summary-boxpointer {
|
||||
-arrow-border-radius: 8px;
|
||||
-arrow-border-radius: 15px;
|
||||
-arrow-background-color: rgba(0,0,0,0.8);
|
||||
-arrow-base: 36px;
|
||||
-arrow-rise: 18px;
|
||||
@ -1276,8 +1358,8 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.summary-notification-stack-scrollview {
|
||||
max-height: 18em;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.summary-notification-stack-scrollview:ltr {
|
||||
@ -1477,17 +1559,17 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.summary-source-counter {
|
||||
background-image: url("summary-counter.svg");
|
||||
background-size: 2.5em;
|
||||
background-size: 2.4em;
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
height: 2.5em;
|
||||
width: 2.5em;
|
||||
-shell-counter-overlap-x: 4px;
|
||||
-shell-counter-overlap-y: 4px;
|
||||
height: 2.4em;
|
||||
width: 2.4em;
|
||||
-shell-counter-overlap-x: 13px;
|
||||
-shell-counter-overlap-y: 13px;
|
||||
}
|
||||
|
||||
/* App Switcher */
|
||||
#altTabPopup {
|
||||
.switcher-popup {
|
||||
padding: 8px;
|
||||
spacing: 16px;
|
||||
}
|
||||
@ -2195,6 +2277,10 @@ StScrollBar StButton#vhandle:active {
|
||||
height: .75em;
|
||||
}
|
||||
|
||||
.login-dialog .modal-dialog-button-box {
|
||||
spacing: 3px;
|
||||
}
|
||||
|
||||
.login-dialog .modal-dialog-button {
|
||||
border-radius: 5px;
|
||||
padding: 3px 18px;
|
||||
@ -2300,16 +2386,21 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.screen-shield-notification-source {
|
||||
padding: 0 24px;
|
||||
padding: 13px 24px;
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
.screen-shield-notification-label {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
padding: 0px 18px;
|
||||
color: #babdb6;
|
||||
}
|
||||
|
||||
.screen-shield-notification-count-text {
|
||||
padding: 0px 18px;
|
||||
}
|
||||
|
||||
/* Remove background from notifications, otherwise
|
||||
opacity is doubled and they look darker
|
||||
*/
|
||||
|
93
data/theme/more-results.svg
Normal file
93
data/theme/more-results.svg
Normal file
@ -0,0 +1,93 @@
|
||||
<?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+devel r11908 custom"
|
||||
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="7.4498765"
|
||||
inkscape:cy="9.9072581"
|
||||
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="1600"
|
||||
inkscape:window-y="27"
|
||||
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></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:0.38207546;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
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)" />
|
||||
<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>
|
After Width: | Height: | Size: 3.7 KiB |
@ -76,9 +76,23 @@ endif
|
||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
||||
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).
|
||||
# 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
|
||||
# These files must be listed here *and* in content_files
|
||||
|
@ -43,6 +43,8 @@
|
||||
</chapter>
|
||||
<chapter>
|
||||
<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-wm.xml"/>
|
||||
<xi:include href="xml/shell-xfixes-cursor.xml"/>
|
||||
|
@ -52,13 +52,6 @@ its dependencies to build from tarballs.</description>
|
||||
<gnome:userid>walters</gnome:userid>
|
||||
</foaf:Person>
|
||||
</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>
|
||||
<foaf:Person>
|
||||
<foaf:name>Marina Zhurakhinskaya</foaf:name>
|
||||
|
@ -41,6 +41,7 @@ nobase_dist_js_DATA = \
|
||||
ui/boxpointer.js \
|
||||
ui/calendar.js \
|
||||
ui/checkBox.js \
|
||||
ui/centerLayout.js \
|
||||
ui/ctrlAltTab.js \
|
||||
ui/dash.js \
|
||||
ui/dateMenu.js \
|
||||
@ -62,6 +63,7 @@ nobase_dist_js_DATA = \
|
||||
ui/main.js \
|
||||
ui/messageTray.js \
|
||||
ui/modalDialog.js \
|
||||
ui/separator.js \
|
||||
ui/sessionMode.js \
|
||||
ui/shellEntry.js \
|
||||
ui/shellMountOperation.js \
|
||||
@ -85,6 +87,7 @@ nobase_dist_js_DATA = \
|
||||
ui/status/power.js \
|
||||
ui/status/volume.js \
|
||||
ui/status/bluetooth.js \
|
||||
ui/switcherPopup.js \
|
||||
ui/tweener.js \
|
||||
ui/unlockDialog.js \
|
||||
ui/userMenu.js \
|
||||
|
@ -39,6 +39,7 @@ const GdmUtil = imports.gdm.util;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const Panel = imports.ui.panel;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const UserMenu = imports.ui.userMenu;
|
||||
@ -48,6 +49,10 @@ const _SCROLL_ANIMATION_TIME = 0.5;
|
||||
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
|
||||
const _LOGO_ICON_HEIGHT = 16;
|
||||
|
||||
const WORK_SPINNER_ICON_SIZE = 24;
|
||||
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
const WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
let _loginDialog = null;
|
||||
|
||||
function _smoothlyResizeActor(actor, width, height) {
|
||||
@ -604,6 +609,14 @@ const SessionList = new Lang.Class({
|
||||
this.close();
|
||||
},
|
||||
|
||||
updateSensitivity: function(sensitive) {
|
||||
this._button.reactive = sensitive;
|
||||
this._button.can_focus = sensitive;
|
||||
|
||||
for (let id in this._items)
|
||||
this._items[id].actor.reactive = sensitive;
|
||||
},
|
||||
|
||||
setActiveSession: function(sessionId) {
|
||||
if (sessionId == this._activeSessionId)
|
||||
return;
|
||||
@ -685,6 +698,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
|
||||
this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
|
||||
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
|
||||
this._userVerifier.connect('verification-failed', Lang.bind(this, this._verificationFailed));
|
||||
this._userVerifier.connect('reset', Lang.bind(this, this._reset));
|
||||
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
||||
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
||||
@ -750,6 +764,9 @@ const LoginDialog = new Lang.Class({
|
||||
this._promptLoginHint.hide();
|
||||
this._promptBox.add(this._promptLoginHint);
|
||||
|
||||
this._signInButton = null;
|
||||
this._workSpinner = null;
|
||||
|
||||
this._sessionList = new SessionList();
|
||||
this._sessionList.connect('session-activated',
|
||||
Lang.bind(this, function(list, sessionId) {
|
||||
@ -829,6 +846,7 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
this._updateSensitivity(true);
|
||||
this._promptMessage.hide();
|
||||
this._user = null;
|
||||
this._verifyingUser = false;
|
||||
@ -839,6 +857,13 @@ const LoginDialog = new Lang.Class({
|
||||
this._showUserList();
|
||||
},
|
||||
|
||||
_verificationFailed: function() {
|
||||
this._promptEntry.text = '';
|
||||
|
||||
this._updateSensitivity(true);
|
||||
this._setWorking(false);
|
||||
},
|
||||
|
||||
_onDefaultSessionChanged: function(client, sessionId) {
|
||||
this._sessionList.setActiveSession(sessionId);
|
||||
},
|
||||
@ -909,35 +934,12 @@ const LoginDialog = new Lang.Class({
|
||||
_showPrompt: function(forSecret) {
|
||||
let hold = new Batch.Hold();
|
||||
|
||||
let cancelButtonInfo = { action: Lang.bind(this, this.cancel),
|
||||
label: _("Cancel"),
|
||||
key: Clutter.Escape };
|
||||
let okButtonInfo = { action: Lang.bind(this, function() {
|
||||
hold.release();
|
||||
}),
|
||||
label: forSecret ? C_("button", "Sign In") : _("Next"),
|
||||
default: true };
|
||||
let buttons = [];
|
||||
if (!this._disableUserList || this._verifyingUser)
|
||||
buttons.push(cancelButtonInfo);
|
||||
buttons.push(okButtonInfo);
|
||||
|
||||
let tasks = [function() {
|
||||
return this._fadeInPrompt();
|
||||
},
|
||||
|
||||
function() {
|
||||
this.setButtons(buttons);
|
||||
|
||||
let updateOkButtonEnabled = Lang.bind(this, function() {
|
||||
let sensitive = this._promptEntry.text.length > 0;
|
||||
okButtonInfo.button.reactive = sensitive;
|
||||
okButtonInfo.button.can_focus = sensitive;
|
||||
});
|
||||
|
||||
updateOkButtonEnabled();
|
||||
|
||||
this._promptEntryTextChangedId = this._promptEntry.clutter_text.connect('text-changed', updateOkButtonEnabled);
|
||||
this._prepareDialog(forSecret, hold);
|
||||
},
|
||||
|
||||
hold];
|
||||
@ -947,6 +949,63 @@ const LoginDialog = new Lang.Class({
|
||||
return batch.run();
|
||||
},
|
||||
|
||||
_prepareDialog: function(forSecret, hold) {
|
||||
this._workSpinner = new Panel.AnimatedIcon('process-working.svg', WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
this._workSpinner.actor.show();
|
||||
|
||||
this.buttonLayout.visible = true;
|
||||
this.clearButtons();
|
||||
|
||||
if (!this._disableUserList || this._verifyingUser)
|
||||
this.addButton({ action: Lang.bind(this, this.cancel),
|
||||
label: _("Cancel"),
|
||||
key: Clutter.Escape },
|
||||
{ expand: true,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this.buttonLayout.add(this._workSpinner.actor,
|
||||
{ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._signInButton = this.addButton({ action: Lang.bind(this, function() {
|
||||
hold.release();
|
||||
}),
|
||||
label: forSecret ? C_("button", "Sign In") : _("Next"),
|
||||
default: true },
|
||||
{ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
|
||||
|
||||
this._promptEntryTextChangedId =
|
||||
this._promptEntry.clutter_text.connect('text-changed',
|
||||
Lang.bind(this, function() {
|
||||
this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
|
||||
}));
|
||||
},
|
||||
|
||||
_updateSensitivity: function(sensitive) {
|
||||
this._promptEntry.reactive = sensitive;
|
||||
this._promptEntry.clutter_text.editable = sensitive;
|
||||
this._sessionList.updateSensitivity(sensitive);
|
||||
this._updateSignInButtonSensitivity(sensitive);
|
||||
},
|
||||
|
||||
_updateSignInButtonSensitivity: function(sensitive) {
|
||||
if (this._signInButton) {
|
||||
this._signInButton.reactive = sensitive;
|
||||
this._signInButton.can_focus = sensitive;
|
||||
}
|
||||
},
|
||||
|
||||
_hidePrompt: function() {
|
||||
this.setButtons([]);
|
||||
|
||||
@ -956,13 +1015,20 @@ const LoginDialog = new Lang.Class({
|
||||
}
|
||||
|
||||
let tasks = [function() {
|
||||
this._setWorking(false);
|
||||
|
||||
return GdmUtil.fadeOutActor(this._promptBox);
|
||||
},
|
||||
|
||||
function() {
|
||||
this._promptLoginHint.hide();
|
||||
this._promptEntry.reactive = true;
|
||||
|
||||
this._updateSensitivity(true);
|
||||
this._promptEntry.set_text('');
|
||||
|
||||
this.clearButtons();
|
||||
this._workSpinner = null;
|
||||
this._signInButton = null;
|
||||
}];
|
||||
|
||||
let batch = new Batch.ConsecutiveBatch(this, tasks);
|
||||
@ -970,6 +1036,31 @@ const LoginDialog = new Lang.Class({
|
||||
return batch.run();
|
||||
},
|
||||
|
||||
_setWorking: function(working) {
|
||||
if (!this._workSpinner)
|
||||
return;
|
||||
|
||||
if (working) {
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_askQuestion: function(verifier, serviceName, question, passwordChar) {
|
||||
this._promptLabel.set_text(question);
|
||||
|
||||
@ -981,9 +1072,10 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
function() {
|
||||
let _text = this._promptEntry.get_text();
|
||||
this._promptEntry.reactive = false;
|
||||
this._userVerifier.answerQuery(serviceName, _text);
|
||||
let text = this._promptEntry.get_text();
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(true);
|
||||
this._userVerifier.answerQuery(serviceName, text);
|
||||
}];
|
||||
|
||||
let batch = new Batch.ConsecutiveBatch(this, tasks);
|
||||
|
@ -11,6 +11,7 @@ const Gio = imports.gi.Gio;
|
||||
const ShellJS = imports.gi.ShellJS;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const FileUtils = imports.misc.fileUtils;
|
||||
|
||||
const ExtensionType = {
|
||||
SYSTEM: 1,
|
||||
@ -150,53 +151,35 @@ function installImporter(extension) {
|
||||
const ExtensionFinder = new Lang.Class({
|
||||
Name: 'ExtensionFinder',
|
||||
|
||||
_scanExtensionsInDirectory: function(dir, type) {
|
||||
let fileEnum;
|
||||
let file, info;
|
||||
try {
|
||||
fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
|
||||
} catch(e) {
|
||||
if (e.domain != Gio.io_error_quark() || e.code != Gio.IOErrorEnum.NOT_FOUND)
|
||||
logError(e, 'Could not enumerate extensions directory');
|
||||
_loadExtension: function(extensionDir, info, perUserDir) {
|
||||
let fileType = info.get_file_type();
|
||||
if (fileType != Gio.FileType.DIRECTORY)
|
||||
return;
|
||||
let uuid = info.get_name();
|
||||
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()));
|
||||
return;
|
||||
}
|
||||
|
||||
while ((info = fileEnum.next_file(null)) != null) {
|
||||
let fileType = info.get_file_type();
|
||||
if (fileType != Gio.FileType.DIRECTORY)
|
||||
continue;
|
||||
let uuid = info.get_name();
|
||||
let extensionDir = dir.get_child(uuid);
|
||||
|
||||
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);
|
||||
let extension;
|
||||
let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER
|
||||
: ExtensionType.SYSTEM;
|
||||
try {
|
||||
extension = createExtensionObject(uuid, extensionDir, type);
|
||||
} catch(e) {
|
||||
logError(e, 'Could not load extension %s'.format(uuid));
|
||||
return;
|
||||
}
|
||||
fileEnum.close(null);
|
||||
this.emit('extension-found', extension);
|
||||
},
|
||||
|
||||
scanExtensions: function() {
|
||||
let userExtensionsDir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions']));
|
||||
this._scanExtensionsInDirectory(userExtensionsDir, ExtensionType.PER_USER);
|
||||
|
||||
let systemDataDirs = GLib.get_system_data_dirs();
|
||||
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);
|
||||
}
|
||||
let perUserDir = Gio.File.new_for_path(global.userdatadir);
|
||||
FileUtils.collectFromDatadirsAsync('extensions',
|
||||
{ processFile: Lang.bind(this, this._loadExtension),
|
||||
includeUserDir: true,
|
||||
data: perUserDir });
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ExtensionFinder.prototype);
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
function listDirAsync(file, callback) {
|
||||
let allFiles = [];
|
||||
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME,
|
||||
file.enumerate_children_async('standard::name,standard::type',
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
GLib.PRIORITY_LOW, null, function (obj, res) {
|
||||
let enumerator = obj.enumerate_children_finish(res);
|
||||
@ -23,6 +25,63 @@ 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) {
|
||||
// Work around 'delete' being a keyword in JS.
|
||||
return file['delete'](null);
|
||||
|
861
js/ui/altTab.js
861
js/ui/altTab.js
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const GMenu = imports.gi.GMenu;
|
||||
@ -18,7 +19,6 @@ const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Search = imports.ui.search;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Workspace = imports.ui.workspace;
|
||||
const Params = imports.misc.params;
|
||||
@ -48,18 +48,16 @@ const AlphabeticalView = new Lang.Class({
|
||||
style_class: 'vfade' });
|
||||
this.actor.add_actor(box);
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
||||
function() {
|
||||
if (!this.actor.mapped)
|
||||
return;
|
||||
let action = new Clutter.PanAction({ interpolate: true });
|
||||
action.connect('pan', Lang.bind(this, this._onPan));
|
||||
this.actor.add_action(action);
|
||||
},
|
||||
|
||||
let adjustment = this.actor.vscroll.adjustment;
|
||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
||||
Main.overview.setScrollAdjustment(adjustment, direction);
|
||||
|
||||
// Reset scroll on mapping
|
||||
adjustment.value = 0;
|
||||
}));
|
||||
_onPan: function(action) {
|
||||
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||
let adjustment = this.actor.vscroll.adjustment;
|
||||
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||
return false;
|
||||
},
|
||||
|
||||
removeAll: function() {
|
||||
@ -216,6 +214,16 @@ const ViewByCategories = new Lang.Class({
|
||||
},
|
||||
|
||||
_addCategory: function(name, index, dir) {
|
||||
let apps;
|
||||
|
||||
if (dir != null) {
|
||||
apps = [];
|
||||
this._loadCategory(dir, apps);
|
||||
|
||||
if (apps.length == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
|
||||
style_class: 'app-filter',
|
||||
x_align: St.Align.START,
|
||||
@ -225,18 +233,16 @@ const ViewByCategories = new Lang.Class({
|
||||
this._selectCategory(index);
|
||||
}));
|
||||
|
||||
var apps;
|
||||
if (dir == null) {
|
||||
this._allCategoryButton = button;
|
||||
} else {
|
||||
apps = [];
|
||||
this._loadCategory(dir, apps);
|
||||
this._categories.push({ apps: apps,
|
||||
name: name,
|
||||
button: button });
|
||||
}
|
||||
|
||||
this._categoryBox.add(button, { expand: true, x_fill: true, y_fill: false });
|
||||
return true;
|
||||
},
|
||||
|
||||
_removeAll: function() {
|
||||
@ -262,8 +268,9 @@ const ViewByCategories = new Lang.Class({
|
||||
var dir = iter.get_directory();
|
||||
if (dir.get_is_nodisplay())
|
||||
continue;
|
||||
this._addCategory(dir.get_name(), i, dir);
|
||||
i++;
|
||||
|
||||
if (this._addCategory(dir.get_name(), i, dir))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,11 +311,10 @@ const AllAppDisplay = new Lang.Class({
|
||||
|
||||
const AppSearchProvider = new Lang.Class({
|
||||
Name: 'AppSearchProvider',
|
||||
Extends: Search.SearchProvider,
|
||||
|
||||
_init: function() {
|
||||
this.parent(_("APPLICATIONS"));
|
||||
this._appSys = Shell.AppSystem.get_default();
|
||||
this.id = 'applications';
|
||||
},
|
||||
|
||||
getResultMetas: function(apps, callback) {
|
||||
@ -333,18 +339,15 @@ const AppSearchProvider = new Lang.Class({
|
||||
this.searchSystem.pushResults(this, this._appSys.subsearch(previousResults, terms));
|
||||
},
|
||||
|
||||
activateResult: function(app, params) {
|
||||
params = Params.parse(params, { workspace: -1,
|
||||
timestamp: 0 });
|
||||
|
||||
activateResult: function(app) {
|
||||
let event = Clutter.get_current_event();
|
||||
let modifiers = event ? event.get_state() : 0;
|
||||
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
||||
|
||||
if (openNewWindow)
|
||||
app.open_new_window(params.workspace);
|
||||
app.open_new_window(-1);
|
||||
else
|
||||
app.activate_full(params.workspace, params.timestamp);
|
||||
app.activate();
|
||||
},
|
||||
|
||||
dragActivateResult: function(id, params) {
|
||||
@ -364,13 +367,10 @@ const AppSearchProvider = new Lang.Class({
|
||||
|
||||
const SettingsSearchProvider = new Lang.Class({
|
||||
Name: 'SettingsSearchProvider',
|
||||
Extends: Search.SearchProvider,
|
||||
|
||||
_init: function() {
|
||||
this.parent(_("SETTINGS"));
|
||||
|
||||
this.appInfo = Gio.DesktopAppInfo.new('gnome-control-center.desktop');
|
||||
this._appSys = Shell.AppSystem.get_default();
|
||||
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
|
||||
},
|
||||
|
||||
getResultMetas: function(prefs, callback) {
|
||||
@ -379,9 +379,7 @@ const SettingsSearchProvider = new Lang.Class({
|
||||
let pref = prefs[i];
|
||||
metas.push({ 'id': pref,
|
||||
'name': pref.get_name(),
|
||||
'createIcon': function(size) {
|
||||
return pref.create_icon_texture(size);
|
||||
}
|
||||
'createIcon': function() { return null; }
|
||||
});
|
||||
}
|
||||
callback(metas);
|
||||
@ -395,21 +393,13 @@ const SettingsSearchProvider = new Lang.Class({
|
||||
this.searchSystem.pushResults(this, this._appSys.search_settings(terms));
|
||||
},
|
||||
|
||||
activateResult: function(pref, params) {
|
||||
params = Params.parse(params, { workspace: -1,
|
||||
timestamp: 0 });
|
||||
|
||||
pref.activate_full(params.workspace, params.timestamp);
|
||||
activateResult: function(pref) {
|
||||
pref.activate();
|
||||
},
|
||||
|
||||
dragActivateResult: function(pref, params) {
|
||||
this.activateResult(pref, params);
|
||||
},
|
||||
|
||||
createResultActor: function (resultMeta, terms) {
|
||||
let app = resultMeta['id'];
|
||||
let icon = new AppWellIcon(app);
|
||||
return icon.actor;
|
||||
launchSearch: function(terms) {
|
||||
// FIXME: this should be a remote search provider
|
||||
this.appInfo.launch([], global.create_app_launch_context());
|
||||
}
|
||||
});
|
||||
|
||||
@ -564,6 +554,7 @@ const AppWellIcon = new Lang.Class({
|
||||
|
||||
this.actor.set_hover(true);
|
||||
this._menu.popup();
|
||||
this._menuManager.ignoreRelease();
|
||||
|
||||
return false;
|
||||
},
|
||||
|
60
js/ui/centerLayout.js
Normal file
60
js/ui/centerLayout.js
Normal file
@ -0,0 +1,60 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
|
||||
const CenterLayout = new Lang.Class({
|
||||
Name: 'CenterLayout',
|
||||
Extends: Clutter.BoxLayout,
|
||||
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
let rtl = container.get_text_direction() == Clutter.TextDirection.RTL;
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
|
||||
// Assume that these are the first three widgets and they are all visible.
|
||||
let [left, center, right] = container.get_children();
|
||||
|
||||
// Only support horizontal layouts for now.
|
||||
let [leftMinWidth, leftNaturalWidth] = left.get_preferred_width(availHeight);
|
||||
let [centerMinWidth, centerNaturalWidth] = center.get_preferred_width(availHeight);
|
||||
let [rightMinWidth, rightNaturalWidth] = right.get_preferred_width(availHeight);
|
||||
|
||||
let sideWidth = (availWidth - centerMinWidth) / 2;
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y1 + availHeight;
|
||||
|
||||
let leftSide = Math.min(Math.floor(sideWidth), leftNaturalWidth);
|
||||
let rightSide = Math.min(Math.floor(sideWidth), rightNaturalWidth);
|
||||
|
||||
if (rtl) {
|
||||
childBox.x1 = availWidth - leftSide;
|
||||
childBox.x2 = availWidth;
|
||||
} else {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = leftSide;
|
||||
}
|
||||
childBox.x1 += box.x1;
|
||||
left.allocate(childBox, flags);
|
||||
|
||||
let maxSide = Math.max(leftSide, rightSide);
|
||||
let sideWidth = Math.max((availWidth - centerNaturalWidth) / 2, maxSide);
|
||||
|
||||
childBox.x1 = box.x1 + Math.ceil(sideWidth);
|
||||
childBox.x2 = box.x2 - Math.ceil(sideWidth);
|
||||
center.allocate(childBox, flags);
|
||||
|
||||
if (rtl) {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = rightSide;
|
||||
} else {
|
||||
childBox.x1 = availWidth - rightSide;
|
||||
childBox.x2 = availWidth;
|
||||
}
|
||||
childBox.x1 += box.x1;
|
||||
right.allocate(childBox, flags);
|
||||
}
|
||||
});
|
@ -598,7 +598,7 @@ const NetworkAgent = new Lang.Class({
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
this._native.register();
|
||||
this._native.auto_register = true;
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
@ -612,6 +612,7 @@ const NetworkAgent = new Lang.Class({
|
||||
this._vpnRequests[requestId].cancel(true);
|
||||
this._vpnRequests = { };
|
||||
|
||||
this._native.auto_register = false;
|
||||
this._native.unregister();
|
||||
},
|
||||
|
||||
|
@ -383,25 +383,12 @@ const TelepathyClient = new Lang.Class({
|
||||
}
|
||||
|
||||
/* Display notification to ask user to accept/reject request */
|
||||
let source = this._ensureSubscriptionSource();
|
||||
let source = this._ensureAppSource();
|
||||
|
||||
let notif = new SubscriptionRequestNotification(source, contact);
|
||||
source.notify(notif);
|
||||
},
|
||||
|
||||
_ensureSubscriptionSource: function() {
|
||||
if (this._subscriptionSource == null) {
|
||||
this._subscriptionSource = new MessageTray.Source(_("Subscription request"),
|
||||
'gtk-dialog-question');
|
||||
Main.messageTray.add(this._subscriptionSource);
|
||||
this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
|
||||
this._subscriptionSource = null;
|
||||
}));
|
||||
}
|
||||
|
||||
return this._subscriptionSource;
|
||||
},
|
||||
|
||||
_accountConnectionStatusNotifyCb: function(account) {
|
||||
let connectionError = account.connection_error;
|
||||
|
||||
@ -415,7 +402,7 @@ const TelepathyClient = new Lang.Class({
|
||||
return;
|
||||
|
||||
/* Display notification that account failed to connect */
|
||||
let source = this._ensureAccountSource();
|
||||
let source = this._ensureAppSource();
|
||||
|
||||
notif = new AccountNotification(source, account, connectionError);
|
||||
this._accountNotifications[account.get_object_path()] = notif;
|
||||
@ -425,17 +412,16 @@ const TelepathyClient = new Lang.Class({
|
||||
source.notify(notif);
|
||||
},
|
||||
|
||||
_ensureAccountSource: function() {
|
||||
if (this._accountSource == null) {
|
||||
this._accountSource = new MessageTray.Source(_("Connection error"),
|
||||
'gtk-dialog-error');
|
||||
Main.messageTray.add(this._accountSource);
|
||||
this._accountSource.connect('destroy', Lang.bind(this, function () {
|
||||
this._accountSource = null;
|
||||
_ensureAppSource: function() {
|
||||
if (this._appSource == null) {
|
||||
this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
|
||||
Main.messageTray.add(this._appSource);
|
||||
this._appSource.connect('destroy', Lang.bind(this, function () {
|
||||
this._appSource = null;
|
||||
}));
|
||||
}
|
||||
|
||||
return this._accountSource;
|
||||
return this._appSource;
|
||||
}
|
||||
});
|
||||
|
||||
@ -492,7 +478,7 @@ const ChatSource = new Lang.Class({
|
||||
}));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
this.setMuted(!this.isMuted);
|
||||
this.emit('done-displaying-content');
|
||||
this.emit('done-displaying-content', false);
|
||||
}));
|
||||
rightClickMenu.add(item.actor);
|
||||
return rightClickMenu;
|
||||
@ -744,8 +730,7 @@ const ChatSource = new Lang.Class({
|
||||
_ackMessages: function() {
|
||||
// Don't clear our messages here, tp-glib will send a
|
||||
// 'pending-message-removed' for each one.
|
||||
this._channel.ack_all_pending_messages_async(Lang.bind(this, function(src, result) {
|
||||
this._channel.ack_all_pending_messages_finish(result);}));
|
||||
this._channel.ack_all_pending_messages_async(null);
|
||||
}
|
||||
});
|
||||
|
||||
@ -941,26 +926,24 @@ const ChatNotification = new Lang.Class({
|
||||
}
|
||||
// Show the word "Yesterday" and time if date is on yesterday
|
||||
else if(daysAgo <2){
|
||||
/* Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"*/
|
||||
/* Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/
|
||||
// xgettext:no-c-format
|
||||
format = _("<b>%H:%M</b> on Yesterday");
|
||||
format = _("<b>Yesterday</b>, <b>%H:%M</b>");
|
||||
}
|
||||
// Show a week day and time if date is in the last week
|
||||
else if (daysAgo < 7) {
|
||||
/* Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday*/
|
||||
/* Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/
|
||||
// xgettext:no-c-format
|
||||
format = _("<b>%H:%M</b> on <b>%A</b>");
|
||||
format = _("<b>%A</b>, <b>%H:%M</b>");
|
||||
|
||||
} else if (date.getYear() == now.getYear()) {
|
||||
/* 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 */
|
||||
/* Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/
|
||||
// xgettext:no-c-format
|
||||
format = _("<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>");
|
||||
format = _("<b>%B</b> <b>%d</b>, <b>%H:%M</b>");
|
||||
} else {
|
||||
/* 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 */
|
||||
/* Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/
|
||||
// xgettext:no-c-format
|
||||
format = _("<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y");
|
||||
format = _("<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> ");
|
||||
}
|
||||
|
||||
return date.toLocaleFormat(format);
|
||||
@ -1353,26 +1336,16 @@ const AccountNotification = new Lang.Class({
|
||||
this.parent(source,
|
||||
/* translators: argument is the account name, like
|
||||
* name@jabber.org for example. */
|
||||
_("Connection to %s failed").format(account.get_display_name()),
|
||||
null, { customContent: true });
|
||||
|
||||
this._label = new St.Label();
|
||||
this.addActor(this._label);
|
||||
this._updateMessage(connectionError);
|
||||
_("Unable to connect to %s").format(account.get_display_name()),
|
||||
this._getMessage(connectionError));
|
||||
|
||||
this._account = account;
|
||||
|
||||
this.addButton('reconnect', _("Reconnect"));
|
||||
this.addButton('edit', _("Edit account"));
|
||||
this.addButton('view', _("View account"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'reconnect':
|
||||
// If it fails again, a new notification should pop up with the
|
||||
// new error.
|
||||
account.reconnect_async(null);
|
||||
break;
|
||||
case 'edit':
|
||||
case 'view':
|
||||
let cmd = '/usr/bin/empathy-accounts'
|
||||
+ ' --select-account=%s'
|
||||
.format(account.get_path_suffix());
|
||||
@ -1398,19 +1371,19 @@ const AccountNotification = new Lang.Class({
|
||||
if (status == Tp.ConnectionStatus.CONNECTED) {
|
||||
this.destroy();
|
||||
} else if (status == Tp.ConnectionStatus.DISCONNECTED) {
|
||||
this._updateMessage(account.connection_error);
|
||||
this.update(this.title, this._getMessage(account.connection_error));
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_updateMessage: function(connectionError) {
|
||||
_getMessage: function(connectionError) {
|
||||
let message;
|
||||
if (connectionError in _connectionErrorMessages) {
|
||||
message = _connectionErrorMessages[connectionError];
|
||||
} else {
|
||||
message = _("Unknown reason");
|
||||
}
|
||||
this._label.set_text(message);
|
||||
return message;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
|
@ -1,15 +1,14 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const AltTab = imports.ui.altTab;
|
||||
const Main = imports.ui.main;
|
||||
const SwitcherPopup = imports.ui.switcherPopup;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
@ -27,6 +26,9 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
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) {
|
||||
@ -40,11 +42,13 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
|
||||
this._items.push(item);
|
||||
root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); }));
|
||||
global.focus_manager.add_group(root);
|
||||
if (root instanceof St.Widget)
|
||||
global.focus_manager.add_group(root);
|
||||
},
|
||||
|
||||
removeGroup: function(root) {
|
||||
global.focus_manager.remove_group(root);
|
||||
if (root instanceof St.Widget)
|
||||
global.focus_manager.remove_group(root);
|
||||
for (let i = 0; i < this._items.length; i++) {
|
||||
if (this._items[i].root == root) {
|
||||
this._items.splice(i, 1);
|
||||
@ -53,11 +57,9 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
focusGroup: function(item) {
|
||||
if (item.window) {
|
||||
Main.activateWindow(item.window);
|
||||
} else if (item.focusCallback) {
|
||||
item.focusCallback();
|
||||
focusGroup: function(item, timestamp) {
|
||||
if (item.focusCallback) {
|
||||
item.focusCallback(timestamp);
|
||||
} else {
|
||||
if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
|
||||
global.stage_input_mode == Shell.StageInputMode.NORMAL)
|
||||
@ -75,24 +77,14 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
if (a.sortGroup != b.sortGroup)
|
||||
return a.sortGroup - b.sortGroup;
|
||||
|
||||
let y;
|
||||
if (a.x == undefined) {
|
||||
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();
|
||||
}
|
||||
let ax, bx, y;
|
||||
[ax, y] = a.proxy.get_transformed_position();
|
||||
[bx, y] = b.proxy.get_transformed_position();
|
||||
|
||||
return a.x - b.x;
|
||||
return ax - bx;
|
||||
},
|
||||
|
||||
popup: function(backwards, mask) {
|
||||
popup: function(backward, binding, mask) {
|
||||
// Start with the set of focus groups that are currently mapped
|
||||
let items = this._items.filter(function (item) { return item.proxy.mapped; });
|
||||
|
||||
@ -123,187 +115,63 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
items.sort(Lang.bind(this, this._sortItems));
|
||||
|
||||
if (!this._popup) {
|
||||
this._popup = new CtrlAltTabPopup();
|
||||
this._popup.show(items, backwards, mask);
|
||||
this._popup = new CtrlAltTabPopup(items);
|
||||
this._popup.show(backward, binding, mask);
|
||||
|
||||
this._popup.actor.connect('destroy',
|
||||
Lang.bind(this, function() {
|
||||
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({
|
||||
Name: 'CtrlAltTabPopup',
|
||||
Extends: SwitcherPopup.SwitcherPopup,
|
||||
|
||||
_init : function() {
|
||||
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);
|
||||
_createSwitcher: function() {
|
||||
this._switcherList = new CtrlAltTabSwitcher(this._items);
|
||||
return true;
|
||||
},
|
||||
|
||||
_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;
|
||||
_initialSelection: function(backward, binding) {
|
||||
if (binding == 'switch-panels') {
|
||||
if (backward)
|
||||
this._selectedIndex = this._items.length - 1;
|
||||
} else if (binding == 'switch-panels-backward') {
|
||||
if (!backward)
|
||||
this._selectedIndex = this._items.length - 1;
|
||||
}
|
||||
|
||||
this.actor.opacity = 0;
|
||||
this.actor.show();
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 255,
|
||||
time: POPUP_FADE_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
|
||||
return true;
|
||||
this._select(this._selectedIndex);
|
||||
},
|
||||
|
||||
_next : function() {
|
||||
return mod(this._selection + 1, this._items.length);
|
||||
},
|
||||
|
||||
_previous : function() {
|
||||
return mod(this._selection - 1, this._items.length);
|
||||
},
|
||||
|
||||
_keyPressEvent : function(actor, event) {
|
||||
let keysym = event.get_key_symbol();
|
||||
let shift = (event.get_state() & Clutter.ModifierType.SHIFT_MASK);
|
||||
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());
|
||||
else if (keysym == Clutter.KEY_ISO_Left_Tab)
|
||||
_keyPressHandler: function(keysym, backwards, action) {
|
||||
if (action == Meta.KeyBindingAction.SWITCH_PANELS)
|
||||
this._select(backwards ? this._previous() : this._next());
|
||||
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
|
||||
this._select(backwards ? this._next() : this._previous());
|
||||
else if (keysym == Clutter.Left)
|
||||
this._select(this._previous());
|
||||
else if (keysym == Clutter.KEY_Left)
|
||||
this._select(this._previous());
|
||||
else if (keysym == Clutter.KEY_Right)
|
||||
else if (keysym == Clutter.Right)
|
||||
this._select(this._next());
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_keyReleaseEvent : function(actor, event) {
|
||||
let [x, y, mods] = global.get_pointer();
|
||||
let state = mods & this._modifierMask;
|
||||
|
||||
if (state == 0)
|
||||
this._finish();
|
||||
|
||||
return true;
|
||||
_finish : function(time) {
|
||||
this.parent(time);
|
||||
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
|
||||
},
|
||||
|
||||
_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({
|
||||
Name: 'CtrlAltTabSwitcher',
|
||||
Extends: AltTab.SwitcherList,
|
||||
Extends: SwitcherPopup.SwitcherList,
|
||||
|
||||
_init : function(items) {
|
||||
this.parent(true);
|
||||
|
@ -371,6 +371,7 @@ const Dash = new Lang.Class({
|
||||
this._maxHeight = -1;
|
||||
this.iconSize = 64;
|
||||
this._shownInitially = false;
|
||||
this._ignoreHeight = false;
|
||||
|
||||
this._dragPlaceholder = null;
|
||||
this._dragPlaceholderPos = -1;
|
||||
@ -396,7 +397,10 @@ const Dash = new Lang.Class({
|
||||
this.actor = new St.Bin({ child: this._container });
|
||||
this.actor.connect('notify::height', Lang.bind(this,
|
||||
function() {
|
||||
if (this._maxHeight != this.actor.height)
|
||||
if (this._ignoreHeight)
|
||||
return;
|
||||
|
||||
if (this._maxHeight != this.actor.height);
|
||||
this._queueRedisplay();
|
||||
this._maxHeight = this.actor.height;
|
||||
}));
|
||||
@ -421,6 +425,8 @@ const Dash = new Lang.Class({
|
||||
Lang.bind(this, this._onDragCancelled));
|
||||
Main.overview.connect('window-drag-end',
|
||||
Lang.bind(this, this._onDragEnd));
|
||||
Main.overview.connect('showing',
|
||||
Lang.bind(this, this._onOverviewShowing));
|
||||
},
|
||||
|
||||
_onDragBegin: function() {
|
||||
@ -923,6 +929,65 @@ const Dash = new Lang.Class({
|
||||
}));
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_computeTranslation: function() {
|
||||
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
if (rtl)
|
||||
return this.actor.width;
|
||||
else
|
||||
return - this.actor.width;
|
||||
},
|
||||
|
||||
_onOverviewShowing: function() {
|
||||
// reset any translation and make sure the actor is visible when
|
||||
// entering the overview
|
||||
this.slideX = 0;
|
||||
this.actor.show();
|
||||
},
|
||||
|
||||
get slideX() {
|
||||
return this._slideX;
|
||||
},
|
||||
|
||||
set slideX(value) {
|
||||
this._slideX = value;
|
||||
this.actor.translation_x = this._slideX;
|
||||
|
||||
if (this._slideX > 0) {
|
||||
let rect = new Clutter.Rect();
|
||||
rect.size.width = this.actor.width - this._slideX;
|
||||
rect.size.height = this.actor.height;
|
||||
this.actor.clip_rect = rect;
|
||||
} else {
|
||||
this.actor.clip_rect = null;
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this.actor.show();
|
||||
Tweener.addTween(this, { slideX: 0,
|
||||
transition: 'easeOutQuad',
|
||||
time: DASH_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this._ignoreHeight = false;
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._ignoreHeight = true;
|
||||
let hiddenX = this._computeTranslation();
|
||||
Tweener.addTween(this, { slideX: hiddenX,
|
||||
transition: 'easeOutQuad',
|
||||
time: DASH_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this.actor.hide();
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -234,7 +234,7 @@ const _Draggable = new Lang.Class({
|
||||
this._dragY = this._dragStartY = stageY;
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||
this._dragActor = this.actor._delegate.getDragActor();
|
||||
this._dragActor.reparent(Main.uiGroup);
|
||||
this._dragActor.raise_top();
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
||||
|
@ -126,11 +126,7 @@ function logExtensionError(uuid, error) {
|
||||
|
||||
let message = '' + error;
|
||||
|
||||
if (error.state)
|
||||
extension.state = error.state;
|
||||
else
|
||||
extension.state = ExtensionState.ERROR;
|
||||
|
||||
extension.state = ExtensionState.ERROR;
|
||||
if (!extension.errors)
|
||||
extension.errors = [];
|
||||
|
||||
@ -145,18 +141,16 @@ function loadExtension(extension) {
|
||||
extension.state = ExtensionState.ERROR;
|
||||
|
||||
if (ExtensionUtils.isOutOfDate(extension)) {
|
||||
let error = new Error('extension is not compatible with current GNOME Shell and/or GJS version');
|
||||
error.state = ExtensionState.OUT_OF_DATE;
|
||||
throw error;
|
||||
}
|
||||
|
||||
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
|
||||
if (enabled) {
|
||||
initExtension(extension.uuid);
|
||||
if (extension.state == ExtensionState.DISABLED)
|
||||
enableExtension(extension.uuid);
|
||||
extension.state = ExtensionState.OUT_OF_DATE;
|
||||
} else {
|
||||
extension.state = ExtensionState.INITIALIZED;
|
||||
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
|
||||
if (enabled) {
|
||||
initExtension(extension.uuid);
|
||||
if (extension.state == ExtensionState.DISABLED)
|
||||
enableExtension(extension.uuid);
|
||||
} else {
|
||||
extension.state = ExtensionState.INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
@ -217,8 +211,16 @@ function initExtension(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() {
|
||||
let newEnabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
||||
let newEnabledExtensions = getEnabledExtensions();
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
@ -252,7 +254,7 @@ function onEnabledExtensionsChanged() {
|
||||
|
||||
function _loadExtensions() {
|
||||
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
|
||||
enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
||||
enabledExtensions = getEnabledExtensions();
|
||||
|
||||
let finder = new ExtensionUtils.ExtensionFinder();
|
||||
finder.connect('extension-found', function(signals, extension) {
|
||||
@ -294,10 +296,17 @@ function disableAllExtensions() {
|
||||
}
|
||||
|
||||
function _sessionUpdated() {
|
||||
if (Main.sessionMode.allowExtensions)
|
||||
// For now sessionMode.allowExtensions controls extensions from both the
|
||||
// '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();
|
||||
else
|
||||
} else {
|
||||
disableAllExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
@ -43,7 +43,6 @@ const GrabHelper = new Lang.Class({
|
||||
|
||||
this._actors = [];
|
||||
this._capturedEventId = 0;
|
||||
this._eventId = 0;
|
||||
this._keyFocusNotifyId = 0;
|
||||
this._focusWindowChangedId = 0;
|
||||
this._ignoreRelease = false;
|
||||
@ -78,9 +77,12 @@ const GrabHelper = new Lang.Class({
|
||||
},
|
||||
|
||||
_isWithinGrabbedActor: function(actor) {
|
||||
let currentActor = this.currentGrab.actor;
|
||||
while (actor) {
|
||||
if (this._actors.indexOf(actor) != -1)
|
||||
return true;
|
||||
if (actor == currentActor)
|
||||
return true;
|
||||
actor = actor.get_parent();
|
||||
}
|
||||
return false;
|
||||
@ -90,6 +92,14 @@ const GrabHelper = new Lang.Class({
|
||||
return this._grabStack[this._grabStack.length - 1] || {};
|
||||
},
|
||||
|
||||
get grabbed() {
|
||||
return this._grabStack.length > 0;
|
||||
},
|
||||
|
||||
get grabStack() {
|
||||
return this._grabStack;
|
||||
},
|
||||
|
||||
_findStackIndex: function(actor) {
|
||||
if (!actor)
|
||||
return -1;
|
||||
@ -101,6 +111,16 @@ const GrabHelper = new Lang.Class({
|
||||
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) {
|
||||
return this._findStackIndex(actor) >= 0;
|
||||
},
|
||||
@ -140,6 +160,7 @@ const GrabHelper = new Lang.Class({
|
||||
params = Params.parse(params, { actor: null,
|
||||
modal: false,
|
||||
grabFocus: false,
|
||||
focus: null,
|
||||
onUngrab: null });
|
||||
|
||||
let focus = global.stage.key_focus;
|
||||
@ -157,7 +178,9 @@ const GrabHelper = new Lang.Class({
|
||||
if (params.grabFocus && !this._takeFocusGrab(hadFocus))
|
||||
return false;
|
||||
|
||||
if (hadFocus || params.grabFocus)
|
||||
if (params.focus)
|
||||
params.focus.grab_key_focus();
|
||||
else if (hadFocus || params.grabFocus)
|
||||
_navigateActor(newFocus);
|
||||
|
||||
this._grabStack.push(params);
|
||||
@ -171,7 +194,6 @@ const GrabHelper = new Lang.Class({
|
||||
return false;
|
||||
|
||||
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++;
|
||||
@ -188,11 +210,6 @@ const GrabHelper = new Lang.Class({
|
||||
this._capturedEventId = 0;
|
||||
}
|
||||
|
||||
if (this._eventId > 0) {
|
||||
global.stage.disconnect(this._eventId);
|
||||
this._eventId = 0;
|
||||
}
|
||||
|
||||
Main.popModal(this._owner);
|
||||
global.sync_pointer();
|
||||
},
|
||||
@ -204,7 +221,6 @@ const GrabHelper = new Lang.Class({
|
||||
|
||||
this._grabbedFromKeynav = hadFocus;
|
||||
this._preGrabInputMode = global.stage_input_mode;
|
||||
this._prevFocusedWindow = metaDisplay.focus_window;
|
||||
|
||||
if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
|
||||
this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
|
||||
@ -243,13 +259,7 @@ const GrabHelper = new Lang.Class({
|
||||
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
global.screen.focus_default_window(global.get_current_time());
|
||||
},
|
||||
|
||||
// ignoreRelease:
|
||||
@ -270,7 +280,8 @@ const GrabHelper = new Lang.Class({
|
||||
// If the actor that was popped from the grab stack was not the actor
|
||||
// That was passed in, this call is ignored.
|
||||
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);
|
||||
if (grabStackIndex < 0)
|
||||
@ -288,7 +299,7 @@ const GrabHelper = new Lang.Class({
|
||||
let poppedGrab = poppedGrabs[i];
|
||||
|
||||
if (poppedGrab.onUngrab)
|
||||
poppedGrab.onUngrab();
|
||||
poppedGrab.onUngrab(params.isUser);
|
||||
|
||||
if (poppedGrab.modal)
|
||||
this._releaseModalGrab();
|
||||
@ -311,12 +322,18 @@ const GrabHelper = new Lang.Class({
|
||||
|
||||
if (release && this._ignoreRelease) {
|
||||
this._ignoreRelease = false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!button && this._modalCount == 0)
|
||||
return false;
|
||||
|
||||
if (type == Clutter.EventType.KEY_PRESS &&
|
||||
event.get_key_symbol() == Clutter.KEY_Escape) {
|
||||
this.ungrab({ isUser: true });
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._isWithinGrabbedActor(event.get_source()))
|
||||
return false;
|
||||
|
||||
@ -328,33 +345,22 @@ const GrabHelper = new Lang.Class({
|
||||
// which should be a release event.
|
||||
if (press)
|
||||
this._ignoreRelease = true;
|
||||
this.ungrab({ actor: this._grabStack[0].actor });
|
||||
let i = this._actorInGrabStack(event.get_source()) + 1;
|
||||
this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
|
||||
}
|
||||
|
||||
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() {
|
||||
let focus = global.stage.key_focus;
|
||||
if (!focus || !this._isWithinGrabbedActor(focus))
|
||||
this.ungrab();
|
||||
this.ungrab({ isUser: true });
|
||||
},
|
||||
|
||||
_focusWindowChanged: function() {
|
||||
let metaDisplay = global.screen.get_display();
|
||||
if (metaDisplay.focus_window != null)
|
||||
this.ungrab();
|
||||
this.ungrab({ isUser: true });
|
||||
}
|
||||
});
|
||||
|
@ -198,7 +198,11 @@ const IconGrid = new Lang.Class({
|
||||
|
||||
_getPreferredHeight: function (grid, forWidth, alloc) {
|
||||
let children = this._getVisibleChildren();
|
||||
let [nColumns, usedWidth] = this._computeLayout(forWidth);
|
||||
let nColumns;
|
||||
if (forWidth < 0)
|
||||
nColumns = children.length;
|
||||
else
|
||||
nColumns = this._computeLayout(forWidth)[0];
|
||||
let nRows;
|
||||
if (nColumns > 0)
|
||||
nRows = Math.ceil(children.length / nColumns);
|
||||
|
@ -251,7 +251,7 @@ const Keyboard = new Lang.Class({
|
||||
this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
|
||||
|
||||
if (show)
|
||||
this.show();
|
||||
this.show(Main.layoutManager.focusIndex);
|
||||
else
|
||||
this._createSource();
|
||||
},
|
||||
@ -375,7 +375,7 @@ const Keyboard = new Lang.Class({
|
||||
if (!this._enableKeyboard)
|
||||
return;
|
||||
|
||||
let monitor = Main.layoutManager.bottomMonitor;
|
||||
let monitor = Main.layoutManager.keyboardMonitor;
|
||||
let maxHeight = monitor.height / 3;
|
||||
this.actor.width = monitor.width;
|
||||
|
||||
@ -462,9 +462,9 @@ const Keyboard = new Lang.Class({
|
||||
actor._extended_keys || actor.extended_key;
|
||||
},
|
||||
|
||||
show: function () {
|
||||
show: function (monitor) {
|
||||
Main.layoutManager.keyboardIndex = monitor;
|
||||
this._redraw();
|
||||
|
||||
Main.layoutManager.showKeyboard();
|
||||
this._destroySource();
|
||||
},
|
||||
@ -512,7 +512,7 @@ const Keyboard = new Lang.Class({
|
||||
|
||||
if (timestamp != Clutter.CURRENT_TIME)
|
||||
this._timestamp = timestamp;
|
||||
this.show();
|
||||
this.show(Main.layoutManager.focusIndex);
|
||||
},
|
||||
|
||||
Hide: function(timestamp) {
|
||||
@ -566,6 +566,7 @@ const KeyboardSource = new Lang.Class({
|
||||
},
|
||||
|
||||
open: function() {
|
||||
this._keyboard.show();
|
||||
// Show the OSK below the message tray
|
||||
this._keyboard.show(Main.layoutManager.bottomIndex);
|
||||
}
|
||||
});
|
||||
|
125
js/ui/layout.js
125
js/ui/layout.js
@ -103,6 +103,7 @@ const LayoutManager = new Lang.Class({
|
||||
this.monitors = [];
|
||||
this.primaryMonitor = null;
|
||||
this.primaryIndex = -1;
|
||||
this._keyboardIndex = -1;
|
||||
this._hotCorners = [];
|
||||
this._background = null;
|
||||
this._leftPanelBarrier = 0;
|
||||
@ -123,7 +124,7 @@ const LayoutManager = new Lang.Class({
|
||||
this.addChrome(this.panelBox, { affectsStruts: true,
|
||||
trackFullscreen: true });
|
||||
this.panelBox.connect('allocation-changed',
|
||||
Lang.bind(this, this._updatePanelBarriers));
|
||||
Lang.bind(this, this._panelBoxChanged));
|
||||
|
||||
this.trayBox = new St.Widget({ name: 'trayBox',
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
@ -240,9 +241,8 @@ const LayoutManager = new Lang.Class({
|
||||
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
|
||||
this.panelBox.set_size(this.primaryMonitor.width, -1);
|
||||
|
||||
this.keyboardBox.set_position(this.bottomMonitor.x,
|
||||
this.bottomMonitor.y + this.bottomMonitor.height);
|
||||
this.keyboardBox.set_size(this.bottomMonitor.width, -1);
|
||||
if (this.keyboardIndex < 0)
|
||||
this.keyboardIndex = this.primaryIndex;
|
||||
|
||||
this.trayBox.set_position(this.bottomMonitor.x,
|
||||
this.bottomMonitor.y + this.bottomMonitor.height);
|
||||
@ -256,6 +256,11 @@ const LayoutManager = new Lang.Class({
|
||||
this.bottomMonitor.width, this.bottomMonitor.height);
|
||||
},
|
||||
|
||||
_panelBoxChanged: function() {
|
||||
this.emit('panel-box-changed');
|
||||
this._updatePanelBarriers();
|
||||
},
|
||||
|
||||
_updatePanelBarriers: function() {
|
||||
if (this._leftPanelBarrier)
|
||||
global.destroy_pointer_barrier(this._leftPanelBarrier);
|
||||
@ -305,8 +310,44 @@ const LayoutManager = new Lang.Class({
|
||||
return this.monitors[index];
|
||||
},
|
||||
|
||||
get keyboardMonitor() {
|
||||
return this.monitors[this.keyboardIndex];
|
||||
},
|
||||
|
||||
get focusIndex() {
|
||||
let i = Main.layoutManager.primaryIndex;
|
||||
|
||||
if (global.stage_input_mode == Shell.StageInputMode.FOCUSED ||
|
||||
global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) {
|
||||
let focusActor = global.stage.key_focus;
|
||||
if (focusActor)
|
||||
i = this._chrome.findIndexForActor(focusActor);
|
||||
} else {
|
||||
let focusWindow = global.display.focus_window;
|
||||
if (focusWindow)
|
||||
i = this._chrome.findIndexForWindow(focusWindow.get_compositor_private());
|
||||
}
|
||||
|
||||
return i;
|
||||
},
|
||||
|
||||
get focusMonitor() {
|
||||
return this.monitors[this.focusIndex];
|
||||
},
|
||||
|
||||
set keyboardIndex(v) {
|
||||
this._keyboardIndex = v;
|
||||
this.keyboardBox.set_position(this.keyboardMonitor.x,
|
||||
this.keyboardMonitor.y + this.keyboardMonitor.height);
|
||||
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
|
||||
},
|
||||
|
||||
get keyboardIndex() {
|
||||
return this._keyboardIndex;
|
||||
},
|
||||
|
||||
_startupAnimation: function() {
|
||||
this.panelBox.anchor_y = this.panelBox.height;
|
||||
this.panelBox.translation_y = -this.panelBox.height;
|
||||
|
||||
let plymouthTransitionRunning = false;
|
||||
|
||||
@ -342,7 +383,7 @@ const LayoutManager = new Lang.Class({
|
||||
}
|
||||
|
||||
Tweener.addTween(this.panelBox,
|
||||
{ anchor_y: 0,
|
||||
{ translation_y: 0,
|
||||
time: STARTUP_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: this._startupAnimationComplete,
|
||||
@ -351,6 +392,7 @@ const LayoutManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_startupAnimationComplete: function() {
|
||||
this.emit('panel-box-changed');
|
||||
this._chrome.thawUpdateRegions();
|
||||
},
|
||||
|
||||
@ -363,11 +405,14 @@ const LayoutManager = new Lang.Class({
|
||||
onComplete: this._showKeyboardComplete,
|
||||
onCompleteScope: this
|
||||
});
|
||||
Tweener.addTween(this.trayBox,
|
||||
{ anchor_y: this.keyboardBox.height,
|
||||
time: KEYBOARD_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
|
||||
if (this.keyboardIndex == this.bottomIndex) {
|
||||
Tweener.addTween(this.trayBox,
|
||||
{ anchor_y: this.keyboardBox.height,
|
||||
time: KEYBOARD_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('keyboard-visible-changed', true);
|
||||
},
|
||||
@ -379,7 +424,8 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
|
||||
this.keyboardBox.anchor_y = this.keyboardBox.height;
|
||||
this.trayBox.anchor_y = this.keyboardBox.height;
|
||||
if (this.keyboardIndex == this.bottomIndex)
|
||||
this.trayBox.anchor_y = this.keyboardBox.height;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -395,11 +441,14 @@ const LayoutManager = new Lang.Class({
|
||||
onComplete: this._hideKeyboardComplete,
|
||||
onCompleteScope: this
|
||||
});
|
||||
Tweener.addTween(this.trayBox,
|
||||
{ anchor_y: 0,
|
||||
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
|
||||
if (this.keyboardIndex == this.bottomIndex) {
|
||||
Tweener.addTween(this.trayBox,
|
||||
{ anchor_y: 0,
|
||||
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('keyboard-visible-changed', false);
|
||||
},
|
||||
@ -463,7 +512,7 @@ const LayoutManager = new Lang.Class({
|
||||
},
|
||||
|
||||
findMonitorForActor: function(actor) {
|
||||
return this._chrome.findMonitorForActor(actor);
|
||||
return this.monitors[this._chrome.findIndexForActor(actor)];
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(LayoutManager.prototype);
|
||||
@ -812,6 +861,7 @@ const Chrome = new Lang.Class({
|
||||
|
||||
_relayout: function() {
|
||||
this._monitors = this._layoutManager.monitors;
|
||||
this._primaryIndex = this._layoutManager.primaryIndex;
|
||||
this._primaryMonitor = this._layoutManager.primaryMonitor;
|
||||
|
||||
this._updateFullscreen();
|
||||
@ -827,32 +877,47 @@ const Chrome = new Lang.Class({
|
||||
let monitor = this._monitors[i];
|
||||
if (cx >= monitor.x && cx < monitor.x + monitor.width &&
|
||||
cy >= monitor.y && cy < monitor.y + monitor.height)
|
||||
return monitor;
|
||||
return i;
|
||||
}
|
||||
// If the center is not on a monitor, return the first overlapping monitor
|
||||
for (let i = 0; i < this._monitors.length; i++) {
|
||||
let monitor = this._monitors[i];
|
||||
if (x + w > monitor.x && x < monitor.x + monitor.width &&
|
||||
y + h > monitor.y && y < monitor.y + monitor.height)
|
||||
return monitor;
|
||||
return i;
|
||||
}
|
||||
// otherwise on no monitor
|
||||
return null;
|
||||
return -1;
|
||||
},
|
||||
|
||||
_findMonitorForWindow: function(window) {
|
||||
return this._findMonitorForRect(window.x, window.y, window.width, window.height);
|
||||
findIndexForWindow: function(window) {
|
||||
let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
|
||||
if (i >= 0)
|
||||
return i;
|
||||
return this._primaryIndex; // Not on any monitor, pretend its on the primary
|
||||
},
|
||||
|
||||
// This call guarantees that we return some monitor to simplify usage of it
|
||||
// In practice all tracked actors should be visible on some monitor anyway
|
||||
findMonitorForActor: function(actor) {
|
||||
findIndexForActor: function(actor) {
|
||||
let [x, y] = actor.get_transformed_position();
|
||||
let [w, h] = actor.get_transformed_size();
|
||||
let monitor = this._findMonitorForRect(x, y, w, h);
|
||||
if (monitor)
|
||||
return monitor;
|
||||
return this._primaryMonitor; // Not on any monitor, pretend its on the primary
|
||||
let i = this._findMonitorForRect(x, y, w, h);
|
||||
if (i >= 0)
|
||||
return i;
|
||||
return this._primaryIndex; // Not on any monitor, pretend its on the primary
|
||||
},
|
||||
|
||||
findMonitorForWindow: function(window) {
|
||||
let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
|
||||
if (i >= 0)
|
||||
return this._monitors[i];
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
findMonitorForActor: function(actor) {
|
||||
return this._monitors[this.findIndexForActor(actor)];
|
||||
},
|
||||
|
||||
_queueUpdateRegions: function() {
|
||||
@ -900,7 +965,7 @@ const Chrome = new Lang.Class({
|
||||
continue;
|
||||
|
||||
if (layer == Meta.StackLayer.FULLSCREEN) {
|
||||
let monitor = this._findMonitorForWindow(window);
|
||||
let monitor = this.findMonitorForWindow(window);
|
||||
if (monitor)
|
||||
monitor.inFullscreen = true;
|
||||
}
|
||||
@ -917,7 +982,7 @@ const Chrome = new Lang.Class({
|
||||
}
|
||||
|
||||
// Or whether it is monitor sized
|
||||
let monitor = this._findMonitorForWindow(window);
|
||||
let monitor = this.findMonitorForWindow(window);
|
||||
if (monitor &&
|
||||
window.x <= monitor.x &&
|
||||
window.x + window.width >= monitor.x + monitor.width &&
|
||||
|
@ -180,7 +180,7 @@ function start() {
|
||||
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
|
||||
false, -1, 1);
|
||||
global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
|
||||
sessionMode.connect('update', _sessionUpdated);
|
||||
sessionMode.connect('updated', _sessionUpdated);
|
||||
_sessionUpdated();
|
||||
|
||||
// Provide the bus object for gnome-session to
|
||||
|
@ -1088,14 +1088,14 @@ const Source = new Lang.Class({
|
||||
item = new PopupMenu.PopupMenuItem(_("Open"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
this.open();
|
||||
this.emit('done-displaying-content');
|
||||
this.emit('done-displaying-content', true);
|
||||
}));
|
||||
rightClickMenu.add(item.actor);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Remove"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
this.destroy();
|
||||
this.emit('done-displaying-content');
|
||||
this.emit('done-displaying-content', false);
|
||||
}));
|
||||
rightClickMenu.add(item.actor);
|
||||
return rightClickMenu;
|
||||
@ -1341,7 +1341,7 @@ const SummaryItem = new Lang.Class({
|
||||
},
|
||||
|
||||
_notificationDoneDisplaying: function() {
|
||||
this.source.emit('done-displaying-content');
|
||||
this.source.emit('done-displaying-content', true);
|
||||
},
|
||||
|
||||
_notificationDestroyed: function(notification) {
|
||||
@ -1441,7 +1441,6 @@ const MessageTray = new Lang.Class({
|
||||
this._clickedSummaryItem = null;
|
||||
this._clickedSummaryItemMouseButton = -1;
|
||||
this._clickedSummaryItemAllocationChangedId = 0;
|
||||
this._pointerBarrier = 0;
|
||||
|
||||
this._closeButton = makeCloseButton();
|
||||
this._closeButton.hide();
|
||||
@ -1471,6 +1470,7 @@ const MessageTray = new Lang.Class({
|
||||
this._pointerInTray = false;
|
||||
this._pointerInKeyboard = false;
|
||||
this._keyboardVisible = false;
|
||||
this._keyboardUnderMessageTray = false;
|
||||
this._summaryState = State.HIDDEN;
|
||||
this._pointerInSummary = false;
|
||||
this._notificationClosed = false;
|
||||
@ -1485,6 +1485,7 @@ const MessageTray = new Lang.Class({
|
||||
this._reNotifyAfterHideNotification = null;
|
||||
this._inFullscreen = false;
|
||||
this._desktopClone = null;
|
||||
this._inCtrlAltTab = false;
|
||||
|
||||
this._lightbox = new Lightbox.Lightbox(global.window_group,
|
||||
{ inhibitEvents: true,
|
||||
@ -1506,7 +1507,7 @@ const MessageTray = new Lang.Class({
|
||||
this._overviewVisible = true;
|
||||
this._grabHelper.ungrab(); // drop modal grab if necessary
|
||||
this.actor.add_style_pseudo_class('overview');
|
||||
this._updateState();
|
||||
this.show();
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this,
|
||||
function() {
|
||||
@ -1543,15 +1544,34 @@ const MessageTray = new Lang.Class({
|
||||
this._trayDwellUserTime = 0;
|
||||
|
||||
this._sessionUpdated();
|
||||
this._updateNoMessagesLabel();
|
||||
},
|
||||
|
||||
_updateNoMessagesLabel: function() {
|
||||
if (this._summaryItems.length == 0 && !this._noMessages) {
|
||||
this._noMessages = new St.Label({ text: _("No Messages"),
|
||||
style_class: 'no-messages-label',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
y_expand: true });
|
||||
this.actor.add_actor(this._noMessages);
|
||||
} else if (this._summaryItems.length > 0 && this._noMessages) {
|
||||
this._noMessages.destroy();
|
||||
this._noMessages = null;
|
||||
}
|
||||
},
|
||||
|
||||
_sessionUpdated: function() {
|
||||
if (Main.sessionMode.isLocked || Main.sessionMode.isGreeter)
|
||||
if ((Main.sessionMode.isLocked || Main.sessionMode.isGreeter) && this._inCtrlAltTab) {
|
||||
Main.ctrlAltTabManager.removeGroup(this._summary);
|
||||
else
|
||||
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'start-here-symbolic',
|
||||
this._inCtrlAltTab = false;
|
||||
} else if (!this._inCtrlAltTab) {
|
||||
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic',
|
||||
{ focusCallback: Lang.bind(this, this.toggleAndNavigate),
|
||||
sortGroup: CtrlAltTab.SortGroup.BOTTOM });
|
||||
this._inCtrlAltTab = true;
|
||||
}
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
@ -1589,6 +1609,8 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_trayDwellTimeout: function() {
|
||||
this._trayDwellTimeoutId = 0;
|
||||
|
||||
if (Main.modalCount > 0)
|
||||
return false;
|
||||
|
||||
@ -1599,8 +1621,6 @@ const MessageTray = new Lang.Class({
|
||||
if (currentUserTime != this._trayDwellUserTime)
|
||||
return false;
|
||||
|
||||
this._trayDwellTimeoutId = 0;
|
||||
|
||||
this._traySummoned = true;
|
||||
this._updateState();
|
||||
|
||||
@ -1687,6 +1707,8 @@ const MessageTray = new Lang.Class({
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateState(); return false; }));
|
||||
|
||||
this.emit('summary-item-added', summaryItem);
|
||||
|
||||
this._updateNoMessagesLabel();
|
||||
},
|
||||
|
||||
getSummaryItems: function() {
|
||||
@ -1719,6 +1741,8 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
summaryItemToRemove.actor.destroy();
|
||||
|
||||
this._updateNoMessagesLabel();
|
||||
|
||||
if (needUpdate)
|
||||
this._updateState();
|
||||
},
|
||||
@ -1766,6 +1790,11 @@ const MessageTray = new Lang.Class({
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._traySummoned = true;
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
_onNotify: function(source, notification) {
|
||||
if (this._summaryBoxPointerItem && this._summaryBoxPointerItem.source == source) {
|
||||
if (this._summaryBoxPointerState == State.HIDING) {
|
||||
@ -1904,12 +1933,15 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) {
|
||||
if (this._keyboardVisible == keyboardVisible)
|
||||
let keyboardUnderMessageTray = layoutManager.keyboardIndex == layoutManager.bottomIndex;
|
||||
if (this._keyboardVisible == keyboardVisible &&
|
||||
this._keyboardUnderMesssageTray == keyboardUnderMessageTray)
|
||||
return;
|
||||
|
||||
this._keyboardVisible = keyboardVisible;
|
||||
this._keyboardUnderMessageTray = keyboardUnderMessageTray;
|
||||
|
||||
if (keyboardVisible)
|
||||
if (keyboardVisible && keyboardUnderMessageTray)
|
||||
this.actor.add_style_pseudo_class('keyboard');
|
||||
else
|
||||
this.actor.remove_style_pseudo_class('keyboard');
|
||||
@ -2009,15 +2041,14 @@ const MessageTray = new Lang.Class({
|
||||
}
|
||||
|
||||
// Summary
|
||||
let summarySummoned = this._pointerInSummary || this._overviewVisible || this._traySummoned;
|
||||
let summarySummoned = this._pointerInSummary || this._traySummoned;
|
||||
let summaryPinned = this._pointerInTray || summarySummoned || this._locked;
|
||||
let summaryHovered = this._pointerInTray || this._pointerInSummary;
|
||||
|
||||
let notificationsVisible = (this._notificationState == State.SHOWING ||
|
||||
this._notificationState == State.SHOWN);
|
||||
let notificationsVisible = this._notificationState != State.HIDDEN;
|
||||
let notificationsDone = !notificationsVisible && !notificationsPending;
|
||||
|
||||
let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered;
|
||||
let summaryOptionalInOverview = !this._locked && !summaryHovered;
|
||||
let mustHideSummary = (notificationsPending && (notificationUrgent || summaryOptionalInOverview))
|
||||
|| notificationsVisible || !Main.sessionMode.hasNotifications;
|
||||
|
||||
@ -2067,12 +2098,12 @@ const MessageTray = new Lang.Class({
|
||||
this._desktopCloneState == State.SHOWN);
|
||||
let desktopCloneShouldBeVisible = (trayShouldBeVisible &&
|
||||
!this._overviewVisible &&
|
||||
!this._keyboardVisible);
|
||||
(!this._keyboardVisible || !this._keyboardUnderMessageTray));
|
||||
|
||||
if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) {
|
||||
this._showDesktopClone();
|
||||
} else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) {
|
||||
this._hideDesktopClone (this._keyboardVisible);
|
||||
this._hideDesktopClone (this._keyboardVisible && this._keyboardUnderMessageTray);
|
||||
}
|
||||
},
|
||||
|
||||
@ -2085,6 +2116,8 @@ const MessageTray = new Lang.Class({
|
||||
params.onCompleteScope = this;
|
||||
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
|
||||
|
||||
// Remove other tweens that could mess with the state machine
|
||||
Tweener.removeTweens(actor);
|
||||
Tweener.addTween(actor, params);
|
||||
|
||||
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
|
||||
@ -2238,40 +2271,28 @@ const MessageTray = new Lang.Class({
|
||||
_updateShowingNotification: function() {
|
||||
this._notification.acknowledged = true;
|
||||
|
||||
Tweener.removeTweens(this._notificationWidget);
|
||||
|
||||
// We auto-expand notifications with CRITICAL urgency.
|
||||
// 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)
|
||||
if (this._notification.urgency == Urgency.CRITICAL)
|
||||
this._expandNotification(true);
|
||||
|
||||
// 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.
|
||||
//
|
||||
// We tween any notification showing in the banner mode to banner height
|
||||
// (this._notificationWidget.y = -this._notificationWidget.height).
|
||||
// We tween any notification showing in the banner mode to the appropriate height
|
||||
// (which is banner height or expanded height, depending on the notification state)
|
||||
// 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 banner height.
|
||||
// have been in the process of hiding are shown with the correct height.
|
||||
//
|
||||
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
|
||||
// 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,
|
||||
y: -this._notificationWidget.height,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: this._showNotificationCompleted,
|
||||
onCompleteScope: this
|
||||
};
|
||||
if (!this._notification.expanded)
|
||||
tweenParams.y = -this._notificationWidget.height;
|
||||
|
||||
this._tween(this._notificationWidget, '_notificationState', State.SHOWN, tweenParams);
|
||||
},
|
||||
@ -2342,6 +2363,7 @@ const MessageTray = new Lang.Class({
|
||||
}
|
||||
|
||||
if (this._notificationRemoved) {
|
||||
Tweener.removeTweens(this._notificationWidget);
|
||||
this._notificationWidget.y = this.actor.height;
|
||||
this._notificationWidget.opacity = 0;
|
||||
this._notificationState = State.HIDDEN;
|
||||
@ -2406,9 +2428,7 @@ const MessageTray = new Lang.Class({
|
||||
this._notificationWidget.y = expandedY;
|
||||
} else if (this._notification.y != expandedY) {
|
||||
// Tween also opacity here, to override a possible tween that's
|
||||
// currently hiding the notification. This will ensure that the
|
||||
// notification is not removed when the onComplete handler for this
|
||||
// one triggers.
|
||||
// currently hiding the notification.
|
||||
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
|
||||
{ y: expandedY,
|
||||
opacity: 255,
|
||||
@ -2442,12 +2462,21 @@ const MessageTray = new Lang.Class({
|
||||
});
|
||||
},
|
||||
|
||||
_onSourceDoneDisplayingContent: function(source, closeTray) {
|
||||
if (closeTray) {
|
||||
this._escapeTray();
|
||||
} else {
|
||||
this._setClickedSummaryItem(null);
|
||||
this._updateState();
|
||||
}
|
||||
},
|
||||
|
||||
_showSummaryBoxPointer: function() {
|
||||
this._summaryBoxPointerItem = this._clickedSummaryItem;
|
||||
this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated',
|
||||
Lang.bind(this, this._onSummaryBoxPointerContentUpdated));
|
||||
this._sourceDoneDisplayingId = this._summaryBoxPointerItem.source.connect('done-displaying-content',
|
||||
Lang.bind(this, this._escapeTray));
|
||||
Lang.bind(this, this._onSourceDoneDisplayingContent));
|
||||
|
||||
let hasRightClickMenu = this._summaryBoxPointerItem.rightClickMenu != null;
|
||||
if (this._clickedSummaryItemMouseButton == 1 || !hasRightClickMenu) {
|
||||
@ -2470,6 +2499,7 @@ const MessageTray = new Lang.Class({
|
||||
this._summaryBoxPointerItem.prepareNotificationStackForShowing();
|
||||
} else if (this._clickedSummaryItemMouseButton == 3) {
|
||||
this._summaryBoxPointer.bin.child = this._clickedSummaryItem.rightClickMenu;
|
||||
this._summaryBoxPointerCloseClickedId = 0;
|
||||
}
|
||||
|
||||
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
|
||||
@ -2576,8 +2606,10 @@ const MessageTray = new Lang.Class({
|
||||
this._summaryBoxPointer.bin.child = null;
|
||||
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
|
||||
this._summaryBoxPointerContentUpdatedId = 0;
|
||||
this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
|
||||
this._summaryBoxPointerCloseClickedId = 0;
|
||||
if (this._summaryBoxPointerCloseClickedId != 0) {
|
||||
this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
|
||||
this._summaryBoxPointerCloseClickedId = 0;
|
||||
}
|
||||
this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
|
||||
this._summaryBoxPointerDoneDisplayingId = 0;
|
||||
|
||||
|
@ -58,7 +58,7 @@ const ModalDialog = new Lang.Class({
|
||||
|
||||
this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
|
||||
|
||||
this._actionKeys = {};
|
||||
this._buttonKeys = {};
|
||||
this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));
|
||||
|
||||
this._backgroundBin = new St.Bin();
|
||||
@ -95,10 +95,10 @@ const ModalDialog = new Lang.Class({
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
|
||||
this.buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
|
||||
visible: false,
|
||||
vertical: false });
|
||||
this.dialogLayout.add(this._buttonLayout,
|
||||
this.dialogLayout.add(this.buttonLayout,
|
||||
{ expand: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.END });
|
||||
@ -113,35 +113,17 @@ const ModalDialog = new Lang.Class({
|
||||
this._group.destroy();
|
||||
},
|
||||
|
||||
setActionKey: function(key, action) {
|
||||
this._actionKeys[key] = action;
|
||||
clearButtons: function() {
|
||||
this.buttonLayout.destroy_all_children();
|
||||
this._buttonKeys = {};
|
||||
},
|
||||
|
||||
setButtons: function(buttons) {
|
||||
this._buttonLayout.destroy_all_children();
|
||||
this._actionKeys = {};
|
||||
|
||||
this._buttonLayout.visible = (buttons.length > 0);
|
||||
this.clearButtons();
|
||||
this.buttonLayout.visible = (buttons.length > 0);
|
||||
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
let buttonInfo = buttons[i];
|
||||
let label = buttonInfo['label'];
|
||||
let action = buttonInfo['action'];
|
||||
let key = buttonInfo['key'];
|
||||
let isDefault = buttonInfo['default'];
|
||||
|
||||
if (isDefault && !key) {
|
||||
this._actionKeys[Clutter.KEY_KP_Enter] = action;
|
||||
this._actionKeys[Clutter.KEY_ISO_Enter] = action;
|
||||
key = Clutter.KEY_Return;
|
||||
}
|
||||
|
||||
buttonInfo.button = new St.Button({ style_class: 'modal-dialog-button',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
label: label });
|
||||
if (isDefault)
|
||||
buttonInfo.button.add_style_pseudo_class('default');
|
||||
|
||||
let x_alignment;
|
||||
if (buttons.length == 1)
|
||||
@ -153,29 +135,62 @@ const ModalDialog = new Lang.Class({
|
||||
else
|
||||
x_alignment = St.Align.MIDDLE;
|
||||
|
||||
if (!this._initialKeyFocusDestroyId)
|
||||
this._initialKeyFocus = buttonInfo.button;
|
||||
this._buttonLayout.add(buttonInfo.button,
|
||||
{ expand: true,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: x_alignment,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
buttonInfo.button.connect('clicked', action);
|
||||
|
||||
if (key)
|
||||
this._actionKeys[key] = action;
|
||||
this.addButton(buttonInfo, { expand: true,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: x_alignment,
|
||||
y_align: St.Align.MIDDLE });
|
||||
}
|
||||
},
|
||||
|
||||
this.emit('buttons-set');
|
||||
addButton: function(buttonInfo, layoutInfo) {
|
||||
let label = buttonInfo['label'];
|
||||
let action = buttonInfo['action'];
|
||||
let key = buttonInfo['key'];
|
||||
let isDefault = buttonInfo['default'];
|
||||
|
||||
let keys;
|
||||
|
||||
if (key)
|
||||
keys = [key];
|
||||
else if (isDefault)
|
||||
keys = [Clutter.KEY_Return, Clutter.KEY_KP_Enter, Clutter.KEY_ISO_Enter];
|
||||
else
|
||||
keys = [];
|
||||
|
||||
let button = new St.Button({ style_class: 'modal-dialog-button',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
label: label });
|
||||
button.connect('clicked', action);
|
||||
|
||||
buttonInfo['button'] = button;
|
||||
|
||||
if (isDefault)
|
||||
button.add_style_pseudo_class('default');
|
||||
|
||||
if (!this._initialKeyFocusDestroyId)
|
||||
this._initialKeyFocus = button;
|
||||
|
||||
for (let i in keys)
|
||||
this._buttonKeys[keys[i]] = buttonInfo;
|
||||
|
||||
this.buttonLayout.add(button, layoutInfo);
|
||||
|
||||
return button;
|
||||
},
|
||||
|
||||
_onKeyReleaseEvent: function(object, event) {
|
||||
let symbol = event.get_key_symbol();
|
||||
let action = this._actionKeys[symbol];
|
||||
let buttonInfo = this._buttonKeys[symbol];
|
||||
|
||||
if (action) {
|
||||
if (!buttonInfo)
|
||||
return false;
|
||||
|
||||
let button = buttonInfo['button'];
|
||||
let action = buttonInfo['action'];
|
||||
|
||||
if (action && button.reactive) {
|
||||
action();
|
||||
return true;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
|
||||
const CenterLayout = imports.ui.centerLayout;
|
||||
const Dash = imports.ui.dash;
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
@ -23,9 +24,6 @@ const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
// Time for initial animation going into Overview mode
|
||||
const ANIMATION_TIME = 0.25;
|
||||
|
||||
// XXX -- grab this automatically. Hard to do.
|
||||
const DASH_MAX_WIDTH = 96;
|
||||
|
||||
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
|
||||
|
||||
const GLSL_DIM_EFFECT_DECLARATIONS = '';
|
||||
@ -46,18 +44,6 @@ const GLSL_DIM_EFFECT_CODE = '\
|
||||
cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
|
||||
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({
|
||||
Name: 'ShellInfo',
|
||||
|
||||
@ -112,11 +98,19 @@ const ShellInfo = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const ControlsChange = {
|
||||
BEFORE_PAGE: 1,
|
||||
AFTER_PAGE: 2,
|
||||
DND_START: 3,
|
||||
DND_END: 4
|
||||
};
|
||||
|
||||
const Overview = new Lang.Class({
|
||||
Name: 'Overview',
|
||||
|
||||
_init: function() {
|
||||
this._overviewCreated = false;
|
||||
this._initCalled = false;
|
||||
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
||||
this._sessionUpdated();
|
||||
@ -147,26 +141,28 @@ const Overview = new Lang.Class({
|
||||
this._desktopFade = new St.Bin();
|
||||
global.overlay_group.add_actor(this._desktopFade);
|
||||
|
||||
this._spacing = 0;
|
||||
|
||||
/* Translators: This is the main view to select
|
||||
activities. See also note for "Activities" string. */
|
||||
this._group = new St.Widget({ name: 'overview',
|
||||
accessible_name: _("Overview"),
|
||||
reactive: true });
|
||||
this._group._delegate = this;
|
||||
this._overview = new St.BoxLayout({ name: 'overview',
|
||||
accessible_name: _("Overview"),
|
||||
reactive: true,
|
||||
vertical: true });
|
||||
this._overview._delegate = this;
|
||||
|
||||
let layout = new CenterLayout.CenterLayout();
|
||||
this._group = new St.Widget({ name: 'overview-group',
|
||||
layout_manager: layout });
|
||||
|
||||
this._spacing = 0;
|
||||
this._group.connect('style-changed',
|
||||
Lang.bind(this, function() {
|
||||
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._buttonPressId = 0;
|
||||
|
||||
@ -182,12 +178,11 @@ const Overview = new Lang.Class({
|
||||
// Dash elements, or mouseover handlers in the workspaces.
|
||||
this._coverPane = new Clutter.Rectangle({ opacity: 0,
|
||||
reactive: true });
|
||||
this._group.add_actor(this._coverPane);
|
||||
this._overview.add_actor(this._coverPane);
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||
|
||||
|
||||
this._group.hide();
|
||||
global.overlay_group.add_actor(this._group);
|
||||
this._overview.hide();
|
||||
global.overlay_group.add_actor(this._overview);
|
||||
|
||||
this._coverPane.hide();
|
||||
|
||||
@ -199,11 +194,16 @@ const Overview = new Lang.Class({
|
||||
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
|
||||
global.screen.connect('restacked', Lang.bind(this, this._onRestacked));
|
||||
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._windowSwitchTimestamp = 0;
|
||||
this._lastActiveWorkspaceIndex = -1;
|
||||
this._lastHoveredWindow = null;
|
||||
this._needsFakePointerEvent = false;
|
||||
|
||||
if (this._initCalled)
|
||||
this.init();
|
||||
},
|
||||
|
||||
_sessionUpdated: function() {
|
||||
@ -216,11 +216,20 @@ const Overview = new Lang.Class({
|
||||
// signal handlers and so forth. So we create them after
|
||||
// construction in this init() method.
|
||||
init: function() {
|
||||
this._initCalled = true;
|
||||
|
||||
if (this.isDummy)
|
||||
return;
|
||||
|
||||
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',
|
||||
/* Translators: this is the text displayed
|
||||
in the search entry when no search is
|
||||
@ -229,16 +238,13 @@ const Overview = new Lang.Class({
|
||||
hint_text: _("Type to search..."),
|
||||
track_hover: true,
|
||||
can_focus: true });
|
||||
this._group.add_actor(this._searchEntry);
|
||||
|
||||
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);
|
||||
this._searchEntryBin = new St.Bin({ child: this._searchEntry,
|
||||
x_align: St.Align.MIDDLE });
|
||||
this._overview.add_actor(this._searchEntryBin);
|
||||
|
||||
// TODO - recalculate everything when desktop size changes
|
||||
this._dash.actor.add_constraint(this._viewSelector.constrainHeight);
|
||||
this._dash = new Dash.Dash();
|
||||
this._group.add_actor(this._dash.actor);
|
||||
this.dashIconSize = this._dash.iconSize;
|
||||
this._dash.connect('icon-size-changed',
|
||||
Lang.bind(this, function() {
|
||||
@ -249,10 +255,99 @@ const Overview = new Lang.Class({
|
||||
// the left of the overview
|
||||
Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks-symbolic');
|
||||
|
||||
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
|
||||
this._dash.showAppsButton);
|
||||
this._group.add_actor(this._viewSelector.actor);
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
this._group.add_actor(this._thumbnailsBox.actor);
|
||||
|
||||
Main.ctrlAltTabManager.addGroup(this._thumbnailsBox.actor, _("Workspaces"), 'view-list-symbolic');
|
||||
|
||||
// Add our same-line elements after the search entry
|
||||
this._overview.add_actor(this._group);
|
||||
|
||||
// Then account for message tray
|
||||
this._messageTrayGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.messageTray.actor }),
|
||||
reactive: false,
|
||||
opacity: 0,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
this._overview.add_actor(this._messageTrayGhost);
|
||||
|
||||
this._viewSelector.connect('after-page-change', Lang.bind(this,
|
||||
function() {
|
||||
this._setSideControlsVisibility(ControlsChange.AFTER_PAGE);
|
||||
}));
|
||||
this._viewSelector.connect('before-page-change', Lang.bind(this,
|
||||
function() {
|
||||
this._setSideControlsVisibility(ControlsChange.BEFORE_PAGE);
|
||||
}));
|
||||
|
||||
this.connect('item-drag-begin', Lang.bind(this,
|
||||
function() {
|
||||
this._setSideControlsVisibility(ControlsChange.DND_START);
|
||||
}));
|
||||
this.connect('item-drag-cancelled', Lang.bind(this,
|
||||
function() {
|
||||
this._setSideControlsVisibility(ControlsChange.DND_END);
|
||||
}));
|
||||
this.connect('item-drag-end', Lang.bind(this,
|
||||
function() {
|
||||
this._setSideControlsVisibility(ControlsChange.DND_END);
|
||||
}));
|
||||
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
|
||||
this._relayout();
|
||||
},
|
||||
|
||||
_setSideControlsVisibility: function(changeType) {
|
||||
// Ignore the case when we're leaving the overview, since
|
||||
// actors will be made visible again when entering the overview
|
||||
// next time, and animating them while doing so is just
|
||||
// unnecesary noise
|
||||
if (!this.visible || this.animationInProgress)
|
||||
return;
|
||||
|
||||
let appsActive = this._viewSelector.getAppsActive();
|
||||
let searchActive = this._viewSelector.getSearchActive();
|
||||
let dashVisible = !searchActive || (changeType == ControlsChange.DND_START);
|
||||
let thumbnailsVisible = (!searchActive && !appsActive) || (changeType == ControlsChange.DND_START);
|
||||
let trayVisible = !searchActive;
|
||||
let trayGhostVisible = trayVisible || dashVisible;
|
||||
|
||||
if ((changeType == ControlsChange.BEFORE_PAGE) ||
|
||||
(changeType == ControlsChange.DND_START)) {
|
||||
if (dashVisible)
|
||||
this._dash.show();
|
||||
if (thumbnailsVisible)
|
||||
this._thumbnailsBox.show();
|
||||
}
|
||||
|
||||
if ((changeType == ControlsChange.BEFORE_PAGE) ||
|
||||
(changeType == ControlsChange.DND_END)) {
|
||||
if (!dashVisible) {
|
||||
this._dash.hide();
|
||||
}
|
||||
if (!thumbnailsVisible)
|
||||
this._thumbnailsBox.hide();
|
||||
}
|
||||
|
||||
if (changeType == ControlsChange.BEFORE_PAGE ||
|
||||
changeType == ControlsChange.DND_START) {
|
||||
if (trayGhostVisible)
|
||||
this._messageTrayGhost.show();
|
||||
if (trayVisible)
|
||||
Main.messageTray.show();
|
||||
else
|
||||
Main.messageTray.hide();
|
||||
} else if (changeType == ControlsChange.AFTER_PAGE ||
|
||||
changeType == ControlsChange.DND_END) {
|
||||
if (!trayGhostVisible)
|
||||
this._messageTrayGhost.hide();
|
||||
}
|
||||
},
|
||||
|
||||
addSearchProvider: function(provider) {
|
||||
this._viewSelector.addSearchProvider(provider);
|
||||
},
|
||||
@ -341,159 +436,11 @@ const Overview = new Lang.Class({
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
|
||||
setScrollAdjustment: function(adjustment, direction) {
|
||||
addAction: function(action) {
|
||||
if (this.isDummy)
|
||||
return;
|
||||
|
||||
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;
|
||||
this._overview.add_action(action);
|
||||
},
|
||||
|
||||
_getDesktopClone: function() {
|
||||
@ -519,41 +466,27 @@ const Overview = new Lang.Class({
|
||||
this.hide();
|
||||
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
let contentY = Main.panel.actor.height;
|
||||
let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
|
||||
|
||||
this._group.set_position(primary.x, primary.y);
|
||||
this._group.set_size(primary.width, primary.height);
|
||||
this._overview.set_position(primary.x, primary.y);
|
||||
this._overview.set_size(primary.width, primary.height);
|
||||
|
||||
this._coverPane.set_position(0, contentY);
|
||||
this._coverPane.set_size(primary.width, contentHeight);
|
||||
},
|
||||
|
||||
let searchWidth = this._searchEntry.get_width();
|
||||
let searchHeight = this._searchEntry.get_height();
|
||||
let searchX = (primary.width - searchWidth) / 2;
|
||||
let searchY = contentY + this._spacing;
|
||||
_onRestacked: function() {
|
||||
let stack = global.get_window_actors();
|
||||
let stackIndices = {};
|
||||
|
||||
let dashWidth = DASH_MAX_WIDTH;
|
||||
let dashY = searchY + searchHeight + this._spacing;
|
||||
let dashX;
|
||||
if (rtl) {
|
||||
this._dash.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
|
||||
dashX = primary.width;
|
||||
} else {
|
||||
dashX = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
this.emit('sync-window-stacking', stackIndices);
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
@ -590,15 +523,11 @@ const Overview = new Lang.Class({
|
||||
return;
|
||||
if (this._shown)
|
||||
return;
|
||||
// Do this manually instead of using _syncInputMode, to handle failure
|
||||
if (!Main.pushModal(this._group, { keybindingMode: Main.KeybindingMode.OVERVIEW }))
|
||||
return;
|
||||
this._modal = true;
|
||||
this._animateVisible();
|
||||
this._shown = true;
|
||||
|
||||
this._buttonPressId = this._group.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
this._syncInputMode();
|
||||
if (!this._modal)
|
||||
return;
|
||||
this._animateVisible();
|
||||
},
|
||||
|
||||
fadeInDesktop: function() {
|
||||
@ -641,12 +570,13 @@ const Overview = new Lang.Class({
|
||||
// Disable unredirection while in the overview
|
||||
Meta.disable_unredirect_for_screen(global.screen);
|
||||
global.window_group.hide();
|
||||
this._group.show();
|
||||
this._messageTrayGhost.show();
|
||||
this._overview.show();
|
||||
this._background.show();
|
||||
this._viewSelector.show();
|
||||
|
||||
this._group.opacity = 0;
|
||||
Tweener.addTween(this._group,
|
||||
this._overview.opacity = 0;
|
||||
Tweener.addTween(this._overview,
|
||||
{ opacity: 255,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
@ -698,10 +628,6 @@ const Overview = new Lang.Class({
|
||||
|
||||
this._shown = false;
|
||||
this._syncInputMode();
|
||||
|
||||
if (this._buttonPressId > 0)
|
||||
this._group.disconnect(this._buttonPressId);
|
||||
this._buttonPressId = 0;
|
||||
},
|
||||
|
||||
// hideTemporarily:
|
||||
@ -725,7 +651,7 @@ const Overview = new Lang.Class({
|
||||
if (this.isDummy)
|
||||
return;
|
||||
|
||||
if (this._shown)
|
||||
if (this.visible)
|
||||
this.hide();
|
||||
else
|
||||
this.show();
|
||||
@ -742,7 +668,7 @@ const Overview = new Lang.Class({
|
||||
|
||||
if (this._shown) {
|
||||
if (!this._modal) {
|
||||
if (Main.pushModal(this._group,
|
||||
if (Main.pushModal(this._overview,
|
||||
{ keybindingMode: Main.KeybindingMode.OVERVIEW }))
|
||||
this._modal = true;
|
||||
else
|
||||
@ -750,13 +676,13 @@ const Overview = new Lang.Class({
|
||||
}
|
||||
} else if (this._shownTemporarily) {
|
||||
if (this._modal) {
|
||||
Main.popModal(this._group);
|
||||
Main.popModal(this._overview);
|
||||
this._modal = false;
|
||||
}
|
||||
global.stage_input_mode = Shell.StageInputMode.FULLSCREEN;
|
||||
} else {
|
||||
if (this._modal) {
|
||||
Main.popModal(this._group);
|
||||
Main.popModal(this._overview);
|
||||
this._modal = false;
|
||||
}
|
||||
else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN)
|
||||
@ -774,7 +700,7 @@ const Overview = new Lang.Class({
|
||||
this._viewSelector.zoomFromOverview();
|
||||
|
||||
// Make other elements fade out.
|
||||
Tweener.addTween(this._group,
|
||||
Tweener.addTween(this._overview,
|
||||
{ opacity: 0,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
@ -816,7 +742,7 @@ const Overview = new Lang.Class({
|
||||
this._viewSelector.hide();
|
||||
this._desktopFade.hide();
|
||||
this._background.hide();
|
||||
this._group.hide();
|
||||
this._overview.hide();
|
||||
|
||||
this.visible = false;
|
||||
this.animationInProgress = false;
|
||||
|
240
js/ui/panel.js
240
js/ui/panel.js
@ -15,6 +15,7 @@ const Signals = imports.signals;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
|
||||
const CenterLayout = imports.ui.centerLayout;
|
||||
const Config = imports.misc.config;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const DND = imports.ui.dnd;
|
||||
@ -75,19 +76,19 @@ function _unpremultiply(color) {
|
||||
blue: blue, alpha: color.alpha });
|
||||
};
|
||||
|
||||
const Animation = new Lang.Class({
|
||||
Name: 'Animation',
|
||||
|
||||
const AnimatedIcon = new Lang.Class({
|
||||
Name: 'AnimatedIcon',
|
||||
|
||||
_init: function(name, size) {
|
||||
this.actor = new St.Bin({ visible: false });
|
||||
_init: function(filename, width, height, speed) {
|
||||
this.actor = new St.Bin();
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
this._speed = speed;
|
||||
|
||||
this._isLoaded = false;
|
||||
this._isPlaying = false;
|
||||
this._timeoutId = 0;
|
||||
this._frame = 0;
|
||||
this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size,
|
||||
this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height,
|
||||
Lang.bind(this, this._animationsLoaded));
|
||||
this.actor.set_child(this._animations);
|
||||
},
|
||||
@ -97,7 +98,7 @@ const AnimatedIcon = new Lang.Class({
|
||||
if (this._frame == 0)
|
||||
this._showFrame(0);
|
||||
|
||||
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
|
||||
this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
|
||||
}
|
||||
|
||||
this._isPlaying = true;
|
||||
@ -132,10 +133,8 @@ const AnimatedIcon = new Lang.Class({
|
||||
_animationsLoaded: function() {
|
||||
this._isLoaded = true;
|
||||
|
||||
if (this._isPlaying) {
|
||||
this._showFrame(0);
|
||||
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
|
||||
}
|
||||
if (this._isPlaying)
|
||||
this.play();
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
@ -143,6 +142,15 @@ const AnimatedIcon = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const AnimatedIcon = new Lang.Class({
|
||||
Name: 'AnimatedIcon',
|
||||
Extends: Animation,
|
||||
|
||||
_init: function(name, size) {
|
||||
this.parent(global.datadir + '/theme/' + name, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
|
||||
}
|
||||
});
|
||||
|
||||
const TextShadower = new Lang.Class({
|
||||
Name: 'TextShadower',
|
||||
|
||||
@ -294,6 +302,7 @@ const AppMenuButton = new Lang.Class({
|
||||
this._spinner = new AnimatedIcon('process-working.svg',
|
||||
PANEL_ICON_SIZE);
|
||||
this._container.add_actor(this._spinner.actor);
|
||||
this._spinner.actor.hide();
|
||||
this._spinner.actor.lower_bottom();
|
||||
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
@ -591,11 +600,12 @@ const AppMenuButton = new Lang.Class({
|
||||
|
||||
menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
|
||||
} else {
|
||||
if (this.menu && !(this.menu instanceof PopupMenu.RemoteMenu))
|
||||
if (this.menu.isDummyQuitMenu)
|
||||
return;
|
||||
|
||||
// fallback to older menu
|
||||
menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
|
||||
menu.isDummyQuitMenu = true;
|
||||
menu.addAction(_("Quit"), Lang.bind(this, function() {
|
||||
this._targetApp.request_quit();
|
||||
}));
|
||||
@ -608,15 +618,12 @@ const AppMenuButton = new Lang.Class({
|
||||
|
||||
Signals.addSignalMethods(AppMenuButton.prototype);
|
||||
|
||||
// Activities button. Because everything else in the top bar is a
|
||||
// PanelMenu.Button, it simplifies some things to make this be one too.
|
||||
// We just hack it up to not actually have a menu attached to it.
|
||||
const ActivitiesButton = new Lang.Class({
|
||||
Name: 'ActivitiesButton',
|
||||
Extends: PanelMenu.Button,
|
||||
|
||||
_init: function() {
|
||||
this.parent(0.0);
|
||||
this.parent(0.0, null, true);
|
||||
this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON;
|
||||
|
||||
let container = new Shell.GenericContainer();
|
||||
@ -636,27 +643,27 @@ const ActivitiesButton = new Lang.Class({
|
||||
this.hotCorner = new Layout.HotCorner();
|
||||
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_after('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
|
||||
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
this.actor.add_style_pseudo_class('overview');
|
||||
this._escapeMenuGrab();
|
||||
this.actor.add_accessible_state (Atk.StateType.CHECKED);
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||
this.actor.remove_style_pseudo_class('overview');
|
||||
this._escapeMenuGrab();
|
||||
this.actor.remove_accessible_state (Atk.StateType.CHECKED);
|
||||
}));
|
||||
|
||||
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) {
|
||||
@ -702,11 +709,6 @@ const ActivitiesButton = new Lang.Class({
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
|
||||
_escapeMenuGrab: function() {
|
||||
if (this.menu.isOpen)
|
||||
this.menu.close();
|
||||
},
|
||||
|
||||
_onCapturedEvent: function(actor, event) {
|
||||
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||
if (!this.hotCorner.shouldToggleOverviewOnClick())
|
||||
@ -715,33 +717,13 @@ const ActivitiesButton = new Lang.Class({
|
||||
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() {
|
||||
if (this.menu.isOpen) {
|
||||
this.menu.close();
|
||||
Main.overview.toggle();
|
||||
}
|
||||
Main.overview.toggle();
|
||||
},
|
||||
|
||||
_onKeyRelease: function(actor, event) {
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
|
||||
if (this.menu.isOpen)
|
||||
this.menu.close();
|
||||
Main.overview.toggle();
|
||||
}
|
||||
},
|
||||
@ -882,10 +864,13 @@ const PanelCorner = new Lang.Class({
|
||||
let backgroundColor = node.get_color('-panel-corner-background-color');
|
||||
let borderColor = node.get_color('-panel-corner-border-color');
|
||||
|
||||
let noOverlap = borderColor.alpha == 0;
|
||||
let offsetY = noOverlap ? borderWidth : 0;
|
||||
|
||||
let cr = this.actor.get_context();
|
||||
cr.setOperator(Cairo.Operator.SOURCE);
|
||||
|
||||
cr.moveTo(0, 0);
|
||||
cr.moveTo(0, offsetY);
|
||||
if (this._side == St.Side.LEFT)
|
||||
cr.arc(cornerRadius,
|
||||
borderWidth + cornerRadius,
|
||||
@ -894,7 +879,7 @@ const PanelCorner = new Lang.Class({
|
||||
cr.arc(0,
|
||||
borderWidth + cornerRadius,
|
||||
cornerRadius, 3 * Math.PI / 2, 2 * Math.PI);
|
||||
cr.lineTo(cornerRadius, 0);
|
||||
cr.lineTo(cornerRadius, offsetY);
|
||||
cr.closePath();
|
||||
|
||||
let savedPath = cr.copyPath();
|
||||
@ -904,6 +889,9 @@ const PanelCorner = new Lang.Class({
|
||||
Clutter.cairo_set_source_color(cr, over);
|
||||
cr.fill();
|
||||
|
||||
if (noOverlap)
|
||||
return;
|
||||
|
||||
let offset = borderWidth;
|
||||
Clutter.cairo_set_source_color(cr, backgroundColor);
|
||||
|
||||
@ -950,22 +938,52 @@ try {
|
||||
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
|
||||
}
|
||||
|
||||
const PanelLayout = new Lang.Class({
|
||||
Name: 'PanelLayout',
|
||||
Extends: CenterLayout.CenterLayout,
|
||||
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
this.parent(container, box, flags);
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
|
||||
let [left, center, right, leftCorner, rightCorner] = container.get_children();
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
let cornerMinWidth, cornerMinHeight;
|
||||
let cornerWidth, cornerHeight;
|
||||
|
||||
[cornerMinWidth, cornerWidth] = leftCorner.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = leftCorner.get_preferred_height(-1);
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = cornerWidth;
|
||||
childBox.y1 = availHeight;
|
||||
childBox.y2 = availHeight + cornerHeight;
|
||||
leftCorner.allocate(childBox, flags);
|
||||
|
||||
[cornerMinWidth, cornerWidth] = rightCorner.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = rightCorner.get_preferred_height(-1);
|
||||
childBox.x1 = availWidth - cornerWidth;
|
||||
childBox.x2 = availWidth;
|
||||
childBox.y1 = availHeight;
|
||||
childBox.y2 = availHeight + cornerHeight;
|
||||
rightCorner.allocate(childBox, flags);
|
||||
}
|
||||
});
|
||||
|
||||
const Panel = new Lang.Class({
|
||||
Name: 'Panel',
|
||||
|
||||
_init : function() {
|
||||
this.actor = new Shell.GenericContainer({ name: 'panel',
|
||||
reactive: true });
|
||||
this.actor = new St.Widget({ name: 'panel',
|
||||
reactive: true,
|
||||
layoutManager: new PanelLayout() });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.statusArea = {};
|
||||
this._sessionStyle = null;
|
||||
|
||||
Main.overview.connect('shown', Lang.bind(this, function () {
|
||||
this.actor.add_style_class_name('in-overview');
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this, function () {
|
||||
this.actor.remove_style_class_name('in-overview');
|
||||
}));
|
||||
this.statusArea = {};
|
||||
|
||||
this.menuManager = new PopupMenu.PopupMenuManager(this);
|
||||
|
||||
@ -980,7 +998,6 @@ const Panel = new Lang.Class({
|
||||
this._leftCorner = new PanelCorner(this._rightBox, St.Side.LEFT);
|
||||
else
|
||||
this._leftCorner = new PanelCorner(this._leftBox, St.Side.LEFT);
|
||||
|
||||
this.actor.add_actor(this._leftCorner.actor);
|
||||
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
||||
@ -989,96 +1006,16 @@ const Panel = new Lang.Class({
|
||||
this._rightCorner = new PanelCorner(this._rightBox, St.Side.RIGHT);
|
||||
this.actor.add_actor(this._rightCorner.actor);
|
||||
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
|
||||
Main.layoutManager.panelBox.add(this.actor);
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here-symbolic',
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic',
|
||||
{ sortGroup: CtrlAltTab.SortGroup.TOP });
|
||||
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._updatePanel));
|
||||
this._updatePanel();
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
alloc.min_size = -1;
|
||||
alloc.natural_size = Main.layoutManager.primaryMonitor.width;
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
// We don't need to implement this; it's forced by the CSS
|
||||
alloc.min_size = -1;
|
||||
alloc.natural_size = -1;
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let allocWidth = box.x2 - box.x1;
|
||||
let allocHeight = box.y2 - box.y1;
|
||||
|
||||
let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
|
||||
let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
|
||||
let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
|
||||
|
||||
let sideWidth, centerWidth;
|
||||
centerWidth = centerNaturalWidth;
|
||||
sideWidth = (allocWidth - centerWidth) / 2;
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = allocHeight;
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
childBox.x1 = allocWidth - Math.min(Math.floor(sideWidth),
|
||||
leftNaturalWidth);
|
||||
childBox.x2 = allocWidth;
|
||||
} else {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
||||
leftNaturalWidth);
|
||||
}
|
||||
this._leftBox.allocate(childBox, flags);
|
||||
|
||||
childBox.x1 = Math.ceil(sideWidth);
|
||||
childBox.y1 = 0;
|
||||
childBox.x2 = childBox.x1 + centerWidth;
|
||||
childBox.y2 = allocHeight;
|
||||
this._centerBox.allocate(childBox, flags);
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = allocHeight;
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
||||
rightNaturalWidth);
|
||||
} else {
|
||||
childBox.x1 = allocWidth - Math.min(Math.floor(sideWidth),
|
||||
rightNaturalWidth);
|
||||
childBox.x2 = allocWidth;
|
||||
}
|
||||
this._rightBox.allocate(childBox, flags);
|
||||
|
||||
let cornerMinWidth, cornerMinHeight;
|
||||
let cornerWidth, cornerHeight;
|
||||
|
||||
[cornerMinWidth, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = cornerWidth;
|
||||
childBox.y1 = allocHeight;
|
||||
childBox.y2 = allocHeight + cornerHeight;
|
||||
this._leftCorner.actor.allocate(childBox, flags);
|
||||
|
||||
[cornerMinWidth, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
|
||||
childBox.x1 = allocWidth - cornerWidth;
|
||||
childBox.x2 = allocWidth;
|
||||
childBox.y1 = allocHeight;
|
||||
childBox.y2 = allocHeight + cornerHeight;
|
||||
this._rightCorner.actor.allocate(childBox, flags);
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (event.get_source() != actor)
|
||||
return false;
|
||||
@ -1152,6 +1089,13 @@ const Panel = new Lang.Class({
|
||||
this._updateBox(panel.left, this._leftBox);
|
||||
this._updateBox(panel.center, this._centerBox);
|
||||
this._updateBox(panel.right, this._rightBox);
|
||||
|
||||
if (this._sessionStyle)
|
||||
this._removeStyleClassName(this._sessionStyle);
|
||||
|
||||
this._sessionStyle = Main.sessionMode.panelStyle;
|
||||
if (this._sessionStyle)
|
||||
this._addStyleClassName(this._sessionStyle);
|
||||
},
|
||||
|
||||
_initBox: function(elements, box) {
|
||||
@ -1240,5 +1184,17 @@ const Panel = new Lang.Class({
|
||||
this.statusArea[role] = indicator;
|
||||
this._addToPanelBox(role, indicator, position, boxContainer);
|
||||
return indicator;
|
||||
},
|
||||
|
||||
_addStyleClassName: function(className) {
|
||||
this.actor.add_style_class_name(className);
|
||||
this._rightCorner.actor.add_style_class_name(className);
|
||||
this._leftCorner.actor.add_style_class_name(className);
|
||||
},
|
||||
|
||||
_removeStyleClassName: function(className) {
|
||||
this.actor.remove_style_class_name(className);
|
||||
this._rightCorner.actor.remove_style_class_name(className);
|
||||
this._leftCorner.actor.remove_style_class_name(className);
|
||||
}
|
||||
});
|
||||
|
@ -112,7 +112,7 @@ const Button = new Lang.Class({
|
||||
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
|
||||
|
||||
if (dontCreateMenu)
|
||||
this.menu = null;
|
||||
this.menu = new PopupMenu.PopupDummyMenu(this.actor);
|
||||
else
|
||||
this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Cairo = imports.cairo;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
@ -12,8 +11,10 @@ const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const BoxPointer = imports.ui.boxpointer;
|
||||
const GrabHelper = imports.ui.grabHelper;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Separator = imports.ui.separator;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
|
||||
@ -404,29 +405,8 @@ const PopupSeparatorMenuItem = new Lang.Class({
|
||||
this.parent({ reactive: false,
|
||||
can_focus: false});
|
||||
|
||||
this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
|
||||
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();
|
||||
this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' });
|
||||
this.addActor(this._separator.actor, { span: -1, expand: true });
|
||||
}
|
||||
});
|
||||
|
||||
@ -1204,7 +1184,6 @@ const PopupMenu = new Lang.Class({
|
||||
this.actor = this._boxPointer.actor;
|
||||
this.actor._delegate = this;
|
||||
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.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
|
||||
@ -1234,15 +1213,6 @@ const PopupMenu = new Lang.Class({
|
||||
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) {
|
||||
this._boxPointer.setArrowOrigin(origin);
|
||||
},
|
||||
@ -1283,6 +1253,28 @@ 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({
|
||||
Name: 'PopupSubMenu',
|
||||
Extends: PopupMenuBase,
|
||||
@ -1537,7 +1529,6 @@ const PopupComboMenu = new Lang.Class({
|
||||
|
||||
this.actor = this.box;
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
|
||||
sourceActor.connect('style-changed',
|
||||
Lang.bind(this, this._onSourceActorStyleChanged));
|
||||
@ -1545,15 +1536,6 @@ const PopupComboMenu = new Lang.Class({
|
||||
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) {
|
||||
let items = this._getMenuItems();
|
||||
let activeItem = items[this._activeItemPos];
|
||||
@ -2044,17 +2026,8 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
_init: function(owner) {
|
||||
this._owner = owner;
|
||||
this.grabbed = false;
|
||||
|
||||
this._eventCaptureId = 0;
|
||||
this._enterEventId = 0;
|
||||
this._leaveEventId = 0;
|
||||
this._keyFocusNotifyId = 0;
|
||||
this._activeMenu = null;
|
||||
this._grabHelper = new GrabHelper.GrabHelper(owner.actor);
|
||||
this._menus = [];
|
||||
this._menuStack = [];
|
||||
this._preGrabInputMode = null;
|
||||
this._grabbedFromKeynav = false;
|
||||
},
|
||||
|
||||
addMenu: function(menu, position) {
|
||||
@ -2073,6 +2046,8 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
let source = menu.sourceActor;
|
||||
if (source) {
|
||||
if (!menu.blockSourceEvents)
|
||||
this._grabHelper.addActor(source);
|
||||
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); }));
|
||||
}
|
||||
@ -2085,7 +2060,7 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
removeMenu: function(menu) {
|
||||
if (menu == this._activeMenu)
|
||||
this._closeMenu();
|
||||
this._closeMenu(menu);
|
||||
|
||||
let position = this._findMenu(menu);
|
||||
if (position == -1) // not a menu we manage
|
||||
@ -2102,79 +2077,29 @@ const PopupMenuManager = new Lang.Class({
|
||||
if (menudata.focusInId)
|
||||
menu.sourceActor.disconnect(menudata.focusInId);
|
||||
|
||||
if (menu.sourceActor)
|
||||
this._grabHelper.removeActor(menu.sourceActor);
|
||||
this._menus.splice(position, 1);
|
||||
},
|
||||
|
||||
_grab: function() {
|
||||
Main.pushModal(this._owner.actor);
|
||||
|
||||
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
|
||||
// captured-event doesn't see enter/leave events
|
||||
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;
|
||||
get activeMenu() {
|
||||
let actor = this._grabHelper.currentGrab.actor;
|
||||
if (actor)
|
||||
return actor._delegate;
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
_ungrab: function() {
|
||||
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);
|
||||
ignoreRelease: function() {
|
||||
return this._grabHelper.ignoreRelease();
|
||||
},
|
||||
|
||||
_onMenuOpenState: function(menu, open) {
|
||||
if (open) {
|
||||
if (this._activeMenu && this._activeMenu.isChildMenu(menu)) {
|
||||
this._menuStack.push(this._activeMenu);
|
||||
menu.actor.grab_key_focus();
|
||||
}
|
||||
this._activeMenu = menu;
|
||||
this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor,
|
||||
onUngrab: Lang.bind(this, this._closeMenu, menu) });
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
this._grabHelper.ungrab({ actor: menu.actor });
|
||||
}
|
||||
},
|
||||
|
||||
@ -2186,87 +2111,38 @@ const PopupMenuManager = new Lang.Class({
|
||||
this.removeMenu(childMenu);
|
||||
},
|
||||
|
||||
// change the currently-open menu without dropping grab
|
||||
_changeMenu: function(newMenu) {
|
||||
if (this._activeMenu) {
|
||||
// _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);
|
||||
let oldMenu = this.activeMenu;
|
||||
if (oldMenu) {
|
||||
oldMenu.close(BoxPointer.PopupAnimation.FADE);
|
||||
newMenu.open(BoxPointer.PopupAnimation.FADE);
|
||||
} else
|
||||
} else {
|
||||
newMenu.open(BoxPointer.PopupAnimation.FULL);
|
||||
}
|
||||
},
|
||||
|
||||
_onMenuSourceEnter: function(menu) {
|
||||
if (!this.grabbed || menu == this._activeMenu)
|
||||
if (!this._grabHelper.grabbed)
|
||||
return false;
|
||||
|
||||
if (this._activeMenu && this._activeMenu.isChildMenu(menu))
|
||||
if (this._grabHelper.isActorGrabbed(menu.actor))
|
||||
return false;
|
||||
|
||||
if (this._menuStack.indexOf(menu) != -1)
|
||||
return false;
|
||||
|
||||
if (this._menuStack.length > 0 && this._menuStack[0].isChildMenu(menu))
|
||||
let isChildMenu = this._grabHelper.grabStack.some(function(grab) {
|
||||
let existingMenu = grab.actor._delegate;
|
||||
return existingMenu.isChildMenu(menu);
|
||||
});
|
||||
if (isChildMenu)
|
||||
return false;
|
||||
|
||||
this._changeMenu(menu);
|
||||
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) {
|
||||
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) {
|
||||
for (let i = 0; i < this._menus.length; i++) {
|
||||
let menudata = this._menus[i];
|
||||
@ -2276,41 +2152,11 @@ const PopupMenuManager = new Lang.Class({
|
||||
return -1;
|
||||
},
|
||||
|
||||
_onEventCapture: function(actor, event) {
|
||||
if (!this.grabbed)
|
||||
return false;
|
||||
|
||||
if (this._owner.menuEventFilter &&
|
||||
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);
|
||||
_closeMenu: function(isUser, menu) {
|
||||
// If this isn't a user action, we called close()
|
||||
// on the BoxPointer ourselves, so we shouldn't
|
||||
// reanimate.
|
||||
if (isUser)
|
||||
menu.close(BoxPointer.PopupAnimation.FULL);
|
||||
}
|
||||
});
|
||||
|
@ -29,93 +29,96 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
|
||||
</method>
|
||||
</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 SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
|
||||
|
||||
function loadRemoteSearchProviders(addProviderCallback) {
|
||||
let loadState = { loadedProviders: [],
|
||||
objectPaths: {},
|
||||
numLoading: 0,
|
||||
addProviderCallback: addProviderCallback };
|
||||
let data = { loadedProviders: [],
|
||||
objectPaths: {},
|
||||
addProviderCallback: addProviderCallback };
|
||||
FileUtils.collectFromDatadirsAsync('search-providers',
|
||||
{ loadedCallback: remoteProvidersLoaded,
|
||||
processFile: loadRemoteSearchProvider,
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
let dataDirs = GLib.get_system_data_dirs();
|
||||
for (let i = 0; i < dataDirs.length; i++) {
|
||||
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
|
||||
let dir = Gio.file_new_for_path(path);
|
||||
function loadRemoteSearchProvider(file, info, data) {
|
||||
let keyfile = new GLib.KeyFile();
|
||||
let path = file.get_path();
|
||||
|
||||
dir.query_info_async('standard:type', Gio.FileQueryInfoFlags.NONE,
|
||||
GLib.PRIORITY_DEFAULT, null,
|
||||
function(object, res) {
|
||||
let exists = false;
|
||||
try {
|
||||
object.query_info_finish(res);
|
||||
exists = true;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
return;
|
||||
|
||||
loadState.numLoading++;
|
||||
loadRemoteSearchProvidersFromDir(dir, loadState);
|
||||
});
|
||||
try {
|
||||
keyfile.load_from_file(path, 0);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
function loadRemoteSearchProvidersFromDir(dir, loadState) {
|
||||
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()]);
|
||||
|
||||
try {
|
||||
keyfile.load_from_file(path, 0);
|
||||
} catch(e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!keyfile.has_group(KEY_FILE_GROUP))
|
||||
continue;
|
||||
|
||||
let remoteProvider;
|
||||
try {
|
||||
let group = KEY_FILE_GROUP;
|
||||
let busName = keyfile.get_string(group, 'BusName');
|
||||
let objectPath = keyfile.get_string(group, 'ObjectPath');
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
remoteProvidersDirLoaded(loadState);
|
||||
}));
|
||||
|
||||
};
|
||||
|
||||
function remoteProvidersDirLoaded(loadState) {
|
||||
loadState.numLoading--;
|
||||
if (loadState.numLoading > 0)
|
||||
if (!keyfile.has_group(KEY_FILE_GROUP))
|
||||
return;
|
||||
|
||||
let remoteProvider;
|
||||
try {
|
||||
let group = KEY_FILE_GROUP;
|
||||
let busName = keyfile.get_string(group, 'BusName');
|
||||
let objectPath = keyfile.get_string(group, 'ObjectPath');
|
||||
|
||||
if (data.objectPaths[objectPath])
|
||||
return;
|
||||
|
||||
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');
|
||||
return;
|
||||
}
|
||||
|
||||
let version = '1';
|
||||
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;
|
||||
data.loadedProviders.push(remoteProvider);
|
||||
} catch(e) {
|
||||
log('Failed to add search provider %s: %s'.format(path, e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
function remoteProvidersLoaded(loadState) {
|
||||
let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
|
||||
let sortOrder = searchSettings.get_strv('sort-order');
|
||||
let numSorted = sortOrder.length;
|
||||
@ -164,13 +167,18 @@ function remoteProvidersDirLoaded(loadState) {
|
||||
|
||||
const RemoteSearchProvider = new Lang.Class({
|
||||
Name: 'RemoteSearchProvider',
|
||||
Extends: Search.SearchProvider,
|
||||
|
||||
_init: function(appInfo, dbusName, dbusPath) {
|
||||
this._proxy = new SearchProviderProxy(Gio.DBus.session,
|
||||
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
|
||||
_init: function(appInfo, dbusName, dbusPath, proxyType) {
|
||||
if (!proxyType)
|
||||
proxyType = SearchProviderProxy;
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
@ -190,9 +198,7 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
width, height, rowStride, size);
|
||||
}
|
||||
|
||||
// Ugh, but we want to fall back to something ...
|
||||
return new St.Icon({ icon_name: 'text-x-generic',
|
||||
icon_size: size });
|
||||
return null;
|
||||
},
|
||||
|
||||
_getResultsFinished: function(results, error) {
|
||||
@ -205,9 +211,9 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this._proxy.GetInitialResultSetRemote(terms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
this.proxy.GetInitialResultSetRemote(terms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
|
||||
this.searchSystem.pushResults(this, []);
|
||||
@ -218,9 +224,9 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this._proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
|
||||
this.searchSystem.pushResults(this, []);
|
||||
@ -249,9 +255,9 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this._proxy.GetResultMetasRemote(ids,
|
||||
Lang.bind(this, this._getResultMetasFinished, callback),
|
||||
this._cancellable);
|
||||
this.proxy.GetResultMetasRemote(ids,
|
||||
Lang.bind(this, this._getResultMetasFinished, callback),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
|
||||
callback([]);
|
||||
@ -259,8 +265,32 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
},
|
||||
|
||||
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());
|
||||
}
|
||||
});
|
||||
|
@ -308,6 +308,7 @@ const NotificationsBox = new Lang.Class({
|
||||
obj.item.disconnect(obj.contentUpdatedId);
|
||||
obj.source.disconnect(obj.sourceDestroyId);
|
||||
obj.source.disconnect(obj.sourceCountChangedId);
|
||||
obj.source.disconnect(obj.sourceTitleChangedId);
|
||||
},
|
||||
});
|
||||
|
||||
@ -502,7 +503,7 @@ const ScreenShield = new Lang.Class({
|
||||
if (symbol == Clutter.KEY_Escape ||
|
||||
symbol == Clutter.KEY_Return ||
|
||||
symbol == Clutter.KEY_KP_Enter) {
|
||||
this._ensureUnlockDialog(true);
|
||||
this._ensureUnlockDialog(true, true);
|
||||
this._hideLockScreen(true, 0);
|
||||
return true;
|
||||
}
|
||||
@ -525,7 +526,7 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
// 7 standard scrolls to lift up
|
||||
if (this._lockScreenScrollCounter > 35) {
|
||||
this._ensureUnlockDialog(false);
|
||||
this._ensureUnlockDialog(false, true);
|
||||
this._hideLockScreen(true, 0);
|
||||
}
|
||||
|
||||
@ -557,7 +558,7 @@ const ScreenShield = new Lang.Class({
|
||||
_onDragBegin: function() {
|
||||
Tweener.removeTweens(this._lockScreenGroup);
|
||||
this._lockScreenState = MessageTray.State.HIDING;
|
||||
this._ensureUnlockDialog(false);
|
||||
this._ensureUnlockDialog(false, false);
|
||||
|
||||
return true;
|
||||
},
|
||||
@ -579,6 +580,7 @@ const ScreenShield = new Lang.Class({
|
||||
// Complete motion automatically
|
||||
let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
|
||||
this._hideLockScreen(true, -velocityY);
|
||||
this._ensureUnlockDialog(false, true);
|
||||
} else {
|
||||
// restore the lock screen to its original place
|
||||
// try to use the same speed as the normal animation
|
||||
@ -661,7 +663,7 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
this.actor.show();
|
||||
this._isGreeter = Main.sessionMode.isGreeter;
|
||||
this._ensureUnlockDialog(true);
|
||||
this._ensureUnlockDialog(true, true);
|
||||
this._hideLockScreen(false, 0);
|
||||
},
|
||||
|
||||
@ -717,7 +719,7 @@ const ScreenShield = new Lang.Class({
|
||||
Main.sessionMode.popMode('lock-screen');
|
||||
},
|
||||
|
||||
_ensureUnlockDialog: function(onPrimary) {
|
||||
_ensureUnlockDialog: function(onPrimary, allowCancel) {
|
||||
if (!this._dialog) {
|
||||
let constructor = Main.sessionMode.unlockDialog;
|
||||
if (!constructor) {
|
||||
@ -740,6 +742,8 @@ const ScreenShield = new Lang.Class({
|
||||
this._dialog.connect('failed', Lang.bind(this, this._onUnlockFailed));
|
||||
this._dialog.connect('unlocked', Lang.bind(this, this._onUnlockSucceded));
|
||||
}
|
||||
|
||||
this._dialog.allowCancel = allowCancel;
|
||||
},
|
||||
|
||||
_onUnlockFailed: function() {
|
||||
|
170
js/ui/search.js
170
js/ui/search.js
@ -1,176 +1,10 @@
|
||||
// -*- 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 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';
|
||||
|
||||
// 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({
|
||||
Name: 'SearchSystem',
|
||||
|
||||
@ -262,7 +96,7 @@ const SearchSystem = new Lang.Class({
|
||||
results.push([provider, []]);
|
||||
provider.getSubsearchResultSet(previousResults, terms);
|
||||
} catch (error) {
|
||||
log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
|
||||
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -272,7 +106,7 @@ const SearchSystem = new Lang.Class({
|
||||
results.push([provider, []]);
|
||||
provider.getInitialResultSet(terms);
|
||||
} catch (error) {
|
||||
log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
|
||||
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,11 @@ const DND = imports.ui.dnd;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const Separator = imports.ui.separator;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
const MAX_SEARCH_RESULTS_ROWS = 1;
|
||||
|
||||
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
|
||||
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
|
||||
|
||||
const SearchResult = new Lang.Class({
|
||||
Name: 'SearchResult',
|
||||
@ -22,33 +23,103 @@ const SearchResult = new Lang.Class({
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.provider = provider;
|
||||
this.metaInfo = metaInfo;
|
||||
this.actor = new St.Button({ style_class: 'search-result',
|
||||
reactive: true,
|
||||
this.terms = terms;
|
||||
|
||||
this.actor = new St.Button({ reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: true });
|
||||
|
||||
this.actor._delegate = this;
|
||||
this._dragActorSource = null;
|
||||
this.actor.connect('clicked', Lang.bind(this, this.activate));
|
||||
},
|
||||
|
||||
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 dragSource = null;
|
||||
|
||||
if (content == null) {
|
||||
content = new St.Bin({ style_class: 'search-result-content',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
accessible_role: Atk.Role.PUSH_BUTTON });
|
||||
content = new St.Bin();
|
||||
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
|
||||
{ createIcon: this.metaInfo['createIcon'] });
|
||||
content.set_child(icon.actor);
|
||||
this._dragActorSource = icon.icon;
|
||||
content.label_actor = icon.label;
|
||||
dragSource = icon.icon;
|
||||
} else {
|
||||
if (content._delegate && content._delegate.getDragActorSource)
|
||||
this._dragActorSource = content._delegate.getDragActorSource();
|
||||
dragSource = content._delegate.getDragActorSource();
|
||||
}
|
||||
this._content = content;
|
||||
this.actor.set_child(content);
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
|
||||
this.actor.set_child(content);
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
draggable.connect('drag-begin',
|
||||
@ -63,32 +134,18 @@ const SearchResult = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endItemDrag(this);
|
||||
}));
|
||||
},
|
||||
|
||||
setSelected: function(selected) {
|
||||
if (selected)
|
||||
this._content.add_style_pseudo_class('selected');
|
||||
else
|
||||
this._content.remove_style_pseudo_class('selected');
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.provider.activateResult(this.metaInfo.id);
|
||||
Main.overview.toggle();
|
||||
},
|
||||
|
||||
_onResultClicked: function(actor) {
|
||||
this.activate();
|
||||
if (!dragSource)
|
||||
// not exactly right, but alignment problems are hard to notice
|
||||
dragSource = content;
|
||||
this._dragActorSource = dragSource;
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
if (this._dragActorSource)
|
||||
return this._dragActorSource;
|
||||
// not exactly right, but alignment problems are hard to notice
|
||||
return this._content;
|
||||
return this._dragActorSource;
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
getDragActor: function() {
|
||||
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
|
||||
},
|
||||
|
||||
@ -96,51 +153,52 @@ const SearchResult = new Lang.Class({
|
||||
if (this.provider.dragActivateResult)
|
||||
this.provider.dragActivateResult(this.metaInfo.id, params);
|
||||
else
|
||||
this.provider.activateResult(this.metaInfo.id, params);
|
||||
this.provider.activateResult(this.metaInfo.id, this.terms);
|
||||
}
|
||||
});
|
||||
|
||||
const ListSearchResults = new Lang.Class({
|
||||
Name: 'ListSearchResults',
|
||||
|
||||
const GridSearchResults = new Lang.Class({
|
||||
Name: 'GridSearchResults',
|
||||
Extends: Search.SearchResultDisplay,
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
|
||||
_init: function(provider, grid) {
|
||||
this.parent(provider);
|
||||
|
||||
this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
this.actor = new St.Bin({ x_align: St.Align.START });
|
||||
|
||||
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.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._grid.visibleItemsCount();
|
||||
let canDisplay = this._grid.childrenInRow(this._width) * this._grid.getRowLimit()
|
||||
- alreadyVisible;
|
||||
let alreadyVisible = this._pendingClear ? 0 : this.getVisibleResultCount();
|
||||
let canDisplay = MAX_LIST_SEARCH_RESULTS_ROWS - alreadyVisible;
|
||||
|
||||
let numResults = Math.min(this._notDisplayedResult.length, canDisplay);
|
||||
|
||||
return this._notDisplayedResult.splice(0, numResults);
|
||||
let newResults = this._notDisplayedResult.splice(0, canDisplay);
|
||||
return newResults;
|
||||
},
|
||||
|
||||
getVisibleResultCount: function() {
|
||||
return this._grid.visibleItemsCount();
|
||||
return this._content.get_n_children();
|
||||
},
|
||||
|
||||
hasMoreResults: function() {
|
||||
return this._notDisplayedResult.length > 0;
|
||||
},
|
||||
|
||||
setResults: function(results, terms) {
|
||||
@ -152,7 +210,68 @@ const GridSearchResults = new Lang.Class({
|
||||
|
||||
renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new SearchResult(this.provider, metas[i], this._terms);
|
||||
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({
|
||||
Name: 'GridSearchResults',
|
||||
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
|
||||
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
this.actor = new St.Bin({ x_align: St.Align.MIDDLE });
|
||||
|
||||
this.actor.set_child(this._grid.actor);
|
||||
|
||||
this._notDisplayedResult = [];
|
||||
this._terms = [];
|
||||
this._pendingClear = false;
|
||||
},
|
||||
|
||||
getResultsForDisplay: function() {
|
||||
let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount();
|
||||
let canDisplay = this._grid.childrenInRow(this.actor.width) * this._grid.getRowLimit()
|
||||
- alreadyVisible;
|
||||
|
||||
let newResults = this._notDisplayedResult.splice(0, canDisplay);
|
||||
return newResults;
|
||||
},
|
||||
|
||||
getVisibleResultCount: function() {
|
||||
return this._grid.visibleItemsCount();
|
||||
},
|
||||
|
||||
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 GridSearchResult(this.provider, metas[i], this._terms);
|
||||
this._grid.addItem(display.actor);
|
||||
}
|
||||
},
|
||||
@ -183,26 +302,20 @@ const SearchResults = new Lang.Class({
|
||||
this._content = new St.BoxLayout({ name: 'searchResultsContent',
|
||||
vertical: true });
|
||||
|
||||
let scrollView = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
style_class: 'vfade' });
|
||||
scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
scrollView.add_actor(this._content);
|
||||
this._scrollView = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
style_class: 'vfade' });
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.add_actor(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(scrollView, { x_fill: true,
|
||||
y_fill: true,
|
||||
expand: true,
|
||||
x_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.actor.add(this._scrollView, { x_fill: true,
|
||||
y_fill: true,
|
||||
expand: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||
@ -219,22 +332,37 @@ const SearchResults = new Lang.Class({
|
||||
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) {
|
||||
let providerBox = new St.BoxLayout({ style_class: 'search-section',
|
||||
vertical: true });
|
||||
let title = new St.Label({ style_class: 'search-section-header',
|
||||
text: provider.title });
|
||||
providerBox.add(title, { x_fill: false, x_align: St.Align.START });
|
||||
let providerIcon = null;
|
||||
let resultDisplay = null;
|
||||
|
||||
let resultDisplayBin = new St.Bin({ style_class: 'search-section-results',
|
||||
if (provider.appInfo) {
|
||||
resultDisplay = new ListSearchResults(provider);
|
||||
providerIcon = resultDisplay.providerIcon;
|
||||
} else {
|
||||
resultDisplay = new GridSearchResults(provider);
|
||||
}
|
||||
|
||||
let resultDisplayBin = new St.Bin({ child: resultDisplay.actor,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
providerBox.add(resultDisplayBin, { expand: true });
|
||||
let resultDisplay = new GridSearchResults(provider);
|
||||
resultDisplayBin.set_child(resultDisplay.actor);
|
||||
|
||||
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
|
||||
providerBox.add(separator.actor);
|
||||
|
||||
this._providerMeta.push({ provider: provider,
|
||||
actor: providerBox,
|
||||
icon: providerIcon,
|
||||
resultDisplay: resultDisplay });
|
||||
this._content.add(providerBox);
|
||||
},
|
||||
@ -341,6 +469,11 @@ const SearchResults = new Lang.Class({
|
||||
meta.resultDisplay.setResults(providerResults, terms);
|
||||
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) {
|
||||
this._clearDisplayForProvider(provider);
|
||||
meta.actor.show();
|
||||
@ -386,10 +519,37 @@ const SearchResults = new Lang.Class({
|
||||
|
||||
let from = this._defaultResult ? this._defaultResult.actor : null;
|
||||
this.actor.navigate_focus(from, direction, false);
|
||||
if (this._defaultResult) {
|
||||
// The default result appears focused, so navigate directly to the
|
||||
// next result.
|
||||
this.actor.navigate_focus(global.stage.key_focus, direction, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ProviderIcon = new Lang.Class({
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
34
js/ui/separator.js
Normal file
34
js/ui/separator.js
Normal file
@ -0,0 +1,34 @@
|
||||
// -*- 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();
|
||||
}
|
||||
});
|
@ -1,8 +1,12 @@
|
||||
// -*- 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 Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const FileUtils = imports.misc.fileUtils;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
@ -10,10 +14,12 @@ const DEFAULT_MODE = 'restrictive';
|
||||
|
||||
const _modes = {
|
||||
'restrictive': {
|
||||
parentMode: null,
|
||||
hasOverview: false,
|
||||
showCalendarEvents: false,
|
||||
allowSettings: false,
|
||||
allowExtensions: false,
|
||||
enabledExtensions: [],
|
||||
hasRunDialog: false,
|
||||
hasWorkspaces: false,
|
||||
hasWindows: false,
|
||||
@ -28,6 +34,7 @@ const _modes = {
|
||||
center: [],
|
||||
right: []
|
||||
},
|
||||
panelStyle: null
|
||||
},
|
||||
|
||||
'gdm': {
|
||||
@ -41,7 +48,8 @@ const _modes = {
|
||||
center: ['dateMenu'],
|
||||
right: ['a11y', 'display', 'keyboard',
|
||||
'volume', 'battery', 'powerMenu']
|
||||
}
|
||||
},
|
||||
panelStyle: 'login-screen'
|
||||
},
|
||||
|
||||
'lock-screen': {
|
||||
@ -54,6 +62,7 @@ const _modes = {
|
||||
center: [],
|
||||
right: ['lockScreen']
|
||||
},
|
||||
panelStyle: 'lock-screen'
|
||||
},
|
||||
|
||||
'unlock-dialog': {
|
||||
@ -65,6 +74,7 @@ const _modes = {
|
||||
center: [],
|
||||
right: ['a11y', 'keyboard', 'lockScreen']
|
||||
},
|
||||
panelStyle: 'unlock-screen'
|
||||
},
|
||||
|
||||
'initial-setup': {
|
||||
@ -100,11 +110,48 @@ const _modes = {
|
||||
}
|
||||
};
|
||||
|
||||
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() {
|
||||
let modes = Object.getOwnPropertyNames(_modes);
|
||||
for (let i = 0; i < modes.length; i++)
|
||||
if (_modes[modes[i]].isPrimary)
|
||||
print(modes[i]);
|
||||
_getModes(function(modes) {
|
||||
let names = Object.getOwnPropertyNames(modes);
|
||||
for (let i = 0; i < names.length; i++)
|
||||
if (_modes[names[i]].isPrimary)
|
||||
print(names[i]);
|
||||
Mainloop.quit('listModes');
|
||||
});
|
||||
Mainloop.run('listModes');
|
||||
}
|
||||
|
||||
const SessionMode = new Lang.Class({
|
||||
@ -112,10 +159,18 @@ const SessionMode = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
global.connect('notify::session-mode', Lang.bind(this, this._sync));
|
||||
let mode = _modes[global.session_mode].isPrimary ? global.session_mode
|
||||
: 'user';
|
||||
this._modeStack = [mode];
|
||||
this._modes = _modes;
|
||||
this._modeStack = [DEFAULT_MODE];
|
||||
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) {
|
||||
@ -142,8 +197,14 @@ const SessionMode = new Lang.Class({
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let params = _modes[this.currentMode];
|
||||
params = Params.parse(params, _modes[DEFAULT_MODE]);
|
||||
let params = this._modes[this.currentMode];
|
||||
let defaults;
|
||||
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
|
||||
// undefined as a special case for "no change / inherit from previous mode"
|
||||
|
@ -46,6 +46,7 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
</method>
|
||||
<property name="Mode" type="s" access="read" />
|
||||
<property name="OverviewActive" type="b" access="readwrite" />
|
||||
<property name="ShellVersion" type="s" access="read" />
|
||||
</interface>;
|
||||
@ -111,7 +112,7 @@ const GnomeShell = new Lang.Class({
|
||||
},
|
||||
|
||||
_onScreenshotComplete: function(obj, result, area, flash, invocation) {
|
||||
if (flash) {
|
||||
if (flash && result) {
|
||||
let flashspot = new Flashspot.Flashspot(area);
|
||||
flashspot.fire();
|
||||
}
|
||||
@ -186,6 +187,8 @@ const GnomeShell = new Lang.Class({
|
||||
flashspot.fire();
|
||||
},
|
||||
|
||||
Mode: global.session_mode,
|
||||
|
||||
get OverviewActive() {
|
||||
return Main.overview.visible;
|
||||
},
|
||||
|
@ -19,6 +19,8 @@ const ShellEntry = imports.ui.shellEntry;
|
||||
|
||||
const LIST_ITEM_ICON_SIZE = 48;
|
||||
|
||||
const REMEMBER_MOUNT_PASSWORD_KEY = 'remember-mount-password';
|
||||
|
||||
/* ------ Common Utils ------- */
|
||||
function _setLabelText(label, text) {
|
||||
if (text) {
|
||||
@ -387,7 +389,8 @@ const ShellMountPasswordDialog = new Lang.Class({
|
||||
if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
|
||||
this._rememberChoice = new CheckBox.CheckBox();
|
||||
this._rememberChoice.getLabelActor().text = _("Remember Password");
|
||||
this._rememberChoice.actor.checked = true;
|
||||
this._rememberChoice.actor.checked =
|
||||
global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY);
|
||||
this._messageBox.add(this._rememberChoice.actor);
|
||||
} else {
|
||||
this._rememberChoice = null;
|
||||
@ -419,6 +422,8 @@ const ShellMountPasswordDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_onEntryActivate: function() {
|
||||
global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY,
|
||||
this._rememberChoice && this._rememberChoice.actor.checked);
|
||||
this.emit('response', 1,
|
||||
this._passwordEntry.get_text(),
|
||||
this._rememberChoice &&
|
||||
|
@ -574,7 +574,11 @@ const NMDevice = new Lang.Class({
|
||||
this.emit('network-lost');
|
||||
}
|
||||
|
||||
if (newstate == NetworkManager.DeviceState.FAILED) {
|
||||
/* Emit a notification if activation fails, but don't do it
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1540,7 +1544,8 @@ const NMVPNSection = new Lang.Class({
|
||||
},
|
||||
|
||||
_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,
|
||||
// we need to convert from NetworkManager.VPNConnectionStateReason
|
||||
// to NetworkManager.DeviceStateReason
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gvc = imports.gi.Gvc;
|
||||
const St = imports.gi.St;
|
||||
|
||||
@ -32,6 +33,8 @@ const VolumeMenu = new Lang.Class({
|
||||
_init: function(control) {
|
||||
this.parent();
|
||||
|
||||
this.hasHeadphones = false;
|
||||
|
||||
this._control = control;
|
||||
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
|
||||
this._control.connect('default-sink-changed', Lang.bind(this, this._readOutput));
|
||||
@ -98,20 +101,47 @@ 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() {
|
||||
if (this._outputVolumeId) {
|
||||
this._output.disconnect(this._outputVolumeId);
|
||||
this._output.disconnect(this._outputMutedId);
|
||||
this._output.disconnect(this._outputPortId);
|
||||
this._outputVolumeId = 0;
|
||||
this._outputMutedId = 0;
|
||||
this._outputPortId = 0;
|
||||
}
|
||||
this._output = this._control.get_default_sink();
|
||||
if (this._output) {
|
||||
this._outputMutedId = this._output.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_output'));
|
||||
this._outputVolumeId = this._output.connect('notify::volume', Lang.bind(this, this._volumeChanged, '_output'));
|
||||
this._mutedChanged (null, null, '_output');
|
||||
this._volumeChanged (null, null, '_output');
|
||||
this._outputPortId = this._output.connect('notify::port', Lang.bind(this, this._portChanged));
|
||||
|
||||
this._mutedChanged(null, null, '_output');
|
||||
this._volumeChanged(null, null, '_output');
|
||||
this._portChanged();
|
||||
} else {
|
||||
this.hasHeadphones = false;
|
||||
this._outputSlider.setValue(0);
|
||||
this.emit('icon-changed', 'audio-volume-muted-symbolic');
|
||||
}
|
||||
@ -227,6 +257,12 @@ const Indicator = new Lang.Class({
|
||||
this.setIcon(icon);
|
||||
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);
|
||||
|
||||
@ -239,6 +275,7 @@ const Indicator = new Lang.Class({
|
||||
_syncVisibility: function() {
|
||||
this.actor.visible = this._hasPulseAudio;
|
||||
this.mainIcon.visible = this._hasPulseAudio;
|
||||
this._headphoneIcon.visible = this._hasPulseAudio && this._volumeMenu.hasHeadphones;
|
||||
},
|
||||
|
||||
_onScrollEvent: function(actor, event) {
|
||||
|
641
js/ui/switcherPopup.js
Normal file
641
js/ui/switcherPopup.js
Normal file
@ -0,0 +1,641 @@
|
||||
// -*- 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();
|
||||
}
|
||||
|
@ -14,12 +14,14 @@ const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const Panel = imports.ui.panel;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const UserMenu = imports.ui.userMenu;
|
||||
|
||||
const Batch = imports.gdm.batch;
|
||||
const GdmUtil = imports.gdm.util;
|
||||
const LoginDialog = imports.gdm.loginDialog;
|
||||
|
||||
// The timeout before going back automatically to the lock screen (in seconds)
|
||||
const IDLE_TIMEOUT = 2 * 60;
|
||||
@ -151,7 +153,6 @@ const UnlockDialog = new Lang.Class({
|
||||
this._promptEntry.clutter_text.set_password_char('\u25cf');
|
||||
ShellEntry.addContextMenu(this._promptEntry, { isPassword: true });
|
||||
this.setInitialKeyFocus(this._promptEntry);
|
||||
this._promptEntry.clutter_text.connect('activate', Lang.bind(this, this._doUnlock));
|
||||
this._promptEntry.clutter_text.connect('text-changed', Lang.bind(this, function() {
|
||||
this._updateOkButtonSensitivity(this._promptEntry.text.length > 0);
|
||||
}));
|
||||
@ -169,15 +170,33 @@ const UnlockDialog = new Lang.Class({
|
||||
this._promptLoginHint.hide();
|
||||
this.contentLayout.add_actor(this._promptLoginHint);
|
||||
|
||||
let cancelButton = { label: _("Cancel"),
|
||||
action: Lang.bind(this, this._escape),
|
||||
key: Clutter.KEY_Escape };
|
||||
this._okButton = { label: _("Unlock"),
|
||||
action: Lang.bind(this, this._doUnlock),
|
||||
default: true };
|
||||
this.setButtons([cancelButton, this._okButton]);
|
||||
this._workSpinner = new Panel.AnimatedIcon('process-working.svg', LoginDialog.WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
|
||||
this._updateSensitivity(true);
|
||||
this.allowCancel = false;
|
||||
this.buttonLayout.visible = true;
|
||||
this.addButton({ label: _("Cancel"),
|
||||
action: Lang.bind(this, this._escape),
|
||||
key: Clutter.KEY_Escape },
|
||||
{ expand: true,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this.buttonLayout.add(this._workSpinner.actor,
|
||||
{ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._okButton = this.addButton({ label: _("Unlock"),
|
||||
action: Lang.bind(this, this._doUnlock),
|
||||
default: true },
|
||||
{ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
|
||||
style_class: 'login-dialog-not-listed-label' });
|
||||
@ -192,6 +211,8 @@ const UnlockDialog = new Lang.Class({
|
||||
{ x_align: St.Align.START,
|
||||
x_fill: false });
|
||||
|
||||
this._updateSensitivity(true);
|
||||
|
||||
let batch = new Batch.Hold();
|
||||
this._userVerifier.begin(this._userName, batch);
|
||||
|
||||
@ -210,11 +231,35 @@ const UnlockDialog = new Lang.Class({
|
||||
this._promptEntry.reactive = sensitive;
|
||||
this._promptEntry.clutter_text.editable = sensitive;
|
||||
this._updateOkButtonSensitivity(sensitive && this._promptEntry.text.length > 0);
|
||||
this._otherUserButton.reactive = sensitive;
|
||||
this._otherUserButton.can_focus = sensitive;
|
||||
},
|
||||
|
||||
_updateOkButtonSensitivity: function(sensitive) {
|
||||
this._okButton.button.reactive = sensitive;
|
||||
this._okButton.button.can_focus = sensitive;
|
||||
this._okButton.reactive = sensitive;
|
||||
this._okButton.can_focus = sensitive;
|
||||
},
|
||||
|
||||
_setWorking: function(working) {
|
||||
if (working) {
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: LoginDialog.WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_showMessage: function(userVerifier, message, styleClass) {
|
||||
@ -247,6 +292,7 @@ const UnlockDialog = new Lang.Class({
|
||||
|
||||
this._currentQuery = serviceName;
|
||||
this._updateSensitivity(true);
|
||||
this._setWorking(false);
|
||||
},
|
||||
|
||||
_showLoginHint: function(verifier, message) {
|
||||
@ -265,6 +311,7 @@ const UnlockDialog = new Lang.Class({
|
||||
// the actual reply to GDM will be sent as soon as asked
|
||||
this._firstQuestionAnswer = this._promptEntry.text;
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -275,6 +322,7 @@ const UnlockDialog = new Lang.Class({
|
||||
this._currentQuery = null;
|
||||
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(true);
|
||||
|
||||
this._userVerifier.answerQuery(query, this._promptEntry.text);
|
||||
},
|
||||
@ -297,11 +345,14 @@ const UnlockDialog = new Lang.Class({
|
||||
this._promptEntry.menu.isPassword = true;
|
||||
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(false);
|
||||
},
|
||||
|
||||
_escape: function() {
|
||||
this._userVerifier.cancel();
|
||||
this.emit('failed');
|
||||
if (this.allowCancel) {
|
||||
this._userVerifier.cancel();
|
||||
this.emit('failed');
|
||||
}
|
||||
},
|
||||
|
||||
_otherUserClicked: function(button, event) {
|
||||
|
@ -27,6 +27,7 @@ const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
|
||||
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
|
||||
const LOCK_ENABLED_KEY = 'lock-enabled';
|
||||
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
|
||||
const SHOW_FULL_NAME_KEY = 'show-full-name';
|
||||
|
||||
const DIALOG_ICON_SIZE = 64;
|
||||
|
||||
@ -550,9 +551,12 @@ const UserMenuButton = new Lang.Class({
|
||||
Lang.bind(this, this._updateSwitchUser));
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
|
||||
Lang.bind(this, this._updateLogout));
|
||||
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
|
||||
Lang.bind(this, this._updateLockScreen));
|
||||
this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_KEY,
|
||||
Lang.bind(this, this._updateUserName));
|
||||
global.settings.connect('changed::' + SHOW_FULL_NAME_KEY,
|
||||
Lang.bind(this, this._updateUserName));
|
||||
this._updateSwitchUser();
|
||||
this._updateLogout();
|
||||
this._updateLockScreen();
|
||||
@ -597,7 +601,10 @@ const UserMenuButton = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateUserName: function() {
|
||||
if (this._user.is_loaded)
|
||||
let settings = global.settings;
|
||||
if (Main.sessionMode.isLocked)
|
||||
settings = this._screenSaverSettings;
|
||||
if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_KEY))
|
||||
this._name.set_text(this._user.get_real_name());
|
||||
else
|
||||
this._name.set_text("");
|
||||
|
@ -52,8 +52,7 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
this._activePage = null;
|
||||
|
||||
this.active = false;
|
||||
this._searchPending = false;
|
||||
this._searchActive = false;
|
||||
this._searchTimeoutId = 0;
|
||||
|
||||
this._searchSystem = new Search.SearchSystem();
|
||||
@ -84,11 +83,11 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
|
||||
this._workspacesPage = this._addPage(this._workspacesDisplay.actor, null,
|
||||
_("Windows"), 'text-x-generic-symbolic');
|
||||
_("Windows"), 'emblem-documents-symbolic');
|
||||
|
||||
this._appDisplay = new AppDisplay.AllAppDisplay();
|
||||
this._appsPage = this._addPage(this._appDisplay.actor, null,
|
||||
_("Applications"), 'system-run-symbolic');
|
||||
_("Applications"), 'view-grid-symbolic');
|
||||
|
||||
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
|
||||
@ -119,9 +118,6 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
global.focus_manager.add_group(this._searchResults.actor);
|
||||
|
||||
Main.overview.connect('item-drag-begin',
|
||||
Lang.bind(this, this._resetShowAppsButton));
|
||||
|
||||
this._stageKeyPressId = 0;
|
||||
Main.overview.connect('showing', Lang.bind(this,
|
||||
function () {
|
||||
@ -138,17 +134,6 @@ 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',
|
||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
@ -223,11 +208,16 @@ const ViewSelector = new Lang.Class({
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('before-page-change');
|
||||
page.show();
|
||||
Tweener.addTween(page,
|
||||
{ opacity: 255,
|
||||
time: 0.1,
|
||||
transition: 'easeOutQuad'
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this.emit('after-page-change');
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
@ -237,7 +227,7 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_onShowAppsButtonToggled: function() {
|
||||
if (this.active)
|
||||
if (this._searchActive)
|
||||
this.reset();
|
||||
else
|
||||
this._showPage(this._showAppsButton.checked ? this._appsPage
|
||||
@ -249,11 +239,16 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_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 symbol = event.get_key_symbol();
|
||||
|
||||
if (symbol == Clutter.Escape) {
|
||||
if (this.active)
|
||||
if (this._searchActive)
|
||||
this.reset();
|
||||
else if (this._showAppsButton.checked)
|
||||
this._resetShowAppsButton();
|
||||
@ -261,9 +256,9 @@ const ViewSelector = new Lang.Class({
|
||||
Main.overview.hide();
|
||||
return true;
|
||||
} else if (Clutter.keysym_to_unicode(symbol) ||
|
||||
(symbol == Clutter.BackSpace && this.active)) {
|
||||
(symbol == Clutter.BackSpace && this._searchActive)) {
|
||||
this.startSearch(event);
|
||||
} else if (!this.active) {
|
||||
} else if (!this._searchActive) {
|
||||
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
return true;
|
||||
@ -337,13 +332,15 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_onTextChanged: function (se, prop) {
|
||||
let searchPreviouslyActive = this.active;
|
||||
this.active = this._entry.get_text() != '';
|
||||
this._searchPending = this.active && !searchPreviouslyActive;
|
||||
if (this._searchPending) {
|
||||
let searchPreviouslyActive = this._searchActive;
|
||||
this._searchActive = this._entry.get_text() != '';
|
||||
|
||||
let startSearch = this._searchActive && !searchPreviouslyActive;
|
||||
if (startSearch) {
|
||||
this._searchResults.startingSearch();
|
||||
}
|
||||
if (this.active) {
|
||||
|
||||
if (this._searchActive) {
|
||||
this._entry.set_secondary_icon(this._activeIcon);
|
||||
|
||||
if (this._iconClickedId == 0) {
|
||||
@ -359,14 +356,14 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
this._entry.set_secondary_icon(this._inactiveIcon);
|
||||
this._searchCancelled();
|
||||
}
|
||||
if (!this.active) {
|
||||
|
||||
if (this._searchTimeoutId > 0) {
|
||||
Mainloop.source_remove(this._searchTimeoutId);
|
||||
this._searchTimeoutId = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._searchTimeoutId > 0)
|
||||
return;
|
||||
this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, this._doSearch));
|
||||
@ -388,7 +385,7 @@ const ViewSelector = new Lang.Class({
|
||||
}
|
||||
this._searchResults.activateDefault();
|
||||
return true;
|
||||
} else if (this.active) {
|
||||
} else if (this._searchActive) {
|
||||
let arrowNext, nextDirection;
|
||||
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
arrowNext = Clutter.Left;
|
||||
@ -462,6 +459,10 @@ const ViewSelector = new Lang.Class({
|
||||
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
|
||||
},
|
||||
|
||||
getAppsActive: function() {
|
||||
return this._showAppsButton.checked;
|
||||
},
|
||||
|
||||
addSearchProvider: function(provider) {
|
||||
if (!this._shouldUseSearchProvider(provider))
|
||||
return;
|
||||
@ -473,6 +474,10 @@ const ViewSelector = new Lang.Class({
|
||||
removeSearchProvider: function(provider) {
|
||||
this._searchSystem.unregisterProvider(provider);
|
||||
this._searchResults.destroyProviderMeta(provider);
|
||||
},
|
||||
|
||||
getSearchActive: function() {
|
||||
return this._searchActive;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ViewSelector.prototype);
|
||||
|
@ -9,7 +9,7 @@ const St = imports.gi.St;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Layout = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
const Search = imports.ui.search;
|
||||
const Panel = imports.ui.panel;
|
||||
|
||||
// we could make these gsettings
|
||||
const FISH_NAME = 'wanda';
|
||||
@ -53,20 +53,9 @@ const WandaIcon = new Lang.Class({
|
||||
icon_size: iconSize });
|
||||
}
|
||||
|
||||
this._animations = St.TextureCache.get_default().load_sliced_image(this._imageFile, this._imgWidth, this._imgHeight);
|
||||
this._animations.connect('notify::mapped', Lang.bind(this, function() {
|
||||
if (this._animations.mapped && !this._timeoutId) {
|
||||
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, FISH_SPEED, Lang.bind(this, this._update));
|
||||
|
||||
this._i = 0;
|
||||
this._update();
|
||||
} else if (!this._animations.mapped && this._timeoutId) {
|
||||
GLib.source_remove(this._timeoutId);
|
||||
this._timeoutId = 0;
|
||||
}
|
||||
}));
|
||||
|
||||
return this._animations;
|
||||
this._animations = new Panel.Animation(this._imageFile, this._imgWidth, this._imgHeight, FISH_SPEED);
|
||||
this._animations.play();
|
||||
return this._animations.actor;
|
||||
},
|
||||
|
||||
_createIconTexture: function(size) {
|
||||
@ -74,28 +63,14 @@ const WandaIcon = new Lang.Class({
|
||||
return;
|
||||
|
||||
this.parent(size);
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
let n = this._animations.get_n_children();
|
||||
if (n == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this._animations.get_child_at_index(this._i).hide();
|
||||
this._i = (this._i + 1) % n;
|
||||
this._animations.get_child_at_index(this._i).show();
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const WandaIconBin = new Lang.Class({
|
||||
Name: 'WandaIconBin',
|
||||
|
||||
_init: function(fish, label, params) {
|
||||
this.actor = new St.Bin({ style_class: 'search-result-content',
|
||||
reactive: true,
|
||||
this.actor = new St.Bin({ reactive: true,
|
||||
track_hover: true });
|
||||
this.icon = new WandaIcon(fish, label, params);
|
||||
|
||||
@ -156,10 +131,9 @@ function capitalize(str) {
|
||||
|
||||
const WandaSearchProvider = new Lang.Class({
|
||||
Name: 'WandaSearchProvider',
|
||||
Extends: Search.SearchProvider,
|
||||
|
||||
_init: function() {
|
||||
this.parent(_("Your favorite Easter Egg"));
|
||||
this.id = 'wanda';
|
||||
},
|
||||
|
||||
getResultMetas: function(fish, callback) {
|
||||
@ -185,7 +159,7 @@ const WandaSearchProvider = new Lang.Class({
|
||||
this.getInitialResultSet(terms);
|
||||
},
|
||||
|
||||
activateResult: function(fish, params) {
|
||||
activateResult: function(fish) {
|
||||
if (this._dialog)
|
||||
this._dialog.destroy();
|
||||
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
|
||||
|
@ -136,18 +136,24 @@ const WindowManager = new Lang.Class({
|
||||
Main.KeybindingMode.NORMAL |
|
||||
Main.KeybindingMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-windows',
|
||||
this.setCustomKeybindingHandler('switch-applications',
|
||||
Main.KeybindingMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-group',
|
||||
Main.KeybindingMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-windows-backward',
|
||||
this.setCustomKeybindingHandler('switch-applications-backward',
|
||||
Main.KeybindingMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-group-backward',
|
||||
Main.KeybindingMode.NORMAL,
|
||||
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',
|
||||
Main.KeybindingMode.NORMAL |
|
||||
Main.KeybindingMode.OVERVIEW |
|
||||
@ -155,6 +161,13 @@ const WindowManager = new Lang.Class({
|
||||
Main.KeybindingMode.UNLOCK_SCREEN |
|
||||
Main.KeybindingMode.LOGIN_SCREEN,
|
||||
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',
|
||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
@ -610,7 +623,20 @@ const WindowManager = new Lang.Class({
|
||||
if (this._workspaceSwitcherPopup != null)
|
||||
this._workspaceSwitcherPopup.destroy();
|
||||
|
||||
let tabPopup = new AltTab.AltTabPopup();
|
||||
let tabPopup = new AltTab.AppSwitcherPopup();
|
||||
|
||||
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 backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
||||
@ -621,7 +647,7 @@ const WindowManager = new Lang.Class({
|
||||
_startA11ySwitcher : function(display, screen, window, binding) {
|
||||
let modifiers = binding.get_modifiers();
|
||||
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
||||
Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
|
||||
Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask());
|
||||
},
|
||||
|
||||
_openAppMenu : function(display, screen, window, event, binding) {
|
||||
|
@ -445,6 +445,9 @@ const WindowOverlay = new Lang.Class({
|
||||
this._parentActor = parentActor;
|
||||
this._hidden = false;
|
||||
|
||||
this.borderSize = 0;
|
||||
this.border = new St.Bin({ style_class: 'window-clone-border' });
|
||||
|
||||
let title = new St.Label({ style_class: 'window-caption',
|
||||
text: metaWindow.title });
|
||||
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
@ -482,11 +485,13 @@ const WindowOverlay = new Lang.Class({
|
||||
this.closeButton = button;
|
||||
|
||||
parentActor.add_actor(this.title);
|
||||
parentActor.add_actor(this.border);
|
||||
parentActor.add_actor(this.closeButton);
|
||||
title.connect('style-changed',
|
||||
Lang.bind(this, this._onStyleChanged));
|
||||
button.connect('style-changed',
|
||||
Lang.bind(this, this._onStyleChanged));
|
||||
this.border.connect('style-changed', Lang.bind(this, this._onStyleChanged));
|
||||
// force a style change if we are already on a stage - otherwise
|
||||
// the signal will be emitted normally when we are added
|
||||
if (parentActor.get_stage())
|
||||
@ -495,15 +500,17 @@ const WindowOverlay = new Lang.Class({
|
||||
|
||||
hide: function() {
|
||||
this._hidden = true;
|
||||
this.closeButton.hide();
|
||||
this.title.hide();
|
||||
|
||||
this.hideCloseButton();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._hidden = false;
|
||||
if (this._windowClone.actor.has_pointer)
|
||||
this.closeButton.show();
|
||||
|
||||
this.title.show();
|
||||
if (this._windowClone.actor.has_pointer)
|
||||
this._animateVisible();
|
||||
},
|
||||
|
||||
fadeIn: function() {
|
||||
@ -520,10 +527,14 @@ const WindowOverlay = new Lang.Class({
|
||||
},
|
||||
|
||||
chromeHeights: function () {
|
||||
return [this.closeButton.height - this.closeButton._overlap,
|
||||
return [Math.max(this.borderSize, this.closeButton.height - this.closeButton._overlap),
|
||||
this.title.height + this.title._spacing];
|
||||
},
|
||||
|
||||
chromeWidths: function () {
|
||||
return [this.borderSize, this.borderSize];
|
||||
},
|
||||
|
||||
_repositionSelf: function() {
|
||||
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
|
||||
this.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight, false);
|
||||
@ -578,16 +589,32 @@ const WindowOverlay = new Lang.Class({
|
||||
title.width = titleWidth;
|
||||
title.set_position(Math.floor(titleX), Math.floor(titleY));
|
||||
}
|
||||
|
||||
let borderX = cloneX - this.borderSize;
|
||||
let borderY = cloneY - this.borderSize;
|
||||
let borderWidth = cloneWidth + 2 * this.borderSize;
|
||||
let borderHeight = cloneHeight + 2 * this.borderSize;
|
||||
|
||||
if (animate) {
|
||||
this._animateOverlayActor(this.border, borderX, borderY,
|
||||
borderWidth, borderHeight);
|
||||
} else {
|
||||
this.border.set_position(borderX, borderY);
|
||||
this.border.set_size(borderWidth, borderHeight);
|
||||
}
|
||||
},
|
||||
|
||||
_animateOverlayActor: function(actor, x, y, width) {
|
||||
Tweener.addTween(actor,
|
||||
{ x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
_animateOverlayActor: function(actor, x, y, width, height) {
|
||||
let params = { x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' };
|
||||
|
||||
if (height !== undefined)
|
||||
params.height = height;
|
||||
|
||||
Tweener.addTween(actor, params);
|
||||
},
|
||||
|
||||
_closeWindow: function(actor) {
|
||||
@ -630,6 +657,43 @@ const WindowOverlay = new Lang.Class({
|
||||
this._windowClone.metaWindow.disconnect(this._updateCaptionId);
|
||||
this.title.destroy();
|
||||
this.closeButton.destroy();
|
||||
this.border.destroy();
|
||||
},
|
||||
|
||||
_animateVisible: function() {
|
||||
this._parentActor.raise_top();
|
||||
|
||||
this.closeButton.show();
|
||||
this.closeButton.opacity = 0;
|
||||
Tweener.addTween(this.closeButton,
|
||||
{ opacity: 255,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
|
||||
this.border.show();
|
||||
this.border.opacity = 0;
|
||||
Tweener.addTween(this.border,
|
||||
{ opacity: 255,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
|
||||
this.title.add_style_pseudo_class('hover');
|
||||
},
|
||||
|
||||
_animateInvisible: function() {
|
||||
this.closeButton.opacity = 255;
|
||||
Tweener.addTween(this.closeButton,
|
||||
{ opacity: 0,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeInQuad' });
|
||||
|
||||
this.border.opacity = 255;
|
||||
Tweener.addTween(this.border,
|
||||
{ opacity: 0,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeInQuad' });
|
||||
|
||||
this.title.remove_style_pseudo_class('hover');
|
||||
},
|
||||
|
||||
_onEnter: function() {
|
||||
@ -639,8 +703,8 @@ const WindowOverlay = new Lang.Class({
|
||||
// are shown again
|
||||
if (this._hidden)
|
||||
return;
|
||||
this._parentActor.raise_top();
|
||||
this.closeButton.show();
|
||||
|
||||
this._animateVisible();
|
||||
this.emit('show-close-button');
|
||||
},
|
||||
|
||||
@ -651,9 +715,10 @@ const WindowOverlay = new Lang.Class({
|
||||
|
||||
_idleToggleCloseButton: function() {
|
||||
this._idleToggleCloseId = 0;
|
||||
|
||||
if (!this._windowClone.actor.has_pointer &&
|
||||
!this.closeButton.has_pointer)
|
||||
this.closeButton.hide();
|
||||
this._animateInvisible();
|
||||
|
||||
return false;
|
||||
},
|
||||
@ -664,6 +729,8 @@ const WindowOverlay = new Lang.Class({
|
||||
this._idleToggleCloseId = 0;
|
||||
}
|
||||
this.closeButton.hide();
|
||||
this.border.hide();
|
||||
this.title.remove_style_pseudo_class('hover');
|
||||
},
|
||||
|
||||
_onStyleChanged: function() {
|
||||
@ -673,6 +740,9 @@ const WindowOverlay = new Lang.Class({
|
||||
let closeNode = this.closeButton.get_theme_node();
|
||||
this.closeButton._overlap = closeNode.get_length('-shell-close-overlap');
|
||||
|
||||
let borderNode = this.border.get_theme_node();
|
||||
this.borderSize = borderNode.get_border_width(St.Side.TOP);
|
||||
|
||||
this._parentActor.queue_relayout();
|
||||
}
|
||||
});
|
||||
@ -1623,20 +1693,25 @@ const Workspace = new Lang.Class({
|
||||
return [];
|
||||
|
||||
let closeButtonHeight, captionHeight;
|
||||
let leftBorder, rightBorder;
|
||||
if (this._windowOverlays.length) {
|
||||
// All of the overlays have the same chrome sizes,
|
||||
// so just pick the first one.
|
||||
let overlay = this._windowOverlays[0];
|
||||
[closeButtonHeight, captionHeight] = overlay.chromeHeights();
|
||||
[leftBorder, rightBorder] = overlay.chromeWidths();
|
||||
} else {
|
||||
[closeButtonHeight, captionHeight] = [0, 0];
|
||||
}
|
||||
|
||||
rowSpacing += captionHeight;
|
||||
columnSpacing += rightBorder;
|
||||
|
||||
let area = { x: this._x, y: this._y, width: this._width, height: this._height };
|
||||
area.y += closeButtonHeight;
|
||||
area.height -= closeButtonHeight;
|
||||
area.x += leftBorder;
|
||||
area.width -= leftBorder;
|
||||
|
||||
if (!this._currentLayout)
|
||||
this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing, captionHeight);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -27,6 +28,8 @@ const WORKSPACE_CUT_SIZE = 10;
|
||||
|
||||
const WORKSPACE_KEEP_ALIVE_TIME = 100;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
const WindowClone = new Lang.Class({
|
||||
Name: 'WindowClone',
|
||||
|
||||
@ -493,6 +496,8 @@ const ThumbnailsBox = new Lang.Class({
|
||||
_init: function() {
|
||||
this.actor = new Shell.GenericContainer({ reactive: true,
|
||||
style_class: 'workspace-thumbnails',
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
@ -521,6 +526,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
this._indicator = indicator;
|
||||
this.actor.add_actor(indicator);
|
||||
|
||||
this._inDrag = false;
|
||||
this._dropWorkspace = -1;
|
||||
this._dropPlaceholderPos = -1;
|
||||
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
|
||||
@ -541,6 +547,18 @@ const ThumbnailsBox = new Lang.Class({
|
||||
|
||||
this.actor.connect('button-press-event', function() { return true; });
|
||||
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||
this.actor.connect('scroll-event',
|
||||
Lang.bind(this, this._onScrollEvent));
|
||||
this.actor.connect('key-release-event',
|
||||
Lang.bind(this, this._onKeyRelease));
|
||||
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateTranslation));
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this._updateTranslation));
|
||||
|
||||
Main.overview.connect('showing',
|
||||
Lang.bind(this, this._createThumbnails));
|
||||
Main.overview.connect('hidden',
|
||||
Lang.bind(this, this._destroyThumbnails));
|
||||
|
||||
Main.overview.connect('item-drag-begin',
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
@ -554,6 +572,50 @@ const ThumbnailsBox = new Lang.Class({
|
||||
Lang.bind(this, this._onDragEnd));
|
||||
Main.overview.connect('window-drag-cancelled',
|
||||
Lang.bind(this, this._onDragCancelled));
|
||||
|
||||
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
|
||||
this._settings.connect('changed::dynamic-workspaces',
|
||||
Lang.bind(this, this._updateSwitcherVisibility));
|
||||
},
|
||||
|
||||
_getInitialTranslation: function() {
|
||||
// Always show the pager when hover, during a drag, or if workspaces are
|
||||
// actually used, e.g. there are windows on more than one
|
||||
let alwaysZoomOut = this.actor.hover || this._inDrag || global.screen.n_workspaces > 2;
|
||||
|
||||
if (!alwaysZoomOut) {
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
|
||||
/* Look for any monitor to the right of the primary, if there is
|
||||
* one, we always keep zoom out, otherwise its hard to reach
|
||||
* the thumbnail area without passing into the next monitor. */
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].x >= primary.x + primary.width) {
|
||||
alwaysZoomOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (alwaysZoomOut)
|
||||
return 0;
|
||||
|
||||
let visibleWidth = this.actor.get_theme_node().get_length('visible-width');
|
||||
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
return rtl ? (visibleWidth - this.actor.width) : (this.actor.width - visibleWidth);
|
||||
},
|
||||
|
||||
_updateTranslation: function() {
|
||||
Tweener.addTween(this, { slideX: this._getInitialTranslation(),
|
||||
time: SLIDE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
},
|
||||
|
||||
_updateSwitcherVisibility: function() {
|
||||
this.actor.visible =
|
||||
this._settings.get_boolean('dynamic-workspaces') ||
|
||||
global.screen.n_workspaces > 1;
|
||||
},
|
||||
|
||||
_onButtonRelease: function(actor, event) {
|
||||
@ -573,6 +635,9 @@ const ThumbnailsBox = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDragBegin: function() {
|
||||
this._inDrag = true;
|
||||
this._updateTranslation();
|
||||
|
||||
this._dragCancelled = false;
|
||||
this._dragMonitor = {
|
||||
dragMotion: Lang.bind(this, this._onDragMotion)
|
||||
@ -595,6 +660,8 @@ const ThumbnailsBox = new Lang.Class({
|
||||
_endDrag: function() {
|
||||
this._clearDragPlaceholder();
|
||||
DND.removeDragMonitor(this._dragMonitor);
|
||||
this._inDrag = false;
|
||||
this._updateTranslation();
|
||||
},
|
||||
|
||||
_onDragMotion: function(dragEvent) {
|
||||
@ -719,10 +786,16 @@ const ThumbnailsBox = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
_createThumbnails: function() {
|
||||
this._switchWorkspaceNotifyId =
|
||||
global.window_manager.connect('switch-workspace',
|
||||
Lang.bind(this, this._activeWorkspaceChanged));
|
||||
this._nWorkspacesNotifyId =
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
Lang.bind(this, this._workspacesChanged));
|
||||
this._syncStackingId =
|
||||
Main.overview.connect('sync-window-stacking',
|
||||
Lang.bind(this, this._syncStacking));
|
||||
|
||||
this._targetScale = 0;
|
||||
this._scale = 0;
|
||||
@ -744,19 +817,101 @@ const ThumbnailsBox = new Lang.Class({
|
||||
};
|
||||
|
||||
this.addThumbnails(0, global.screen.n_workspaces);
|
||||
|
||||
// reset any translation and make sure the actor is visible when
|
||||
// entering the overview
|
||||
this.slideX = this._getInitialTranslation();
|
||||
this.actor.show();
|
||||
|
||||
this._updateSwitcherVisibility();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
_destroyThumbnails: function() {
|
||||
if (this._switchWorkspaceNotifyId > 0) {
|
||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||
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++)
|
||||
this._thumbnails[w].destroy();
|
||||
this._thumbnails = [];
|
||||
},
|
||||
|
||||
_computeTranslation: function() {
|
||||
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
if (rtl)
|
||||
return - this.actor.width;
|
||||
else
|
||||
return this.actor.width;
|
||||
},
|
||||
|
||||
get slideX() {
|
||||
return this._slideX;
|
||||
},
|
||||
|
||||
set slideX(value) {
|
||||
this._slideX = value;
|
||||
this.actor.translation_x = this._slideX;
|
||||
|
||||
if (this._slideX > 0) {
|
||||
let rect = new Clutter.Rect();
|
||||
rect.size.width = this._background.width - this._slideX;
|
||||
rect.size.height = this._background.height;
|
||||
this.actor.clip_rect = rect;
|
||||
} else {
|
||||
this.actor.clip_rect = null;
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this.actor.show();
|
||||
this._updateTranslation();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
let hiddenX = this._computeTranslation();
|
||||
Tweener.addTween(this, { slideX: hiddenX,
|
||||
transition: 'easeOutQuad',
|
||||
time: SLIDE_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, function () {
|
||||
this.actor.hide();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
_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) {
|
||||
for (let k = start; k < start + count; k++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(k);
|
||||
@ -802,7 +957,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
this._queueUpdateStates();
|
||||
},
|
||||
|
||||
syncStacking: function(stackIndices) {
|
||||
_syncStacking: function(actor, stackIndices) {
|
||||
for (let i = 0; i < this._thumbnails.length; i++)
|
||||
this._thumbnails[i].syncStacking(stackIndices);
|
||||
},
|
||||
@ -1157,5 +1312,30 @@ const ThumbnailsBox = new Lang.Class({
|
||||
},
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyRelease: function (actor, event) {
|
||||
switch (event.get_key_symbol()) {
|
||||
case Clutter.KEY_Up:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
|
||||
break;
|
||||
case Clutter.KEY_Down:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
|
||||
break;
|
||||
case Clutter.KEY_Return:
|
||||
Main.overview.toggle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -22,8 +23,6 @@ const MAX_WORKSPACES = 16;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
const CONTROLS_POP_IN_TIME = 0.1;
|
||||
|
||||
|
||||
const WorkspacesView = new Lang.Class({
|
||||
Name: 'WorkspacesView',
|
||||
@ -128,8 +127,11 @@ const WorkspacesView = new Lang.Class({
|
||||
continue;
|
||||
|
||||
let ws = new Workspace.Workspace(null, i);
|
||||
ws.setGeometry(monitors[i].x, monitors[i].y,
|
||||
monitors[i].width, monitors[i].height);
|
||||
let overviewSpacing = Main.overview._spacing;
|
||||
ws.setGeometry(monitors[i].x + overviewSpacing/2,
|
||||
monitors[i].y + overviewSpacing/2,
|
||||
monitors[i].width - overviewSpacing,
|
||||
monitors[i].height - overviewSpacing);
|
||||
global.overlay_group.add_actor(ws.actor);
|
||||
this._extraWorkspaces.push(ws);
|
||||
}
|
||||
@ -205,11 +207,11 @@ const WorkspacesView = new Lang.Class({
|
||||
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
|
||||
},
|
||||
|
||||
_scrollToActive: function(showAnimation) {
|
||||
_scrollToActive: function() {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
|
||||
this._updateWorkspaceActors(showAnimation);
|
||||
this._updateScrollAdjustment(active, showAnimation);
|
||||
this._updateWorkspaceActors(true);
|
||||
this._updateScrollAdjustment(active);
|
||||
},
|
||||
|
||||
// Update workspace actors parameters
|
||||
@ -267,26 +269,21 @@ const WorkspacesView = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_updateScrollAdjustment: function(index, showAnimation) {
|
||||
_updateScrollAdjustment: function(index) {
|
||||
if (this._scrolling)
|
||||
return;
|
||||
|
||||
this._animatingScroll = true;
|
||||
|
||||
if (showAnimation) {
|
||||
Tweener.addTween(this.scrollAdjustment, {
|
||||
value: index,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this._animatingScroll = false;
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this.scrollAdjustment.value = index;
|
||||
this._animatingScroll = false;
|
||||
}
|
||||
Tweener.addTween(this.scrollAdjustment, {
|
||||
value: index,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this._animatingScroll = false;
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
|
||||
@ -313,7 +310,7 @@ const WorkspacesView = new Lang.Class({
|
||||
if (this._scrolling)
|
||||
return;
|
||||
|
||||
this._scrollToActive(true);
|
||||
this._scrollToActive();
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
@ -387,24 +384,11 @@ const WorkspacesView = new Lang.Class({
|
||||
this._scrolling = true;
|
||||
},
|
||||
|
||||
endSwipeScroll: function(result) {
|
||||
endSwipeScroll: function() {
|
||||
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
|
||||
this._scrollToActive();
|
||||
this._updateVisibility();
|
||||
},
|
||||
|
||||
@ -453,32 +437,39 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
this.actor = new Shell.GenericContainer();
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._updateWorkspacesGeometry));
|
||||
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
||||
this.actor.set_clip_to_allocation(true);
|
||||
|
||||
let controls = new St.Bin({ style_class: 'workspace-controls',
|
||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
|
||||
y_align: St.Align.START,
|
||||
y_fill: true });
|
||||
this._controls = controls;
|
||||
this.actor.add_actor(controls);
|
||||
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);
|
||||
|
||||
controls.reactive = true;
|
||||
controls.track_hover = true;
|
||||
controls.connect('notify::hover',
|
||||
Lang.bind(this, this._onControlsHoverChanged));
|
||||
controls.connect('scroll-event',
|
||||
Lang.bind(this, this._onScrollEvent));
|
||||
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);
|
||||
|
||||
this._primaryIndex = Main.layoutManager.primaryIndex;
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
controls.add_actor(this._thumbnailsBox.actor);
|
||||
|
||||
this._workspacesViews = null;
|
||||
this._primaryScrollAdjustment = null;
|
||||
|
||||
@ -491,26 +482,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._inDrag = false;
|
||||
this._cancelledDrag = false;
|
||||
|
||||
this._controlsInitiallyHovered = false;
|
||||
this._alwaysZoomOut = false;
|
||||
this._zoomOut = false;
|
||||
this._zoomFraction = 0;
|
||||
|
||||
this._updateAlwaysZoom();
|
||||
|
||||
// If we stop hiding the overview on layout changes, we will need to
|
||||
// update the _workspacesViews here
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom));
|
||||
|
||||
Main.xdndHandler.connect('drag-begin', Lang.bind(this, function(){
|
||||
this._alwaysZoomOut = true;
|
||||
}));
|
||||
|
||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, function(){
|
||||
this._alwaysZoomOut = false;
|
||||
this._updateAlwaysZoom();
|
||||
}));
|
||||
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
Lang.bind(this, this._workspacesChanged));
|
||||
|
||||
@ -525,44 +496,20 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._notifyOpacityId = 0;
|
||||
this._swipeScrollBeginId = 0;
|
||||
this._swipeScrollEndId = 0;
|
||||
|
||||
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
|
||||
this._settings.connect('changed::dynamic-workspaces',
|
||||
Lang.bind(this, this._updateSwitcherVisibility));
|
||||
},
|
||||
|
||||
_updateSwitcherVisibility: function() {
|
||||
this._thumbnailsBox.actor.visible =
|
||||
this._settings.get_boolean('dynamic-workspaces') ||
|
||||
global.screen.n_workspaces > 1;
|
||||
_onPan: function(action) {
|
||||
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||
let adjustment = this._scrollAdjustment;
|
||||
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||
return false;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if(!this._alwaysZoomOut) {
|
||||
let [mouseX, mouseY] = global.get_pointer();
|
||||
let [x, y] = this._controls.get_transformed_position();
|
||||
let [width, height] = this._controls.get_transformed_size();
|
||||
let visibleWidth = this._controls.get_theme_node().get_length('visible-width');
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
if(rtl)
|
||||
x = x + width - visibleWidth;
|
||||
if(mouseX > x - 0.5 && mouseX < x + visibleWidth + 0.5 &&
|
||||
mouseY > y - 0.5 && mouseY < y + height + 0.5)
|
||||
this._controlsInitiallyHovered = true;
|
||||
}
|
||||
|
||||
this._zoomOut = this._alwaysZoomOut;
|
||||
this._zoomFraction = this._alwaysZoomOut ? 1 : 0;
|
||||
this._updateZoom();
|
||||
|
||||
this._controls.show();
|
||||
this._thumbnailsBox.show();
|
||||
this._updateSwitcherVisibility();
|
||||
|
||||
this._updateWorkspacesViews();
|
||||
|
||||
this._restackedNotifyId =
|
||||
global.screen.connect('restacked',
|
||||
Main.overview.connect('sync-window-stacking',
|
||||
Lang.bind(this, this._onRestacked));
|
||||
|
||||
if (this._itemDragBeginId == 0)
|
||||
@ -583,8 +530,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
if (this._windowDragEndId == 0)
|
||||
this._windowDragEndId = Main.overview.connect('window-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
|
||||
this._onRestacked();
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
@ -594,14 +539,8 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._controls.hide();
|
||||
this._thumbnailsBox.hide();
|
||||
|
||||
if (!this._alwaysZoomOut)
|
||||
this.zoomFraction = 0;
|
||||
|
||||
if (this._restackedNotifyId > 0){
|
||||
global.screen.disconnect(this._restackedNotifyId);
|
||||
Main.overview.disconnect(this._restackedNotifyId);
|
||||
this._restackedNotifyId = 0;
|
||||
}
|
||||
if (this._itemDragBeginId > 0) {
|
||||
@ -640,33 +579,6 @@ 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() {
|
||||
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
|
||||
|
||||
@ -706,7 +618,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._scrollAdjustment = view.scrollAdjustment;
|
||||
this._scrollAdjustment.connect('notify::value',
|
||||
Lang.bind(this, this._scrollValueChanged));
|
||||
this._setupSwipeScrolling();
|
||||
}
|
||||
this._workspacesViews.push(view);
|
||||
}
|
||||
@ -745,76 +656,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows();
|
||||
},
|
||||
|
||||
// zoomFraction property allows us to tween the controls sliding in and out
|
||||
set zoomFraction(fraction) {
|
||||
this._zoomFraction = fraction;
|
||||
this.actor.queue_relayout();
|
||||
},
|
||||
|
||||
get zoomFraction() {
|
||||
return this._zoomFraction;
|
||||
},
|
||||
|
||||
_updateAlwaysZoom: function() {
|
||||
// Always show the pager if workspaces are actually used,
|
||||
// e.g. there are windows on more than one
|
||||
this._alwaysZoomOut = global.screen.n_workspaces > 2;
|
||||
|
||||
if (this._alwaysZoomOut)
|
||||
return;
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
|
||||
/* Look for any monitor to the right of the primary, if there is
|
||||
* one, we always keep zoom out, otherwise its hard to reach
|
||||
* the thumbnail area without passing into the next monitor. */
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].x >= primary.x + primary.width) {
|
||||
this._alwaysZoomOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getPreferredWidth: function (actor, forHeight, alloc) {
|
||||
// pass through the call in case the child needs it, but report 0x0
|
||||
this._controls.get_preferred_width(forHeight);
|
||||
},
|
||||
|
||||
_getPreferredHeight: function (actor, forWidth, alloc) {
|
||||
// pass through the call in case the child needs it, but report 0x0
|
||||
this._controls.get_preferred_height(forWidth);
|
||||
},
|
||||
|
||||
_allocate: function (actor, box, flags) {
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
let totalWidth = box.x2 - box.x1;
|
||||
|
||||
// width of the controls
|
||||
let [controlsMin, controlsNatural] = this._controls.get_preferred_width(box.y2 - box.y1);
|
||||
|
||||
// Amount of space on the screen we reserve for the visible control
|
||||
let controlsVisible = this._controls.get_theme_node().get_length('visible-width');
|
||||
let controlsReserved = controlsVisible * (1 - this._zoomFraction) + controlsNatural * this._zoomFraction;
|
||||
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
if (rtl) {
|
||||
childBox.x2 = controlsReserved;
|
||||
childBox.x1 = childBox.x2 - controlsNatural;
|
||||
} else {
|
||||
childBox.x1 = totalWidth - controlsReserved;
|
||||
childBox.x2 = childBox.x1 + controlsNatural;
|
||||
}
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = box.y2- box.y1;
|
||||
this._controls.allocate(childBox, flags);
|
||||
|
||||
this._updateWorkspacesGeometry();
|
||||
},
|
||||
|
||||
_parentSet: function(actor, oldParent) {
|
||||
if (oldParent && this._notifyOpacityId)
|
||||
oldParent.disconnect(this._notifyOpacityId);
|
||||
@ -851,23 +692,19 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
let width = fullWidth;
|
||||
let height = fullHeight;
|
||||
|
||||
let [controlsMin, controlsNatural] = this._controls.get_preferred_width(height);
|
||||
let controlsVisible = this._controls.get_theme_node().get_length('visible-width');
|
||||
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
|
||||
let clipWidth = width - controlsVisible;
|
||||
let clipWidth = width;
|
||||
let clipHeight = fullHeight;
|
||||
let clipX = rtl ? x + controlsVisible : x;
|
||||
let clipX = x;
|
||||
let clipY = y + (fullHeight - clipHeight) / 2;
|
||||
|
||||
let widthAdjust = this._zoomOut ? controlsNatural : controlsVisible;
|
||||
widthAdjust += Main.overview._spacing;
|
||||
width -= widthAdjust;
|
||||
let overviewSpacing = Main.overview._spacing;
|
||||
width -= overviewSpacing;
|
||||
if (rtl)
|
||||
x += widthAdjust;
|
||||
x += overviewSpacing;
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
@ -882,34 +719,21 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
monitors[i].y,
|
||||
monitors[i].width,
|
||||
monitors[i].height);
|
||||
this._workspacesViews[m].setGeometry(monitors[i].x,
|
||||
monitors[i].y,
|
||||
monitors[i].width,
|
||||
monitors[i].height);
|
||||
this._workspacesViews[m].setGeometry(monitors[i].x + overviewSpacing/2,
|
||||
monitors[i].y + overviewSpacing/2,
|
||||
monitors[i].width - overviewSpacing,
|
||||
monitors[i].height - overviewSpacing);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
_onRestacked: function(actor, stackIndices) {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].syncStacking(stackIndices);
|
||||
|
||||
this._thumbnailsBox.syncStacking(stackIndices);
|
||||
},
|
||||
|
||||
_workspacesChanged: function() {
|
||||
this._updateAlwaysZoom();
|
||||
this._updateZoom();
|
||||
|
||||
if (this._workspacesViews == null)
|
||||
return;
|
||||
|
||||
@ -934,8 +758,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
|
||||
} else {
|
||||
// Assume workspaces are only removed sequentially
|
||||
// (e.g. 2,3,4 - not 2,4,7)
|
||||
@ -958,43 +780,11 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
lostWorkspaces[l].destroy();
|
||||
}
|
||||
}
|
||||
|
||||
this._thumbnailsBox.removeThumbnails(removedIndex, removedNum);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces,
|
||||
newNumWorkspaces);
|
||||
this._updateSwitcherVisibility();
|
||||
},
|
||||
|
||||
_updateZoom : function() {
|
||||
if (Main.overview.animationInProgress)
|
||||
return;
|
||||
|
||||
let shouldZoom = this._alwaysZoomOut || this._controls.hover;
|
||||
if (shouldZoom != this._zoomOut) {
|
||||
this._zoomOut = shouldZoom;
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
if (!this._workspacesViews)
|
||||
return;
|
||||
|
||||
Tweener.addTween(this,
|
||||
{ zoomFraction: this._zoomOut ? 1 : 0,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].updateWindowPositions();
|
||||
}
|
||||
},
|
||||
|
||||
_onControlsHoverChanged: function() {
|
||||
if(!this._controls.hover)
|
||||
this._controlsInitiallyHovered = false;
|
||||
if(!this._controlsInitiallyHovered)
|
||||
this._updateZoom();
|
||||
},
|
||||
|
||||
_dragBegin: function() {
|
||||
@ -1012,33 +802,11 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDragMotion: function(dragEvent) {
|
||||
let controlsHovered = this._controls.contains(dragEvent.targetActor);
|
||||
this._controls.set_hover(controlsHovered);
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
|
||||
_dragEnd: function() {
|
||||
this._inDrag = false;
|
||||
|
||||
// We do this deferred because drag-end is emitted before dnd.js emits
|
||||
// event/leave events that were suppressed during the drag. If we didn't
|
||||
// defer this, we'd zoom out then immediately zoom in because of the
|
||||
// enter event we received. That would normally be invisible but we
|
||||
// might as well avoid it.
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
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);
|
||||
|
@ -17,6 +17,7 @@ js/ui/components/networkAgent.js
|
||||
js/ui/components/polkitAgent.js
|
||||
js/ui/components/recorder.js
|
||||
js/ui/components/telepathyClient.js
|
||||
js/ui/ctrlAltTab.js
|
||||
js/ui/dash.js
|
||||
js/ui/dateMenu.js
|
||||
js/ui/endSessionDialog.js
|
||||
|
248
po/he.po
248
po/he.po
@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-11-09 11:32+0200\n"
|
||||
"PO-Revision-Date: 2012-11-09 11:36+0200\n"
|
||||
"POT-Creation-Date: 2012-11-23 10:13+0200\n"
|
||||
"PO-Revision-Date: 2012-11-23 10:14+0200\n"
|
||||
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
|
||||
"Language-Team: Hebrew <sh.yaron@gmail.com>\n"
|
||||
"Language: he\n"
|
||||
@ -244,11 +244,11 @@ msgstr "הרחבה"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "יש לבחור את ההרחבה להגדרה באמצעות תיבת הבחירה המשולבת שלהלן."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:560
|
||||
#: ../js/gdm/loginDialog.js:565
|
||||
msgid "Session..."
|
||||
msgstr "הפעלה..."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:707
|
||||
#: ../js/gdm/loginDialog.js:722
|
||||
msgctxt "title"
|
||||
msgid "Sign In"
|
||||
msgstr "כניסה"
|
||||
@ -256,40 +256,40 @@ msgstr "כניסה"
|
||||
#. translators: this message is shown below the user list on the
|
||||
#. login screen. It can be activated to reveal an entry for
|
||||
#. manually entering the username.
|
||||
#: ../js/gdm/loginDialog.js:768
|
||||
#: ../js/gdm/loginDialog.js:786
|
||||
msgid "Not listed?"
|
||||
msgstr "לא רשום?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:912
|
||||
#: ../js/gdm/loginDialog.js:962
|
||||
#: ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162
|
||||
#: ../js/ui/endSessionDialog.js:373
|
||||
#: ../js/ui/extensionDownloader.js:195
|
||||
#: ../js/ui/shellMountOperation.js:396
|
||||
#: ../js/ui/status/bluetooth.js:427
|
||||
#: ../js/ui/unlockDialog.js:171
|
||||
#: ../js/ui/status/bluetooth.js:413
|
||||
#: ../js/ui/unlockDialog.js:179
|
||||
msgid "Cancel"
|
||||
msgstr "ביטול"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:917
|
||||
#: ../js/gdm/loginDialog.js:978
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "כניסה"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:917
|
||||
#: ../js/gdm/loginDialog.js:978
|
||||
msgid "Next"
|
||||
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/gdm/loginDialog.js:993
|
||||
#: ../js/gdm/loginDialog.js:1086
|
||||
#: ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "שם משתמש:"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1289
|
||||
#: ../js/gdm/loginDialog.js:1382
|
||||
msgid "Login Window"
|
||||
msgstr "חלון כניסה"
|
||||
|
||||
@ -347,28 +347,28 @@ msgid "Execution of '%s' failed:"
|
||||
msgstr "ההרצה של '%s' נכשלה:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:252
|
||||
#: ../js/ui/appDisplay.js:259
|
||||
msgid "All"
|
||||
msgstr "הכול"
|
||||
|
||||
#: ../js/ui/appDisplay.js:310
|
||||
#: ../js/ui/appDisplay.js:317
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "יישומים"
|
||||
|
||||
#: ../js/ui/appDisplay.js:370
|
||||
#: ../js/ui/appDisplay.js:377
|
||||
msgid "SETTINGS"
|
||||
msgstr "הגדרות"
|
||||
|
||||
#: ../js/ui/appDisplay.js:675
|
||||
#: ../js/ui/appDisplay.js:682
|
||||
msgid "New Window"
|
||||
msgstr "חלון חדש"
|
||||
|
||||
#: ../js/ui/appDisplay.js:678
|
||||
#: ../js/ui/appDisplay.js:685
|
||||
#: ../js/ui/dash.js:289
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "הסרה מהמועדפים"
|
||||
|
||||
#: ../js/ui/appDisplay.js:679
|
||||
#: ../js/ui/appDisplay.js:686
|
||||
msgid "Add to Favorites"
|
||||
msgstr "הוספה למועדפים"
|
||||
|
||||
@ -644,7 +644,7 @@ msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "פעולה זו לא הצליחה, נא לנסות שוב. עמך הסליחה."
|
||||
|
||||
#. Translators: this is a filename used for screencast recording
|
||||
#: ../js/ui/components/recorder.js:44
|
||||
#: ../js/ui/components/recorder.js:48
|
||||
#, no-c-format
|
||||
msgid "Screencast from %d %t"
|
||||
msgstr "צילום מסך מהקובץ %d %t"
|
||||
@ -1080,11 +1080,15 @@ msgstr "פתיחה"
|
||||
msgid "Remove"
|
||||
msgstr "הסרה"
|
||||
|
||||
#: ../js/ui/messageTray.js:1545
|
||||
#: ../js/ui/messageTray.js:1552
|
||||
msgid "No Messages"
|
||||
msgstr "אין הודעות"
|
||||
|
||||
#: ../js/ui/messageTray.js:1569
|
||||
msgid "Message Tray"
|
||||
msgstr "אזור דיווח ההודעות"
|
||||
|
||||
#: ../js/ui/messageTray.js:2588
|
||||
#: ../js/ui/messageTray.js:2639
|
||||
msgid "System Information"
|
||||
msgstr "פרטי המערכת"
|
||||
|
||||
@ -1116,17 +1120,17 @@ msgstr "יש להקליד כדי לחפש..."
|
||||
msgid "Dash"
|
||||
msgstr "חלונית"
|
||||
|
||||
#: ../js/ui/panel.js:580
|
||||
#: ../js/ui/panel.js:599
|
||||
msgid "Quit"
|
||||
msgstr "יציאה"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:612
|
||||
#: ../js/ui/panel.js:631
|
||||
msgid "Activities"
|
||||
msgstr "פעילויות"
|
||||
|
||||
#: ../js/ui/panel.js:979
|
||||
#: ../js/ui/panel.js:999
|
||||
msgid "Top Bar"
|
||||
msgstr "הסרגל העליון"
|
||||
|
||||
@ -1169,6 +1173,11 @@ msgstr[0] "התרעה אחת"
|
||||
msgstr[1] "%d התרעות"
|
||||
msgstr[2] "2 התרעות"
|
||||
|
||||
#: ../js/ui/screenShield.js:401
|
||||
#: ../js/ui/userMenu.js:773
|
||||
msgid "Lock"
|
||||
msgstr "נעילה"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:275
|
||||
msgid "Searching..."
|
||||
msgstr "בחיפוש..."
|
||||
@ -1202,66 +1211,64 @@ msgid "Remember Password"
|
||||
msgstr "שמירת הססמה"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:400
|
||||
#: ../js/ui/unlockDialog.js:174
|
||||
#: ../js/ui/unlockDialog.js:193
|
||||
msgid "Unlock"
|
||||
msgstr "שחרור"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:39
|
||||
#: ../js/ui/status/accessibility.js:40
|
||||
msgid "Accessibility"
|
||||
msgstr "נגישות"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:44
|
||||
#: ../js/ui/status/accessibility.js:45
|
||||
msgid "Zoom"
|
||||
msgstr "תקריב"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:51
|
||||
#: ../js/ui/status/accessibility.js:52
|
||||
msgid "Screen Reader"
|
||||
msgstr "מקריא מסך"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:55
|
||||
#: ../js/ui/status/accessibility.js:56
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "מקלדת מסך"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:59
|
||||
#: ../js/ui/status/accessibility.js:60
|
||||
msgid "Visual Alerts"
|
||||
msgstr "התראות חזותיות"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:62
|
||||
#: ../js/ui/status/accessibility.js:63
|
||||
msgid "Sticky Keys"
|
||||
msgstr "מקשים דביקים"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:65
|
||||
#: ../js/ui/status/accessibility.js:66
|
||||
msgid "Slow Keys"
|
||||
msgstr "מקשים אטיים"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:68
|
||||
#: ../js/ui/status/accessibility.js:69
|
||||
msgid "Bounce Keys"
|
||||
msgstr "מקשים קופצים"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:71
|
||||
#: ../js/ui/status/accessibility.js:72
|
||||
msgid "Mouse Keys"
|
||||
msgstr "מקשי עכבר"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:75
|
||||
#: ../js/ui/status/accessibility.js:76
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "הגדרות גישה אוניברסלית"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:109
|
||||
#: ../js/ui/status/accessibility.js:112
|
||||
msgid "High Contrast"
|
||||
msgstr "ניגודיות גבוהה"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:146
|
||||
#: ../js/ui/status/accessibility.js:159
|
||||
msgid "Large Text"
|
||||
msgstr "טקסט גדול"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:27
|
||||
#: ../js/ui/status/bluetooth.js:31
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
#: ../js/ui/status/bluetooth.js:304
|
||||
#: ../js/ui/status/bluetooth.js:335
|
||||
#: ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:400
|
||||
#: ../js/ui/status/network.js:873
|
||||
#: ../js/ui/status/bluetooth.js:288
|
||||
#: ../js/ui/status/bluetooth.js:319
|
||||
#: ../js/ui/status/bluetooth.js:355
|
||||
#: ../js/ui/status/bluetooth.js:386
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -1283,7 +1290,7 @@ msgstr "הגדרות Bluetooth"
|
||||
|
||||
#. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill
|
||||
#: ../js/ui/status/bluetooth.js:103
|
||||
#: ../js/ui/status/network.js:208
|
||||
#: ../js/ui/status/network.js:169
|
||||
msgid "hardware disabled"
|
||||
msgstr "מנוטרל חומרתית"
|
||||
|
||||
@ -1292,13 +1299,13 @@ msgid "Connection"
|
||||
msgstr "חיבור"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:207
|
||||
#: ../js/ui/status/network.js:475
|
||||
#: ../js/ui/status/network.js:436
|
||||
msgid "disconnecting..."
|
||||
msgstr "בהליכי ניתוק..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:220
|
||||
#: ../js/ui/status/network.js:481
|
||||
#: ../js/ui/status/network.js:1507
|
||||
#: ../js/ui/status/network.js:442
|
||||
#: ../js/ui/status/network.js:1449
|
||||
msgid "connecting..."
|
||||
msgstr "בהתחברות..."
|
||||
|
||||
@ -1306,88 +1313,77 @@ msgstr "בהתחברות..."
|
||||
msgid "Send Files..."
|
||||
msgstr "שליחת קבצים..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
msgid "Browse Files..."
|
||||
msgstr "עיון בקבצים..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:252
|
||||
msgid "Error browsing device"
|
||||
msgstr "שגיאה בעיון בהתקן"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:253
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "לא ניתן לעיין בהתקן הנבחר, השגיאה היא '%s'"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:261
|
||||
#: ../js/ui/status/bluetooth.js:245
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "הגדרות מקלדת"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:264
|
||||
#: ../js/ui/status/bluetooth.js:248
|
||||
msgid "Mouse Settings"
|
||||
msgstr "הגדרות עכבר"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:269
|
||||
#: ../js/ui/status/bluetooth.js:253
|
||||
#: ../js/ui/status/volume.js:234
|
||||
msgid "Sound Settings"
|
||||
msgstr "הגדרות שמע"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:336
|
||||
#: ../js/ui/status/bluetooth.js:320
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "בקשת אישור מאת %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:342
|
||||
#: ../js/ui/status/bluetooth.js:326
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "ההתקן %s מעוניין לגשת אל השירות '%s'"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:344
|
||||
#: ../js/ui/status/bluetooth.js:328
|
||||
msgid "Always grant access"
|
||||
msgstr "תמיד להעניק גישה"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:345
|
||||
#: ../js/ui/status/bluetooth.js:329
|
||||
msgid "Grant this time only"
|
||||
msgstr "הענקת גישה הפעם בלבד"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:346
|
||||
#: ../js/ui/status/bluetooth.js:330
|
||||
msgid "Reject"
|
||||
msgstr "סירוב"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#. Translators: argument is the device short name
|
||||
#: ../js/ui/status/bluetooth.js:357
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "אישור צימוד עבור %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#: ../js/ui/status/bluetooth.js:408
|
||||
#: ../js/ui/status/bluetooth.js:363
|
||||
#: ../js/ui/status/bluetooth.js:394
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "ההתקן %s מעוניין בצימוד עם מחשב זה"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:379
|
||||
#: ../js/ui/status/bluetooth.js:364
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
|
||||
msgstr "נא לאשר האם קוד ה־PIN '%06d' תואם את זה שמופיע בהתקן."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
#. Translators: this is the verb, not the noun
|
||||
#: ../js/ui/status/bluetooth.js:367
|
||||
msgid "Matches"
|
||||
msgstr "התאמות"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
#: ../js/ui/status/bluetooth.js:368
|
||||
msgid "Does not match"
|
||||
msgstr "אינו תואם"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:401
|
||||
#: ../js/ui/status/bluetooth.js:387
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "בקשת צימוד עבור %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:409
|
||||
#: ../js/ui/status/bluetooth.js:395
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "נא להזין את קוד ה־PIN המוזכר בהתקן."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:426
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
msgid "OK"
|
||||
msgstr "אישור"
|
||||
|
||||
@ -1403,122 +1399,114 @@ msgstr "הגדרות אזור ושפה"
|
||||
msgid "Volume, network, battery"
|
||||
msgstr "עצמת שמע, רשת, סוללה"
|
||||
|
||||
#: ../js/ui/status/network.js:94
|
||||
#: ../js/ui/status/network.js:95
|
||||
msgid "<unknown>"
|
||||
msgstr "<לא ידוע>"
|
||||
|
||||
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
|
||||
#: ../js/ui/status/network.js:230
|
||||
#: ../js/ui/status/network.js:191
|
||||
msgid "disabled"
|
||||
msgstr "מנוטרל"
|
||||
|
||||
#. Translators: this is for network devices that are physically present but are not
|
||||
#. under NetworkManager's control (and thus cannot be used in the menu)
|
||||
#: ../js/ui/status/network.js:473
|
||||
#: ../js/ui/status/network.js:434
|
||||
msgid "unmanaged"
|
||||
msgstr "לא מנוהל"
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
#: ../js/ui/status/network.js:484
|
||||
#: ../js/ui/status/network.js:1510
|
||||
#: ../js/ui/status/network.js:445
|
||||
#: ../js/ui/status/network.js:1452
|
||||
msgid "authentication required"
|
||||
msgstr "נדרש אימות"
|
||||
|
||||
#. Translators: this is for devices that require some kind of firmware or kernel
|
||||
#. module, which is missing
|
||||
#: ../js/ui/status/network.js:494
|
||||
#: ../js/ui/status/network.js:455
|
||||
msgid "firmware missing"
|
||||
msgstr "הקושחה חסרה"
|
||||
|
||||
#. Translators: this is for wired network devices that are physically disconnected
|
||||
#: ../js/ui/status/network.js:501
|
||||
#: ../js/ui/status/network.js:462
|
||||
msgid "cable unplugged"
|
||||
msgstr "הכבל מנותק"
|
||||
|
||||
#. Translators: this is for a network device that cannot be activated (for example it
|
||||
#. is disabled by rfkill, or it has no coverage
|
||||
#: ../js/ui/status/network.js:506
|
||||
#: ../js/ui/status/network.js:467
|
||||
msgid "unavailable"
|
||||
msgstr "לא זמין"
|
||||
|
||||
#: ../js/ui/status/network.js:508
|
||||
#: ../js/ui/status/network.js:1512
|
||||
#: ../js/ui/status/network.js:469
|
||||
#: ../js/ui/status/network.js:1454
|
||||
msgid "connection failed"
|
||||
msgstr "החיבור נכשל"
|
||||
|
||||
#: ../js/ui/status/network.js:560
|
||||
#: ../js/ui/status/network.js:1446
|
||||
#: ../js/ui/status/network.js:1588
|
||||
#: ../js/ui/status/network.js:525
|
||||
#: ../js/ui/status/network.js:1388
|
||||
#: ../js/ui/status/network.js:1530
|
||||
msgid "More..."
|
||||
msgstr "עוד..."
|
||||
|
||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
|
||||
#. and we cannot access its settings (including the name)
|
||||
#: ../js/ui/status/network.js:596
|
||||
#: ../js/ui/status/network.js:1376
|
||||
#: ../js/ui/status/network.js:561
|
||||
#: ../js/ui/status/network.js:1318
|
||||
msgid "Connected (private)"
|
||||
msgstr "מחובר (פרטי)"
|
||||
|
||||
#: ../js/ui/status/network.js:669
|
||||
#: ../js/ui/status/network.js:615
|
||||
msgid "Auto Ethernet"
|
||||
msgstr "אתרנט אוטומטי"
|
||||
|
||||
#: ../js/ui/status/network.js:727
|
||||
#: ../js/ui/status/network.js:673
|
||||
msgid "Auto broadband"
|
||||
msgstr "פס רחב אוטומטי"
|
||||
|
||||
#: ../js/ui/status/network.js:730
|
||||
#: ../js/ui/status/network.js:676
|
||||
msgid "Auto dial-up"
|
||||
msgstr "חיוג אוטומטי"
|
||||
|
||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
|
||||
#: ../js/ui/status/network.js:859
|
||||
#: ../js/ui/status/network.js:1393
|
||||
#: ../js/ui/status/network.js:805
|
||||
#: ../js/ui/status/network.js:1335
|
||||
#, c-format
|
||||
msgid "Auto %s"
|
||||
msgstr "%s אוטומטי"
|
||||
|
||||
#: ../js/ui/status/network.js:861
|
||||
#: ../js/ui/status/network.js:807
|
||||
msgid "Auto bluetooth"
|
||||
msgstr "Bluetooth אוטומטי"
|
||||
|
||||
#: ../js/ui/status/network.js:1395
|
||||
#: ../js/ui/status/network.js:1337
|
||||
msgid "Auto wireless"
|
||||
msgstr "אלחוטי אוטומטי"
|
||||
|
||||
#: ../js/ui/status/network.js:1637
|
||||
#: ../js/ui/status/network.js:1579
|
||||
msgid "Enable networking"
|
||||
msgstr "הפעלת תכונת הרשת"
|
||||
|
||||
#: ../js/ui/status/network.js:1659
|
||||
msgid "Wired"
|
||||
msgstr "קווי"
|
||||
#: ../js/ui/status/network.js:1611
|
||||
msgid "Wi-Fi"
|
||||
msgstr "רשת אלחוטית"
|
||||
|
||||
#: ../js/ui/status/network.js:1670
|
||||
msgid "Wireless"
|
||||
msgstr "אלחוטי"
|
||||
|
||||
#: ../js/ui/status/network.js:1680
|
||||
msgid "Mobile broadband"
|
||||
msgstr "פס־רחב נייד"
|
||||
|
||||
#: ../js/ui/status/network.js:1691
|
||||
#: ../js/ui/status/network.js:1630
|
||||
msgid "Network Settings"
|
||||
msgstr "הגדרות הרשת"
|
||||
|
||||
#: ../js/ui/status/network.js:1735
|
||||
#: ../js/ui/status/network.js:1674
|
||||
msgid "Network Manager"
|
||||
msgstr "מנהל הרשתות"
|
||||
|
||||
#: ../js/ui/status/network.js:1809
|
||||
#: ../js/ui/status/network.js:1756
|
||||
msgid "Connection failed"
|
||||
msgstr "ההתחברות נכשל"
|
||||
|
||||
#: ../js/ui/status/network.js:1810
|
||||
#: ../js/ui/status/network.js:1757
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "הפעלת חיבור הרשת נכשלה"
|
||||
|
||||
#: ../js/ui/status/network.js:2108
|
||||
#: ../js/ui/status/network.js:2074
|
||||
msgid "Networking is disabled"
|
||||
msgstr "תכונת הרשת מנוטרלת"
|
||||
|
||||
@ -1634,10 +1622,14 @@ msgstr "עצמה"
|
||||
msgid "Microphone"
|
||||
msgstr "מיקרופון"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:181
|
||||
#: ../js/ui/unlockDialog.js:202
|
||||
msgid "Log in as another user"
|
||||
msgstr "כניסה בתור משתמש אחר"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:225
|
||||
msgid "Unlock Window"
|
||||
msgstr "שחרור החלון"
|
||||
|
||||
#: ../js/ui/userMenu.js:176
|
||||
msgid "Available"
|
||||
msgstr "זמין"
|
||||
@ -1678,10 +1670,6 @@ msgstr "החלפת משתמש"
|
||||
msgid "Log Out"
|
||||
msgstr "יציאה"
|
||||
|
||||
#: ../js/ui/userMenu.js:773
|
||||
msgid "Lock"
|
||||
msgstr "נעילה"
|
||||
|
||||
#: ../js/ui/userMenu.js:788
|
||||
msgid "Install Updates & Restart"
|
||||
msgstr "התקנת עדכונים והפעלה מחדש"
|
||||
@ -1798,6 +1786,24 @@ msgstr "בררת מחדל"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "המשתמש בחר להתעלם מתיבת דו־שיח האימות"
|
||||
|
||||
#~ msgid "Browse Files..."
|
||||
#~ msgstr "עיון בקבצים..."
|
||||
|
||||
#~ msgid "Error browsing device"
|
||||
#~ msgstr "שגיאה בעיון בהתקן"
|
||||
|
||||
#~ msgid "The requested device cannot be browsed, error is '%s'"
|
||||
#~ msgstr "לא ניתן לעיין בהתקן הנבחר, השגיאה היא '%s'"
|
||||
|
||||
#~ msgid "Wired"
|
||||
#~ msgstr "קווי"
|
||||
|
||||
#~ msgid "Wireless"
|
||||
#~ msgstr "אלחוטי"
|
||||
|
||||
#~ msgid "Mobile broadband"
|
||||
#~ msgstr "פס־רחב נייד"
|
||||
|
||||
#~ msgid "VPN Connections"
|
||||
#~ msgstr "חיבורי VPN"
|
||||
|
||||
|
412
po/kn.po
412
po/kn.po
@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2012-09-19 11:02+0000\n"
|
||||
"PO-Revision-Date: 2012-09-26 16:05+0530\n"
|
||||
"POT-Creation-Date: 2012-12-07 10:16+0000\n"
|
||||
"PO-Revision-Date: 2012-12-07 16:12+0530\n"
|
||||
"Last-Translator: Shankar Prasad <svenkate@redhat.com>\n"
|
||||
"Language-Team: Kannada <kn@li.org>\n"
|
||||
"Language: kn\n"
|
||||
@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
||||
"X-Generator: Lokalize 1.2\n"
|
||||
"X-Generator: Lokalize 1.5\n"
|
||||
|
||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
|
||||
msgid "Screenshots"
|
||||
@ -25,16 +25,15 @@ msgstr "ತೆರೆಚಿತ್ರಗಳು"
|
||||
|
||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:2
|
||||
msgid "Record a screencast"
|
||||
msgstr ""
|
||||
msgstr "ಒಂದು ಸ್ಕ್ರೀನ್ಕ್ಯಾಸ್ಟನ್ನು ರೆಕಾರ್ಡು ಮಾಡಿ"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:1
|
||||
#| msgid "File System"
|
||||
msgid "System"
|
||||
msgstr "ವ್ಯವಸ್ಥೆ"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:2
|
||||
msgid "Show the message tray"
|
||||
msgstr ""
|
||||
msgstr "ಸಂದೇಶ ಟ್ರೇ ಅನ್ನು ತೋರಿಸು"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
@ -79,6 +78,12 @@ msgid ""
|
||||
"list. You can also manipulate this list with the EnableExtension and "
|
||||
"DisableExtension DBus methods on org.gnome.Shell."
|
||||
msgstr ""
|
||||
"GNOME ಶೆಲ್ ವಿಸ್ತರಣೆಗಳು ಒಂದು uuid ಗುಣವನ್ನು ಹೊಂದಿವೆ; ಈ ಕೀಲಿ ಪಟ್ಟಿಯು ಲೋಡ್ "
|
||||
"ಮಾಡಬೇಕಿರುವ "
|
||||
"ವಿಸ್ತರಣೆಗಳ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸುತ್ತದೆ. ಯಾವುದೆ ವಿಸ್ತರಣೆಗಳನ್ನು ಲೋಡ್ ಮಾಡಬೇಕಿದ್ದಲ್ಲಿ "
|
||||
"ಅದು ಈ "
|
||||
"ಪಟ್ಟಿಯಲ್ಲಿ ಇರುವುದು ಅತ್ಯಗತ್ಯ. org.gnome.Shell ನಲ್ಲಿ EnableExtension ಮತ್ತು "
|
||||
"DisableExtension DBus ವಿಧಾನಗಳನ್ನು ಬಳಸಿಕೊಂಡೂ ಸಹ ಈ ಪಟ್ಟಿಯನ್ನು ನಿರ್ವಹಿಸಬಹುದು."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
@ -91,6 +96,11 @@ msgid ""
|
||||
"want to disable this for privacy reasons. Please note that doing so won't "
|
||||
"remove already saved data."
|
||||
msgstr ""
|
||||
"ಶೆಲ್ ಸಾಮಾನ್ಯವಾಗಿ ಹೆಚ್ಚಾಗಿ ಬಳಸಲಾದ (ಉದಾ. ಆರಂಭಕಗಳಲ್ಲಿ) ಅನ್ವಯಗಳನ್ನು ತೋರಿಸಲು "
|
||||
"ಸಕ್ರಿಯವಾದವುಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ನಡೆಸುತ್ತದೆ. ಈ ದತ್ತಾಂಶವನ್ನು ಗೌಪ್ಯವಾಗಿ "
|
||||
"ಇರಿಸಲಾಗುತ್ತದೆ, "
|
||||
"ಹಾಗೂ ಗೌಪ್ಯತಾ ಕಾರಣಗಳಿದ್ದಲ್ಲಿ ನೀವು ಅದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು. ಹಾಗೆ ಮಾಡುವುದರಿಂದ "
|
||||
"ಉಳಿಸಲಾದ ಯಾವದೆ ದತ್ತಾಂಶವು ತೆಗೆದುಹಾಕಲ್ಪಡುವುದಿಲ್ಲ ಎನ್ನುವುದನ್ನು ನೆನಪಿಡಿ."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
@ -116,64 +126,75 @@ msgid ""
|
||||
"Internally used to store the last IM presence explicitly set by the user. "
|
||||
"The value here is from the TpConnectionPresenceType enumeration."
|
||||
msgstr ""
|
||||
"ಆಂತರಿಕವಾಗಿ ಬಳಕೆದಾರರಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ಹೊಂದಿಸಲಾದ ಕೊನೆಯ IM ಅನ್ನು ಶೇಖರಿಸಿಡಸಲು "
|
||||
"ಬಳಸಲಾಗುತ್ತದೆ. ಇಲ್ಲಿರುವ ಮೌಲ್ಯವು TpConnectionPresenceType ಎನ್ಯೂಮರೇಶನ್ನಿಂದ "
|
||||
"ಬಂದಿರುತ್ತದೆ."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
|
||||
msgid ""
|
||||
"Internally used to store the last session presence status for the user. The "
|
||||
"value here is from the GsmPresenceStatus enumeration."
|
||||
msgstr ""
|
||||
"ಆಂತರಿಕವಾಗಿ ಬಳಕೆದಾರರಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ಹೊಂದಿಸಲಾದ ಕೊನೆಯ ಅಧಿವೇಶನವನ್ನು ಶೇಖರಿಸಿಡಸಲು "
|
||||
"ಬಳಸಲಾಗುತ್ತದೆ. ಇಲ್ಲಿರುವ ಮೌಲ್ಯವು GsmPresenceStatus ಎನ್ಯೂಮರೇಶನ್ನಿಂದ ಬಂದಿರುತ್ತದೆ."
|
||||
|
||||
#: ../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"
|
||||
msgstr "ಕ್ಯಾಲೆಂಡರಿನಲ್ಲಿ ವಾರದ ದಿನವನ್ನು ತೋರಿಸು"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
|
||||
msgid "If true, display the ISO week date in the calendar."
|
||||
msgstr "true ಆದಲ್ಲಿ, ಕ್ಯಾಲೆಂಡರಿನಲ್ಲಿ ISO ವಾರದ ದಿನವನ್ನು ತೋರಿಸುತ್ತದೆ."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
|
||||
msgid "Keybinding to open the application menu"
|
||||
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
|
||||
msgid "Keybinding to open the application menu."
|
||||
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
|
||||
msgid "Keybinding to toggle the visibility of the message tray"
|
||||
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 "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್"
|
||||
msgid "Keybinding to toggle the visibility of the message tray"
|
||||
msgstr "ಸಂದೇಶ ಟ್ರೇಯ ಗೋಚರಿಕೆಯನ್ನು ಹೊರಳಿಸಲು ಕೀಬೈಂಡಿಂಗ್"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
|
||||
#, fuzzy
|
||||
#| msgid "Keybinding to open the application menu."
|
||||
msgid "Keybinding to start/stop the builtin screen recorder."
|
||||
msgstr "ಅನ್ವಯಗಳ ಮೆನುವನ್ನು ತೆರೆಯಬೇಕಿರುವ ಕೀಲಿಬೈಂಡಿಂಗ್."
|
||||
msgid "Keybinding to toggle the visibility of the message tray."
|
||||
msgstr "ಸಂದೇಶ ಟ್ರೇಯ ಗೋಚರಿಕೆಯನ್ನು ಹೊರಳಿಸಲು ಕೀಬೈಂಡಿಂಗ್."
|
||||
|
||||
#: ../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"
|
||||
msgstr "ಯಾವ ಕೀಲಿಮಣೆಯನ್ನು ಬಳಸಬೇಕಿದೆ"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
|
||||
msgid "The type of keyboard to use."
|
||||
msgstr "ಬಳಸಬೇಕಿರುವ ಕೀಲಿಮಣೆಯ ಬಗೆ."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
|
||||
msgid "Framerate used for recording screencasts."
|
||||
msgstr "ಸ್ಕ್ರೀನ್ಕ್ಯಾಸ್ಟುಗಳನ್ನು ರೆಕಾರ್ಡು ಮಾಡಲು ಬಳಸಲಾಗುವ ಫ್ರೇಮ್ದರಗಳು."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
@ -182,11 +203,11 @@ msgstr ""
|
||||
"ರೆಕಾರ್ಡು ಮಾಡಲಾದ "
|
||||
"ಸ್ಕ್ರೀನ್ಕ್ಯಾಸ್ಟಿನ ಫ್ರೇಮ್ದರ. "
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "ಸ್ಕ್ರೀನ್ಕ್ಯಾಸ್ಟ್ ಅನ್ನು ಎನ್ಕೋಡ್ ಮಾಡಲು ಬಳಸಲಾಗುವ gstreamer ಪೈಪ್ಲೈನ್"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
@ -200,12 +221,31 @@ msgid ""
|
||||
"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."
|
||||
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:28
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
|
||||
msgid "File extension used for storing the screencast"
|
||||
msgstr "ಸ್ಕ್ರೀನ್ಕ್ಯಾಸ್ಟುಗಳನ್ನು ಶೇಖರಿಸಿಡಲು ಬಳಸಲಾಗುವ ಕಡತ ವಿಸ್ತರಣೆಗಳು"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
msgid ""
|
||||
"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 "
|
||||
@ -222,7 +262,6 @@ msgid "There was an error loading the preferences dialog for %s:"
|
||||
msgstr "%s ಗಾಗಿ ಆದ್ಯತೆಗಳ ಸಂವಾದವನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ದೋಷ ಉಂಟಾಗಿದೆ:"
|
||||
|
||||
#: ../js/extensionPrefs/main.js:164
|
||||
#| msgid "<b>Extension</b>"
|
||||
msgid "Extension"
|
||||
msgstr "ವಿಸ್ತರಣೆ"
|
||||
|
||||
@ -231,11 +270,11 @@ msgid "Select an extension to configure using the combobox above."
|
||||
msgstr ""
|
||||
"ಮೇಲಿನ ಸಂಯೋಜನಾಚೌಕವನ್ನು ಬಳಸಿಕೊಂಡು ಸಂರಚಿಸಬೇಕಿರುವ ಒಂದು ವಿಸ್ತರಣೆಯನ್ನು ಆರಿಸಿ."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:526
|
||||
#: ../js/gdm/loginDialog.js:529
|
||||
msgid "Session..."
|
||||
msgstr "ಅಧಿವೇಶನ..."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:674
|
||||
#: ../js/gdm/loginDialog.js:680
|
||||
msgctxt "title"
|
||||
msgid "Sign In"
|
||||
msgstr "ಒಳ ಪ್ರವೇಶಿಸಿ"
|
||||
@ -243,55 +282,68 @@ msgstr "ಒಳ ಪ್ರವೇಶಿಸಿ"
|
||||
#. translators: this message is shown below the user list on the
|
||||
#. login screen. It can be activated to reveal an entry for
|
||||
#. manually entering the username.
|
||||
#: ../js/gdm/loginDialog.js:741
|
||||
#: ../js/gdm/loginDialog.js:740
|
||||
msgid "Not listed?"
|
||||
msgstr "ಪಟ್ಟಿಯಲ್ಲಿಲ್ಲವೆ?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:894 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/gdm/loginDialog.js:898 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396
|
||||
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:166
|
||||
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:168
|
||||
msgid "Cancel"
|
||||
msgstr "ರದ್ದು ಮಾಡು"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:899
|
||||
#: ../js/gdm/loginDialog.js:903
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "ಒಳಗೆ ಪ್ರವೇಶಿಸು"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1238
|
||||
#. TTLS and PEAP are actually much more complicated, but this complication
|
||||
#. is not visible here since we only care about phase2 authentication
|
||||
#. (and don't even care of which one)
|
||||
#: ../js/gdm/loginDialog.js:962 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "ಬಳಕೆದಾರ ಹೆಸರು: "
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1269
|
||||
msgid "Login Window"
|
||||
msgstr "ಪ್ರವೇಶದ ಕಿಟಕಿ"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:88 ../js/ui/userMenu.js:658 ../js/ui/userMenu.js:662
|
||||
#: ../js/ui/userMenu.js:773
|
||||
#. Translators: accessible name of the power menu in the login screen
|
||||
#: ../js/gdm/powerMenu.js:35
|
||||
#| 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"
|
||||
msgstr "ಅಮಾನತ್ತಿನಲ್ಲಿಡು"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:93
|
||||
#: ../js/gdm/powerMenu.js:94
|
||||
msgid "Restart"
|
||||
msgstr "ಮರಳಿ ಆರಂಭಿಸು"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:98 ../js/ui/userMenu.js:660 ../js/ui/userMenu.js:662
|
||||
#: ../js/ui/userMenu.js:772
|
||||
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:666 ../js/ui/userMenu.js:668
|
||||
#: ../js/ui/userMenu.js:778
|
||||
msgid "Power Off"
|
||||
msgstr "ಸ್ಥಗಿತಗೊಳಿಸು"
|
||||
|
||||
#: ../js/gdm/util.js:148
|
||||
#| msgid "Authentication Required"
|
||||
#: ../js/gdm/util.js:152
|
||||
msgid "Authentication error"
|
||||
msgstr "ದೃಢೀಕರಣ ದೋಷ"
|
||||
|
||||
#. Translators: this message is shown below the password entry field
|
||||
#. to indicate the user can swipe their finger instead
|
||||
#: ../js/gdm/util.js:265
|
||||
#: ../js/gdm/util.js:269
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(ಅಥವ ನಿಮ್ಮ ಬೆರಳನ್ನು ಉಜ್ಜಿ)"
|
||||
|
||||
#: ../js/gdm/util.js:290
|
||||
#: ../js/gdm/util.js:294
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr ""
|
||||
msgstr "(ಉದಾ., ಬಳಕೆದಾರ ಅಥವ %s)"
|
||||
|
||||
#: ../js/misc/util.js:92
|
||||
msgid "Command not found"
|
||||
@ -325,7 +377,7 @@ msgstr "SETTINGS"
|
||||
msgid "New Window"
|
||||
msgstr "ಹೊಸ ವಿಂಡೊ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:271
|
||||
#: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:290
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "ಎಲ್ಲಾ ಅಚ್ಚುಮೆಚ್ಚಿನವುಗಳನ್ನು ತೆಗೆದುಹಾಕು"
|
||||
|
||||
@ -489,16 +541,16 @@ msgstr "ಈ ವಾರ"
|
||||
msgid "Next week"
|
||||
msgstr "ಮುಂದಿನ ವಾರ"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:278
|
||||
#: ../js/ui/components/autorunManager.js:297
|
||||
msgid "Removable Devices"
|
||||
msgstr "ತೆಗೆದುಹಾಕಬಹುದಾದ ಸಾಧನಗಳು"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:575
|
||||
#: ../js/ui/components/autorunManager.js:594
|
||||
#, c-format
|
||||
msgid "Open with %s"
|
||||
msgstr "%s ನೊಂದಿಗೆ ತೆರೆ"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:601
|
||||
#: ../js/ui/components/autorunManager.js:620
|
||||
msgid "Eject"
|
||||
msgstr "ಹೊರತಳ್ಳು"
|
||||
|
||||
@ -528,14 +580,6 @@ msgstr "ದಾಟುಪದ: "
|
||||
msgid "Key: "
|
||||
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
|
||||
msgid "Identity: "
|
||||
msgstr "ಗುರುತು: "
|
||||
@ -646,7 +690,7 @@ msgstr "ಸಂಪರ್ಕ ದೋಷ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:491
|
||||
msgid "Unmute"
|
||||
msgstr ""
|
||||
msgstr "ಮಾತುಬರಿಸು"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:491
|
||||
msgid "Mute"
|
||||
@ -655,35 +699,35 @@ msgstr "ಮೂಕಗೊಳಿಸು"
|
||||
#. Translators: this is a time format string followed by a date.
|
||||
#. If applicable, replace %X with a strftime format valid for your
|
||||
#. locale, without seconds.
|
||||
#: ../js/ui/components/telepathyClient.js:948
|
||||
#: ../js/ui/components/telepathyClient.js:952
|
||||
#, no-c-format
|
||||
msgid "Sent at <b>%X</b> on <b>%A</b>"
|
||||
msgstr "<b>%A</b> ರಂದು <b>%X</b> ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ"
|
||||
|
||||
#. Translators: this is a time format in the style of "Wednesday, May 25",
|
||||
#. shown when you get a chat message in the same year.
|
||||
#: ../js/ui/components/telepathyClient.js:954
|
||||
#: ../js/ui/components/telepathyClient.js:958
|
||||
#, no-c-format
|
||||
msgid "Sent on <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",
|
||||
#. shown when you get a chat message in a different year.
|
||||
#: ../js/ui/components/telepathyClient.js:959
|
||||
#: ../js/ui/components/telepathyClient.js:963
|
||||
#, no-c-format
|
||||
msgid "Sent on <b>%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
|
||||
#. IM name.
|
||||
#: ../js/ui/components/telepathyClient.js:988
|
||||
#: ../js/ui/components/telepathyClient.js:992
|
||||
#, c-format
|
||||
msgid "%s is now known as %s"
|
||||
msgstr "%s ಈಗ %s ಆಗಿದ್ದಾರೆ"
|
||||
|
||||
#. translators: argument is a room name like
|
||||
#. * room@jabber.org for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1088
|
||||
#: ../js/ui/components/telepathyClient.js:1092
|
||||
#, c-format
|
||||
msgid "Invitation to %s"
|
||||
msgstr "%s ಗಾಗಿನ ಆಹ್ವಾನ"
|
||||
@ -691,42 +735,42 @@ msgstr "%s ಗಾಗಿನ ಆಹ್ವಾನ"
|
||||
#. translators: first argument is the name of a contact and the second
|
||||
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
|
||||
#. * for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1096
|
||||
#: ../js/ui/components/telepathyClient.js:1100
|
||||
#, c-format
|
||||
msgid "%s is inviting you to join %s"
|
||||
msgstr "%s ನಿಮ್ಮನ್ನು %s ಗೆ ಸೇರುವಂತೆ ಆಹ್ವಾನಿಸುತ್ತಿದ್ದಾರೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1098
|
||||
#: ../js/ui/components/telepathyClient.js:1177
|
||||
#: ../js/ui/components/telepathyClient.js:1240
|
||||
#: ../js/ui/components/telepathyClient.js:1102
|
||||
#: ../js/ui/components/telepathyClient.js:1181
|
||||
#: ../js/ui/components/telepathyClient.js:1244
|
||||
msgid "Decline"
|
||||
msgstr "ತಿರಸ್ಕರಿಸು"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1099
|
||||
#: ../js/ui/components/telepathyClient.js:1178
|
||||
#: ../js/ui/components/telepathyClient.js:1241
|
||||
#: ../js/ui/components/telepathyClient.js:1103
|
||||
#: ../js/ui/components/telepathyClient.js:1182
|
||||
#: ../js/ui/components/telepathyClient.js:1245
|
||||
msgid "Accept"
|
||||
msgstr "ಅಂಗೀಕರಿಸು"
|
||||
|
||||
#. translators: argument is a contact name like Alice for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1129
|
||||
#: ../js/ui/components/telepathyClient.js:1133
|
||||
#, c-format
|
||||
msgid "Video call from %s"
|
||||
msgstr "%s ಇಂದ ವೀಡಿಯೊ ಕರೆ ಬಂದಿದೆ"
|
||||
|
||||
#. translators: argument is a contact name like Alice for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1132
|
||||
#: ../js/ui/components/telepathyClient.js:1136
|
||||
#, c-format
|
||||
msgid "Call from %s"
|
||||
msgstr "%s ಇಂದ ಕರೆ ಬಂದಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1137
|
||||
#: ../js/ui/components/telepathyClient.js:1141
|
||||
#: ../js/ui/status/bluetooth.js:346
|
||||
msgid "Reject"
|
||||
msgstr "ತಿರಸ್ಕರಿಸು"
|
||||
|
||||
#. translators: this is a button label (verb), not a noun
|
||||
#: ../js/ui/components/telepathyClient.js:1139
|
||||
#: ../js/ui/components/telepathyClient.js:1143
|
||||
msgid "Answer"
|
||||
msgstr "ಉತ್ತರ"
|
||||
|
||||
@ -735,106 +779,106 @@ msgstr "ಉತ್ತರ"
|
||||
#. * file name. The string will be something
|
||||
#. * like: "Alice is sending you test.ogg"
|
||||
#.
|
||||
#: ../js/ui/components/telepathyClient.js:1171
|
||||
#: ../js/ui/components/telepathyClient.js:1175
|
||||
#, c-format
|
||||
msgid "%s is sending you %s"
|
||||
msgstr "%s ರವರು ನಿಮಗೆ %s ಅನ್ನು ಕಳುಹಿಸುತ್ತಿದ್ದಾರೆ"
|
||||
|
||||
#. To translators: The parameter is the contact's alias
|
||||
#: ../js/ui/components/telepathyClient.js:1206
|
||||
#: ../js/ui/components/telepathyClient.js:1210
|
||||
#, c-format
|
||||
msgid "%s would like permission to see when you are online"
|
||||
msgstr ""
|
||||
"ನೀವು ಯಾವಾಗ ಆನ್ಲೈನ್ನಲ್ಲಿ ಇರುತ್ತೀರಿ ಎಂದು ತಿಳಿಯಲು %s ರವರು ನಿಮ್ಮ ಅನುಮತಿಯನ್ನು "
|
||||
"ಕೋರಿದ್ದಾರೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1298
|
||||
#: ../js/ui/components/telepathyClient.js:1302
|
||||
msgid "Network error"
|
||||
msgstr "ಜಾಲಬಂಧದ ದೋಷ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1300
|
||||
#: ../js/ui/components/telepathyClient.js:1304
|
||||
msgid "Authentication failed"
|
||||
msgstr "ದೃಢೀಕರಣವು ವಿಫಲಗೊಂಡಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1302
|
||||
#: ../js/ui/components/telepathyClient.js:1306
|
||||
msgid "Encryption error"
|
||||
msgstr "ಗೂಢಲಿಪೀಕರಣ ದೋಷ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1304
|
||||
#: ../js/ui/components/telepathyClient.js:1308
|
||||
msgid "Certificate not provided"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1306
|
||||
#: ../js/ui/components/telepathyClient.js:1310
|
||||
msgid "Certificate untrusted"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ನಂಬಲಾಗಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1308
|
||||
#: ../js/ui/components/telepathyClient.js:1312
|
||||
msgid "Certificate expired"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರದ ಕಾಲಾವಧಿ ತೀರಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1310
|
||||
#: ../js/ui/components/telepathyClient.js:1314
|
||||
msgid "Certificate not activated"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರವು ಸಕ್ರಿಯಗೊಂಡಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1312
|
||||
#: ../js/ui/components/telepathyClient.js:1316
|
||||
msgid "Certificate hostname mismatch"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರದ ಅತಿಥೇಯದ ಹೆಸರು ತಾಳೆಯಾಗುತ್ತಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1314
|
||||
#: ../js/ui/components/telepathyClient.js:1318
|
||||
msgid "Certificate fingerprint mismatch"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರದ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ತಾಳೆಯಾಗುತ್ತಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1316
|
||||
#: ../js/ui/components/telepathyClient.js:1320
|
||||
msgid "Certificate self-signed"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರವು ಸ್ವತಃ ಸೈನ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1318
|
||||
#: ../js/ui/components/telepathyClient.js:1322
|
||||
msgid "Status is set to offline"
|
||||
msgstr "ಸ್ಥಿತಿಯನ್ನು ಆಫ್ಲೈನ್ ಎಂದು ಸೂಚಿಸಿದ್ದಾರೆ."
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1320
|
||||
#: ../js/ui/components/telepathyClient.js:1324
|
||||
msgid "Encryption is not available"
|
||||
msgstr "ಗೂಢಲಿಪೀಕರಣ ಲಭ್ಯವಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1322
|
||||
#: ../js/ui/components/telepathyClient.js:1326
|
||||
msgid "Certificate is invalid"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರವು ಅಮಾನ್ಯವಾಗಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1324
|
||||
#: ../js/ui/components/telepathyClient.js:1328
|
||||
msgid "Connection has been refused"
|
||||
msgstr "ಸಂಪರ್ಕವನ್ನು ನಿರಾಕರಿಸಲಾಗಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1326
|
||||
#: ../js/ui/components/telepathyClient.js:1330
|
||||
msgid "Connection can't be established"
|
||||
msgstr "ಸಂಪರ್ಕವನ್ನು ಸಾಧಿಸಲಾಗಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1328
|
||||
#: ../js/ui/components/telepathyClient.js:1332
|
||||
msgid "Connection has been lost"
|
||||
msgstr "ಸಂಪರ್ಕವು ಕಡಿದು ಹೋಗಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1330
|
||||
#: ../js/ui/components/telepathyClient.js:1334
|
||||
msgid "This account is already connected to the server"
|
||||
msgstr "ಈ ಖಾತೆಯು ಈಗಾಗಲೆ ಪರಿಚಾರಕದೊಂದಿಗೆ ಸಂಪರ್ಕ ಜೋಡಿಸಲಾಗಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1332
|
||||
#: ../js/ui/components/telepathyClient.js:1336
|
||||
msgid ""
|
||||
"Connection has been replaced by a new connection using the same resource"
|
||||
msgstr ""
|
||||
"ಒಂದು ಹೊಸ ಸಂಪರ್ಕದಿಂದ ಈ ಸಂಪರ್ಕವನ್ನು ಇದೇ ಸಂಪನ್ಮೂಲವನ್ನು ಬಳಸಿಕೊಂಡು ಬದಲಾಯಿಸಲಾಗಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1334
|
||||
#: ../js/ui/components/telepathyClient.js:1338
|
||||
msgid "The account already exists on the server"
|
||||
msgstr "ಖಾತೆಯು ಈಗಾಗಲೆ ಪರಿಚಾರಕದಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1336
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
msgid "Server is currently too busy to handle the connection"
|
||||
msgstr "ಪರಿಚಾರಕಕ್ಕೆ ಬಿಡುವಿಲ್ಲದ ಕಾರಣ ಸಂಪರ್ಕವನ್ನು ನಿಭಾಯಿಸಲಾಗುತ್ತಿಲ್ಲ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1338
|
||||
#: ../js/ui/components/telepathyClient.js:1342
|
||||
msgid "Certificate has been revoked"
|
||||
msgstr "ಪ್ರಮಾಣಪತ್ರವನ್ನು ಹಿಂದಕ್ಕೆ ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
#: ../js/ui/components/telepathyClient.js:1344
|
||||
msgid ""
|
||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr ""
|
||||
@ -842,7 +886,7 @@ msgstr ""
|
||||
"ಗೂಢಲಿಪೀಕರಣವನ್ನು "
|
||||
"ಹೊಂದಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1342
|
||||
#: ../js/ui/components/telepathyClient.js:1346
|
||||
msgid ""
|
||||
"The length of the server certificate, or the depth of the server certificate "
|
||||
"chain, exceed the limits imposed by the cryptography library"
|
||||
@ -851,31 +895,30 @@ msgstr ""
|
||||
"ಲೈಬ್ರರಿಯಿಂದ "
|
||||
"ನಿಗದಿ ಪಡಿಸಲಾದ ಮಿತಿಗಳನ್ನು ಮೀರಿದೆ."
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1344
|
||||
#: ../js/ui/components/telepathyClient.js:1348
|
||||
msgid "Internal error"
|
||||
msgstr "ಆಂತರಿಕ ತಪ್ಪು"
|
||||
|
||||
#. translators: argument is the account name, like
|
||||
#. * name@jabber.org for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1354
|
||||
#: ../js/ui/components/telepathyClient.js:1358
|
||||
#, c-format
|
||||
msgid "Connection to %s failed"
|
||||
msgstr "%s ಗಾಗಿನ ಸಂಪರ್ಕವು ವಿಫಲಗೊಂಡಿದೆ"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1363
|
||||
#: ../js/ui/components/telepathyClient.js:1367
|
||||
msgid "Reconnect"
|
||||
msgstr "ಮರಳಿ ಸಂಪರ್ಕ ಜೋಡಿಸು"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1364
|
||||
#: ../js/ui/components/telepathyClient.js:1368
|
||||
msgid "Edit account"
|
||||
msgstr "ಖಾತೆಯನ್ನು ಸಂಪಾದಿಸು"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1409
|
||||
#: ../js/ui/components/telepathyClient.js:1413
|
||||
msgid "Unknown reason"
|
||||
msgstr "ಅಜ್ಞಾತ ಕಾರಣ"
|
||||
|
||||
#: ../js/ui/dash.js:245 ../js/ui/dash.js:273
|
||||
#| msgid "Applications"
|
||||
#: ../js/ui/dash.js:254 ../js/ui/dash.js:292
|
||||
msgid "Show Applications"
|
||||
msgstr "ಅನ್ವಯಗಳನ್ನು ತೋರಿಸು"
|
||||
|
||||
@ -883,14 +926,14 @@ msgstr "ಅನ್ವಯಗಳನ್ನು ತೋರಿಸು"
|
||||
msgid "Date and Time Settings"
|
||||
msgstr "ದಿನಾಂಕ ಹಾಗು ಸಮಯದ ಸಿದ್ಧತೆಗಳು"
|
||||
|
||||
#: ../js/ui/dateMenu.js:109
|
||||
#: ../js/ui/dateMenu.js:111
|
||||
msgid "Open Calendar"
|
||||
msgstr "ಕ್ಯಾಲೆಂಡರನ್ನು ತೆರೆ"
|
||||
|
||||
#. Translators: This is the date format to use when the calendar popup is
|
||||
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
||||
#.
|
||||
#: ../js/ui/dateMenu.js:175
|
||||
#: ../js/ui/dateMenu.js:201
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%A %B %e, %Y"
|
||||
|
||||
@ -995,11 +1038,11 @@ msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr ""
|
||||
"'%s' ಅನ್ನು extensions.gnome.org ಇಂದ ಡೌನ್ಲೋಡ್ ಮಾಡಿಕೊಂಡು ಅನುಸ್ಥಾಪಿಸಬೇಕೆ?"
|
||||
|
||||
#: ../js/ui/keyboard.js:327
|
||||
#: ../js/ui/keyboard.js:337
|
||||
msgid "tray"
|
||||
msgstr "ಟ್ರೇ"
|
||||
|
||||
#: ../js/ui/keyboard.js:561 ../js/ui/status/keyboard.js:194
|
||||
#: ../js/ui/keyboard.js:584 ../js/ui/status/keyboard.js:195
|
||||
#: ../js/ui/status/power.js:205
|
||||
msgid "Keyboard"
|
||||
msgstr "ಕೀಲಿಮಣೆ"
|
||||
@ -1052,24 +1095,23 @@ msgstr "ಆಕರವನ್ನು ನೋಡಿ"
|
||||
msgid "Web Page"
|
||||
msgstr "ಜಾಲ ಪುಟ"
|
||||
|
||||
#: ../js/ui/messageTray.js:1080
|
||||
#: ../js/ui/messageTray.js:1084
|
||||
msgid "Open"
|
||||
msgstr "ತೆರೆ"
|
||||
|
||||
#: ../js/ui/messageTray.js:1087
|
||||
#: ../js/ui/messageTray.js:1091
|
||||
msgid "Remove"
|
||||
msgstr "ತೆಗೆದು ಹಾಕು"
|
||||
|
||||
#: ../js/ui/messageTray.js:2052
|
||||
#: ../js/ui/messageTray.js:1531
|
||||
msgid "Message Tray"
|
||||
msgstr ""
|
||||
msgstr "ಸಂದೇಶ ಟ್ರೇ"
|
||||
|
||||
#: ../js/ui/messageTray.js:2508
|
||||
#: ../js/ui/messageTray.js:2543
|
||||
msgid "System Information"
|
||||
msgstr "ವ್ಯವಸ್ಥೆಯ ಮಾಹಿತಿ"
|
||||
|
||||
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:373
|
||||
#| msgid "Unknown"
|
||||
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374
|
||||
msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "ಗೊತ್ತಿಲ್ಲದ"
|
||||
@ -1125,33 +1167,29 @@ msgstr "ದಯವಿಟ್ಟು ಒಂದು ಆಜ್ಞೆಯನ್ನು ನ
|
||||
|
||||
#. Translators: This is a time format for a date in
|
||||
#. long format
|
||||
#: ../js/ui/screenShield.js:79
|
||||
#| msgctxt "calendar heading"
|
||||
#| msgid "%A, %B %d"
|
||||
#: ../js/ui/screenShield.js:81
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%A, %B %d"
|
||||
|
||||
#: ../js/ui/screenShield.js:144
|
||||
#: ../js/ui/screenShield.js:145
|
||||
#, c-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%d ಹೊಸ ಸಂದೇಶ"
|
||||
msgstr[1] "%d ಹೊಸ ಸಂದೇಶಗಳು"
|
||||
|
||||
#: ../js/ui/screenShield.js:146
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Notifications"
|
||||
#: ../js/ui/screenShield.js:147
|
||||
#, c-format
|
||||
msgid "%d new notification"
|
||||
msgid_plural "%d new notifications"
|
||||
msgstr[0] "ಸೂಚನೆಗಳು"
|
||||
msgstr[1] "ಸೂಚನೆಗಳು"
|
||||
msgstr[0] "%d ಹೊಸ ಸೂಚನೆ"
|
||||
msgstr[1] "%d ಹೊಸ ಸೂಚನೆಗಳು"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:275
|
||||
msgid "Searching..."
|
||||
msgstr "ಹುಡುಕಲಾಗುತ್ತಿದೆ..."
|
||||
|
||||
#: ../js/ui/searchDisplay.js:323
|
||||
#| msgid "No matching results."
|
||||
msgid "No results."
|
||||
msgstr "ಯಾವುದೆ ಫಲಿತಾಂಶಗಳಿಲ್ಲ."
|
||||
|
||||
@ -1172,18 +1210,16 @@ msgid "Hide Text"
|
||||
msgstr "ಪಠ್ಯವನ್ನು ಅಡಗಿಸು"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:368
|
||||
#| msgid "Password:"
|
||||
msgid "Password"
|
||||
msgstr "ಗುಪ್ತಪದ"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:389
|
||||
#| msgid "Password:"
|
||||
msgid "Remember Password"
|
||||
msgstr "ಈ ಗುಪ್ತಪದವನ್ನು ನೆನಪಿನಲ್ಲಿಡು"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:169
|
||||
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:171
|
||||
msgid "Unlock"
|
||||
msgstr ""
|
||||
msgstr "ಅನ್ಲಾಕ್ ಮಾಡು"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:39
|
||||
msgid "Accessibility"
|
||||
@ -1299,7 +1335,7 @@ msgstr "ಕೀಲಿಮಣೆ ಸಿದ್ಧತೆಗಳು"
|
||||
msgid "Mouse Settings"
|
||||
msgstr "ಮೌಸ್ನ ಸಿದ್ಧತೆಗಳು"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:269 ../js/ui/status/volume.js:236
|
||||
#: ../js/ui/status/bluetooth.js:269 ../js/ui/status/volume.js:234
|
||||
msgid "Sound Settings"
|
||||
msgstr "ಧ್ವನಿಯ ಸಿದ್ಧತೆಗಳು"
|
||||
|
||||
@ -1332,10 +1368,10 @@ msgid "Device %s wants to pair with this computer"
|
||||
msgstr "%s ಎನ್ನುವ ಸಾಧನದೊಂದಿಗೆ ಸಂಪರ್ಕ ಜೋಡಿಸಲು ಬಯಸುತ್ತಿದೆ"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:379
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
|
||||
msgstr "'%s' ಎನ್ನುವ PIN ಸಾಧನದಲ್ಲಿರುವುದಕ್ಕೆ ತಾಳೆಯಾಗುತ್ತದೆಯೆ ಎಂದು ಖಚಿತಪಡಿಸಿ."
|
||||
msgstr ""
|
||||
"'%06d' ಎಂಬ PIN ಸಾಧನದಲ್ಲಿರುವುದಕ್ಕೆ ತಾಳೆಯಾಗುತ್ತದೆಯೆ ಎಂದು ದಯವಿಟ್ಟು ಖಚಿತಪಡಿಸಿ."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
msgid "Matches"
|
||||
@ -1358,17 +1394,17 @@ msgstr "ದಯವಿಟ್ಟು ಸಾಧನದಲ್ಲಿ ಸೂಚಿಸಿ
|
||||
msgid "OK"
|
||||
msgstr "ಸರಿ"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:227
|
||||
#: ../js/ui/status/keyboard.js:228
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸವನ್ನು ತೋರಿಸು"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:232
|
||||
#: ../js/ui/status/keyboard.js:233
|
||||
msgid "Region and Language Settings"
|
||||
msgstr "ಪ್ರದೇಶ ಮತ್ತು ಭಾಷೆ ಸಿದ್ಧತೆಗಳು"
|
||||
|
||||
#: ../js/ui/status/lockScreenMenu.js:18
|
||||
msgid "Volume, network, battery"
|
||||
msgstr ""
|
||||
msgstr "ಧ್ವನಿಪ್ರಮಾಣ, ಜಾಲಬಂಧ, ಬ್ಯಾಟರಿ"
|
||||
|
||||
#: ../js/ui/status/network.js:94
|
||||
msgid "<unknown>"
|
||||
@ -1580,13 +1616,12 @@ msgid "Computer"
|
||||
msgstr "ಗಣಕ"
|
||||
|
||||
#: ../js/ui/status/power.js:217
|
||||
#| msgid "Unknown"
|
||||
msgctxt "device"
|
||||
msgid "Unknown"
|
||||
msgstr "ಗೊತ್ತಿಲ್ಲದ"
|
||||
|
||||
#. Translators: This is the label for audio volume
|
||||
#: ../js/ui/status/volume.js:47 ../js/ui/status/volume.js:223
|
||||
#: ../js/ui/status/volume.js:47 ../js/ui/status/volume.js:221
|
||||
msgid "Volume"
|
||||
msgstr "ಧ್ವನಿ ಪ್ರಮಾಣ"
|
||||
|
||||
@ -1594,75 +1629,71 @@ msgstr "ಧ್ವನಿ ಪ್ರಮಾಣ"
|
||||
msgid "Microphone"
|
||||
msgstr "ಮೈಕ್ರೊಫೋನ್"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:176
|
||||
#: ../js/ui/unlockDialog.js:178
|
||||
msgid "Log in as another user"
|
||||
msgstr ""
|
||||
msgstr "ಇನ್ನೊಬ್ಬ ಬಳಕೆದಾರನಾಗಿ ಪ್ರವೇಶಿಸಿ"
|
||||
|
||||
#: ../js/ui/userMenu.js:175
|
||||
#: ../js/ui/userMenu.js:181
|
||||
msgid "Available"
|
||||
msgstr "ಲಭ್ಯ"
|
||||
|
||||
#: ../js/ui/userMenu.js:178
|
||||
#: ../js/ui/userMenu.js:184
|
||||
msgid "Busy"
|
||||
msgstr "ಕಾರ್ಯನಿರತ"
|
||||
|
||||
#: ../js/ui/userMenu.js:181
|
||||
#: ../js/ui/userMenu.js:187
|
||||
msgid "Invisible"
|
||||
msgstr "ಅಗೋಚರ"
|
||||
|
||||
#: ../js/ui/userMenu.js:184
|
||||
#: ../js/ui/userMenu.js:190
|
||||
msgid "Away"
|
||||
msgstr "ಹೊರಗೆ ಹೋಗಿದ್ದೇನೆ"
|
||||
|
||||
#: ../js/ui/userMenu.js:187
|
||||
#: ../js/ui/userMenu.js:193
|
||||
msgid "Idle"
|
||||
msgstr "ಜಡ"
|
||||
|
||||
#: ../js/ui/userMenu.js:190
|
||||
#: ../js/ui/userMenu.js:196
|
||||
msgid "Unavailable"
|
||||
msgstr "ಅಲಭ್ಯ"
|
||||
|
||||
#: ../js/ui/userMenu.js:613 ../js/ui/userMenu.js:754
|
||||
msgid "Switch User"
|
||||
msgstr "ಬಳಕೆದಾರನನ್ನು ಬದಲಿಸು"
|
||||
|
||||
#: ../js/ui/userMenu.js:614
|
||||
#, fuzzy
|
||||
#| msgid "Switch User"
|
||||
msgid "Switch Session"
|
||||
msgstr "ಬಳಕೆದಾರನನ್ನು ಬದಲಿಸು"
|
||||
|
||||
#: ../js/ui/userMenu.js:738
|
||||
#: ../js/ui/userMenu.js:744
|
||||
msgid "Notifications"
|
||||
msgstr "ಸೂಚನೆಗಳು"
|
||||
|
||||
#: ../js/ui/userMenu.js:746
|
||||
#: ../js/ui/userMenu.js:752
|
||||
msgid "System Settings"
|
||||
msgstr "ವ್ಯವಸ್ಥೆಯ ಸಿದ್ಧತೆಗಳು"
|
||||
|
||||
#: ../js/ui/userMenu.js:759
|
||||
#| msgctxt "title"
|
||||
#| msgid "Log Out"
|
||||
#: ../js/ui/userMenu.js:760
|
||||
msgid "Switch User"
|
||||
msgstr "ಬಳಕೆದಾರನನ್ನು ಬದಲಿಸು"
|
||||
|
||||
#: ../js/ui/userMenu.js:765
|
||||
msgid "Log Out"
|
||||
msgstr "ನಿರ್ಗಮಿಸು"
|
||||
|
||||
#: ../js/ui/userMenu.js:764
|
||||
#: ../js/ui/userMenu.js:770
|
||||
msgid "Lock"
|
||||
msgstr ""
|
||||
msgstr "ಲಾಕ್ ಮಾಡು"
|
||||
|
||||
#: ../js/ui/userMenu.js:779
|
||||
#: ../js/ui/userMenu.js:785
|
||||
msgid "Install Updates & Restart"
|
||||
msgstr ""
|
||||
msgstr "ಅಪ್ಡೇಟ್ಗಳನ್ನು ಅನುಸ್ಥಾಪಿಸು ಮತ್ತು ಮರಳಿಸ್ಥಾಪಿಸು"
|
||||
|
||||
#: ../js/ui/userMenu.js:797
|
||||
#: ../js/ui/userMenu.js:803
|
||||
msgid "Your chat status will be set to busy"
|
||||
msgstr "ನಿಮ್ಮ ಹರಟೆಯ ಸ್ಥಿತಿಯನ್ನು ಕಾರ್ಯನಿರತರಾಗಿದ್ದಾರೆ ಎಂದು ಬದಲಾಯಿಸಲಾಗಿದೆ."
|
||||
|
||||
#: ../js/ui/userMenu.js:798
|
||||
#: ../js/ui/userMenu.js:804
|
||||
msgid ""
|
||||
"Notifications are now disabled, including chat messages. Your online status "
|
||||
"has been adjusted to let others know that you might not see their messages."
|
||||
msgstr ""
|
||||
"ಸಂಭಾಷಣೆಯ ಸಂದೇಶಗಳೂ ಸಹ ಸೇರಿದಂತೆ ಸೂಚನೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿರುತ್ತದೆ. ನೀವು "
|
||||
"ಬೇರೆಯವರಿಂದ ಬಂದ ಸಂದೇಶಗಳನ್ನು ನೀವು ನೋಡಿಲ್ಲ ಎಂದು ಅವರಿಗೆ ಗೊತ್ತಾಗುವಂತೆ ನಿಮ್ಮ "
|
||||
"ಆನ್ಲೈನ್ "
|
||||
"ಸ್ಥಿತಿಯನ್ನು ಹೊಂದಿಸಲಾಗಿರುತ್ತದೆ."
|
||||
|
||||
#: ../js/ui/viewSelector.js:85
|
||||
msgid "Windows"
|
||||
@ -1676,7 +1707,7 @@ msgstr "ಅನ್ವಯಗಳು"
|
||||
msgid "Search"
|
||||
msgstr "ಹುಡುಕು"
|
||||
|
||||
#: ../js/ui/wanda.js:119
|
||||
#: ../js/ui/wanda.js:117
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Sorry, no wisdom for you today:\n"
|
||||
@ -1685,12 +1716,12 @@ msgstr ""
|
||||
"ಕ್ಷಮಿಸಿ, ನಿಮಗಾಗಿ ಯಾವುದೆ ವಿವೇಕವಾಣಿ ಇಲ್ಲ :\n"
|
||||
"%s"
|
||||
|
||||
#: ../js/ui/wanda.js:123
|
||||
#: ../js/ui/wanda.js:121
|
||||
#, c-format
|
||||
msgid "%s the Oracle says"
|
||||
msgstr "%s Oracle ಹೇಳುವಂತೆ"
|
||||
|
||||
#: ../js/ui/wanda.js:164
|
||||
#: ../js/ui/wanda.js:162
|
||||
msgid "Your favorite Easter Egg"
|
||||
msgstr "ನಿಮ್ಮ ಮೆಚ್ಚಿನ ಈಸ್ಟರ್ ಮೊಟ್ಟೆ"
|
||||
|
||||
@ -1700,7 +1731,6 @@ msgid "'%s' is ready"
|
||||
msgstr "'%s' ಸಿದ್ಧಗೊಂಡಿದೆ"
|
||||
|
||||
#: ../src/calendar-server/evolution-calendar.desktop.in.in.h:1
|
||||
#| msgid "Open Calendar"
|
||||
msgid "Evolution Calendar"
|
||||
msgstr "Evolution ಕ್ಯಾಲೆಂಡರ್"
|
||||
|
||||
@ -1726,23 +1756,23 @@ msgstr[1] "%u ಇನ್ಪುಟ್ಗಳು"
|
||||
msgid "System Sounds"
|
||||
msgstr "ವ್ಯವಸ್ಥೆಯ ಧ್ವನಿಗಳು"
|
||||
|
||||
#: ../src/main.c:330
|
||||
#: ../src/main.c:332
|
||||
msgid "Print version"
|
||||
msgstr "ಮುದ್ರಿಸಬಹುದಾದ ಆವೃತ್ತಿ"
|
||||
|
||||
#: ../src/main.c:336
|
||||
#: ../src/main.c:338
|
||||
msgid "Mode used by GDM for login screen"
|
||||
msgstr "ಪ್ರವೇಶದ ತೆರೆಗಾಗಿ GDM ಬಳಸಿದ ಪ್ರಕಾರ"
|
||||
|
||||
#: ../src/main.c:342
|
||||
#: ../src/main.c:344
|
||||
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
|
||||
msgstr ""
|
||||
msgstr "ನಿಶ್ಚಿತ ಸ್ಥಿತಿಯನ್ನು ಬಳಸು, ಉದಾ. ಪ್ರವೇಶ ತೆರೆಗಾಗಿ \"gdm\""
|
||||
|
||||
#: ../src/main.c:348
|
||||
#: ../src/main.c:350
|
||||
msgid "List possible modes"
|
||||
msgstr ""
|
||||
msgstr "ಸಾಧ್ಯವಿರುವ ಸ್ಥಿತಿಗಳನ್ನು ಪಟ್ಟಿ ಮಾಡು"
|
||||
|
||||
#: ../src/shell-app.c:621
|
||||
#: ../src/shell-app.c:622
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "'%s' ಅನ್ನು ಆರಂಭಿಸುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ"
|
||||
@ -1767,6 +1797,10 @@ msgstr "ಪೂರ್ವನಿಯೋಜಿತ"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "ದೃಢೀಕರಣದ ಸಂವಾದವನ್ನು ಬಳಕೆದಾರರಿಂದ ತಿರಸ್ಕರಿಸಲಾಗಿದೆ"
|
||||
|
||||
#~| msgid "Switch User"
|
||||
#~ msgid "Switch Session"
|
||||
#~ msgstr "ಅಧಿವೇಶನವನ್ನು ಬದಲಿಸು"
|
||||
|
||||
#~ msgid "disabled OpenSearch providers"
|
||||
#~ msgstr "ಅಶಕ್ತಗೊಳಿಸಲಾದ OpenSearch ಒದಗಿಸುವವರು"
|
||||
|
||||
|
111
po/ml.po
111
po/ml.po
@ -11,15 +11,15 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
|
||||
"cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2012-09-20 16:11+0000\n"
|
||||
"PO-Revision-Date: 2012-09-20 22:56+0000\n"
|
||||
"Last-Translator: Ani Peter <apeter@redhat.com>\n"
|
||||
"PO-Revision-Date: 2012-11-26 15:02+0530\n"
|
||||
"Last-Translator: Ani Peter <peter.ani@gmail.com>\n"
|
||||
"Language-Team: Malayalam <discuss@lists.smc.org.in>\n"
|
||||
"Language: ml\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 1.0\n"
|
||||
"X-Generator: Lokalize 1.5\n"
|
||||
"X-DamnedLies-Scope: partial\n"
|
||||
|
||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
|
||||
@ -61,7 +61,8 @@ msgstr "ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷ
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1
|
||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
|
||||
msgstr ""
|
||||
"Alt-F2-ല് ഡവലപ്പര്മാര്ക്കും ടെസ്റ്റേര്സിനും പ്രയോജനകരമായ ആന്തരിക പ്രയോഗങ്ങള് പ്രവര്ത്തന "
|
||||
"Alt-F2-ല് ഡവലപ്പര്മാര്ക്കും ടെസ്റ്റേര്സിനും പ്രയോജനകരമായ ആന്തരിക "
|
||||
"പ്രയോഗങ്ങള് പ്രവര്ത്തന "
|
||||
"സജ്ജമാക്കുന്നു"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:2
|
||||
@ -69,7 +70,8 @@ msgid ""
|
||||
"Allows access to internal debugging and monitoring tools using the Alt-F2 "
|
||||
"dialog."
|
||||
msgstr ""
|
||||
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും പ്രവേശനം "
|
||||
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും "
|
||||
"പ്രവേശനം "
|
||||
"അനുവദിയ്ക്കുക."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:3
|
||||
@ -83,14 +85,19 @@ msgid ""
|
||||
"list. You can also manipulate this list with the EnableExtension and "
|
||||
"DisableExtension DBus methods on org.gnome.Shell."
|
||||
msgstr ""
|
||||
"ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷനുകള്ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട എക്സ്റ്റെന്ഷനുകള് ഈ കീ പട്ടിക "
|
||||
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്ഷനും ഈ പട്ടികയിലുണ്ടാവണം. org.gnome.Shell-ല് "
|
||||
"നിങ്ങള്ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ പട്ടിക "
|
||||
"ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷനുകള്ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട "
|
||||
"എക്സ്റ്റെന്ഷനുകള് ഈ കീ പട്ടിക "
|
||||
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്ഷനും ഈ പട്ടികയിലുണ്ടാവണം. "
|
||||
"org.gnome.Shell-ല് "
|
||||
"നിങ്ങള്ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ "
|
||||
"പട്ടിക "
|
||||
"കൈകാര്യം ചെയ്യുവാനും സാധിയ്ക്കുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr "പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള് ശേഖരിയ്ക്കണമോ എന്നു്"
|
||||
msgstr ""
|
||||
"പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള് ശേഖരിയ്ക്കണമോ "
|
||||
"എന്നു്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:6
|
||||
msgid ""
|
||||
@ -99,9 +106,12 @@ msgid ""
|
||||
"want to disable this for privacy reasons. Please note that doing so won't "
|
||||
"remove already saved data."
|
||||
msgstr ""
|
||||
"ഏറ്റവും കൂടുതല് തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള് ലഭ്യമാക്കുന്നതിനായി ഷെല് സാധാരണയായി സജീവമായ "
|
||||
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്സ്). ഈ ഡേറ്റാ സ്വകാര്യമായി "
|
||||
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല് ഇതു് പ്രവര്ത്തന രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
|
||||
"ഏറ്റവും കൂടുതല് തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള് ലഭ്യമാക്കുന്നതിനായി ഷെല് "
|
||||
"സാധാരണയായി സജീവമായ "
|
||||
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്സ്). ഈ ഡേറ്റാ "
|
||||
"സ്വകാര്യമായി "
|
||||
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല് ഇതു് പ്രവര്ത്തന "
|
||||
"രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
|
||||
"നിങ്ങള് സൂക്ഷിച്ച ഡേറ്റയെ ബാധിയ്ക്കുന്നതല്ല."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7
|
||||
@ -112,7 +122,8 @@ msgstr "ഇഷ്ടമുള്ള പ്രയോഗങ്ങള്ക്
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr "ഈ ഐഡന്റിഫയറുകള്ക്കുള്ള പ്രയോഗങ്ങള് ഉചിതമായ സ്ഥലങ്ങളില് കാണിയ്ക്കുന്നു."
|
||||
msgstr ""
|
||||
"ഈ ഐഡന്റിഫയറുകള്ക്കുള്ള പ്രയോഗങ്ങള് ഉചിതമായ സ്ഥലങ്ങളില് കാണിയ്ക്കുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9
|
||||
msgid "History for command (Alt-F2) dialog"
|
||||
@ -127,7 +138,8 @@ msgid ""
|
||||
"Internally used to store the last IM presence explicitly set by the user. "
|
||||
"The value here is from the TpConnectionPresenceType enumeration."
|
||||
msgstr ""
|
||||
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
|
||||
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
|
||||
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
|
||||
"TpConnectionPresenceType തരത്തിലുള്ളതാകുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
|
||||
@ -135,7 +147,8 @@ msgid ""
|
||||
"Internally used to store the last session presence status for the user. The "
|
||||
"value here is from the GsmPresenceStatus enumeration."
|
||||
msgstr ""
|
||||
"ഉപയോക്താവിനുള്ള അവസാന സെഷന് അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
|
||||
"ഉപയോക്താവിനുള്ള അവസാന സെഷന് അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
|
||||
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
|
||||
"GsmPresenceStatus തരത്തിലുള്ളതാകുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
|
||||
@ -168,7 +181,9 @@ msgstr "സ്ക്രീന് റിക്കോര്ഡര് ട
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
|
||||
msgid "Keybinding to start/stop the builtin screen recorder."
|
||||
msgstr "ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള കീക്കൂട്ടം."
|
||||
msgstr ""
|
||||
"ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള "
|
||||
"കീക്കൂട്ടം."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
|
||||
msgid "Which keyboard to use"
|
||||
@ -187,7 +202,8 @@ msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
msgstr ""
|
||||
"ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്കാസ്റ്റ് റിക്കോര്ഡര് റീക്കോര്ഡ് ചെയ്തിട്ടുള്ള സ്ക്രീന്കാസ്റ്റിന്റെ "
|
||||
"ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്കാസ്റ്റ് റിക്കോര്ഡര് റീക്കോര്ഡ് ചെയ്തിട്ടുള്ള "
|
||||
"സ്ക്രീന്കാസ്റ്റിന്റെ "
|
||||
"ഫ്രെയിംറേറ്റ്, ഒരു സെക്കന്ഡില് ഒരു ഫ്രെയിം."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
|
||||
@ -219,9 +235,12 @@ msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
"റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് ഉപയോഗിയ്ക്കുന്നു. "
|
||||
"gst-launch-നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് കാലിയാകുന്നു."
|
||||
"ഇതു് നിലവില് 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 "
|
||||
"റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് "
|
||||
"ഉപയോഗിയ്ക്കുന്നു. "
|
||||
"gst-launch-നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് "
|
||||
"കാലിയാകുന്നു."
|
||||
"ഇതു് നിലവില് 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 "
|
||||
"deadline=1000000 "
|
||||
"threads=%T ! queue ! webmmux' ആകുന്നുസ WEBM VP8 കോഡ് ഉപയോഗിച്ചു് റിക്കോര്ഡ് "
|
||||
"ചെയ്യുന്നു."
|
||||
|
||||
@ -235,8 +254,10 @@ msgid ""
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
"a different container format."
|
||||
msgstr ""
|
||||
"റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, എക്സ്റ്റെന്ഷന് എന്നിവ "
|
||||
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് മാറ്റണം."
|
||||
"റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, "
|
||||
"എക്സ്റ്റെന്ഷന് എന്നിവ "
|
||||
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് "
|
||||
"മാറ്റണം."
|
||||
|
||||
#: ../js/extensionPrefs/main.js:124
|
||||
#, c-format
|
||||
@ -249,7 +270,9 @@ msgstr "എക്സ്റ്റെന്ഷന്"
|
||||
|
||||
#: ../js/extensionPrefs/main.js:188
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക."
|
||||
msgstr ""
|
||||
"മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു "
|
||||
"എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:526
|
||||
msgid "Session..."
|
||||
@ -578,7 +601,8 @@ msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
"'%s'."
|
||||
msgstr ""
|
||||
"വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് "
|
||||
"വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് "
|
||||
"അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് "
|
||||
"ആവശ്യമുണ്ടു്."
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:314
|
||||
@ -764,7 +788,8 @@ msgstr "%s നിങ്ങള്ക്കു് %s അയച്ചിരി
|
||||
#: ../js/ui/components/telepathyClient.js:1206
|
||||
#, c-format
|
||||
msgid "%s would like permission to see when you are online"
|
||||
msgstr "നിങ്ങള് ഓണ്ലൈന് ആകുമ്പോള് കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
|
||||
msgstr ""
|
||||
"നിങ്ങള് ഓണ്ലൈന് ആകുമ്പോള് കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1298
|
||||
msgid "Network error"
|
||||
@ -835,8 +860,11 @@ msgid "This account is already connected to the server"
|
||||
msgstr "ഈ അക്കൌണ്ട് നിലവില് സര്വറിലേക്കു് കണക്ട് ചെയ്തിരിയ്ക്കുന്നു"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1332
|
||||
msgid "Connection has been replaced by a new connection using the same resource"
|
||||
msgstr "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
|
||||
msgid ""
|
||||
"Connection has been replaced by a new connection using the same resource"
|
||||
msgstr ""
|
||||
"അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് "
|
||||
"മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1334
|
||||
msgid "The account already exists on the server"
|
||||
@ -851,15 +879,19 @@ msgid "Certificate has been revoked"
|
||||
msgstr "സമ്മതപത്രം വീണ്ടും ആവശ്യപ്പെട്ടിരിയ്ക്കുന്നു"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
msgid "Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു അല്ലെങ്കില് ഉചിതമല്ല"
|
||||
msgid ""
|
||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr ""
|
||||
"സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു "
|
||||
"അല്ലെങ്കില് ഉചിതമല്ല"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1342
|
||||
msgid ""
|
||||
"The length of the server certificate, or the depth of the server certificate "
|
||||
"chain, exceed the limits imposed by the cryptography library"
|
||||
msgstr ""
|
||||
"സര്വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില് സര്വര് സമ്മതപത്ര ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
|
||||
"സര്വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില് സര്വര് സമ്മതപത്ര "
|
||||
"ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
|
||||
"പരിധിയില് കൂടുന്നു"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1344
|
||||
@ -918,7 +950,8 @@ msgstr "പുറത്ത് കടക്കുക"
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് ചെയ്തു് സിസ്റ്റത്തില് നിന്നും "
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് "
|
||||
"ചെയ്തു് സിസ്റ്റത്തില് നിന്നും "
|
||||
"പുറത്തു് കടക്കുക."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
@ -952,7 +985,8 @@ msgstr "നിര്ത്തുക"
|
||||
#: ../js/ui/endSessionDialog.js:82
|
||||
msgid "Click Power Off to quit these applications and power off the system."
|
||||
msgstr ""
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് ചെയ്തു സിസ്റ്റിന്റെ പവര് "
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് "
|
||||
"ചെയ്തു സിസ്റ്റിന്റെ പവര് "
|
||||
"ഓഫ് ചെയ്യുക."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84
|
||||
@ -983,7 +1017,8 @@ msgstr "പുനരാരംഭിക്കുക"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:99
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr "ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക"
|
||||
msgstr ""
|
||||
"ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:101
|
||||
#, c-format
|
||||
@ -1003,7 +1038,9 @@ msgstr "ഇന്സ്റ്റോള്"
|
||||
#: ../js/ui/extensionDownloader.js:204
|
||||
#, c-format
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "extensions.gnome.org ഇല് നിന്നും '%s' ഡൗണ്ലോട് ചെയ്ത് ഇന്സ്റ്റോള് ചെയ്യേണമോ?"
|
||||
msgstr ""
|
||||
"extensions.gnome.org ഇല് നിന്നും '%s' ഡൗണ്ലോട് ചെയ്ത് ഇന്സ്റ്റോള് "
|
||||
"ചെയ്യേണമോ?"
|
||||
|
||||
#: ../js/ui/keyboard.js:327
|
||||
msgid "tray"
|
||||
@ -1660,8 +1697,10 @@ msgid ""
|
||||
"Notifications are now disabled, including chat messages. Your online status "
|
||||
"has been adjusted to let others know that you might not see their messages."
|
||||
msgstr ""
|
||||
"ചാറ്റ് സന്ദേശങ്ങള് എന്ന പോലെ അറിയിപ്പുകള് പ്രവര്ത്തന രഹിതമാക്കുന്നു. മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള് "
|
||||
"നിങ്ങള്ക്കു് കാണുവാന് സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്ലൈന് അവസ്ഥയില് വ്യക്തമാക്കുന്നു."
|
||||
"ചാറ്റ് സന്ദേശങ്ങള് എന്ന പോലെ അറിയിപ്പുകള് പ്രവര്ത്തന രഹിതമാക്കുന്നു. "
|
||||
"മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള് "
|
||||
"നിങ്ങള്ക്കു് കാണുവാന് സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്ലൈന് അവസ്ഥയില് "
|
||||
"വ്യക്തമാക്കുന്നു."
|
||||
|
||||
#: ../js/ui/viewSelector.js:85
|
||||
msgid "Windows"
|
||||
|
281
po/ru.po
281
po/ru.po
@ -13,18 +13,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2012-10-31 16:48+0000\n"
|
||||
"PO-Revision-Date: 2012-11-04 20:48+0400\n"
|
||||
"PO-Revision-Date: 2012-11-20 11:46+0300\n"
|
||||
"Last-Translator: Yuri Myasoedov <omerta13@yandex.ru>\n"
|
||||
"Language-Team: русский <gnome-cyr@gnome.org>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
|
||||
"X-Generator: Lokalize 1.2\n"
|
||||
|
||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
|
||||
@ -65,55 +63,32 @@ msgid "Enable internal tools useful for developers and testers from Alt-F2"
|
||||
msgstr "Включить внутренние инструменты из Alt-F2 для разработчиков и тестеров"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:2
|
||||
msgid ""
|
||||
"Allows access to internal debugging and monitoring tools using the Alt-F2 "
|
||||
"dialog."
|
||||
msgstr ""
|
||||
"Разрешает доступ к внутренней отладке и инструментам наблюдения, используя "
|
||||
"диалог Alt-F2."
|
||||
msgid "Allows access to internal debugging and monitoring tools using the Alt-F2 dialog."
|
||||
msgstr "Разрешает доступ к внутренней отладке и инструментам наблюдения, используя диалог Alt-F2."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:3
|
||||
msgid "Uuids of extensions to enable"
|
||||
msgstr "Uuid включенных расширений"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:4
|
||||
msgid ""
|
||||
"GNOME Shell extensions have a uuid property; this key lists extensions which "
|
||||
"should be loaded. Any extension that wants to be loaded needs to be in this "
|
||||
"list. You can also manipulate this list with the EnableExtension and "
|
||||
"DisableExtension DBus methods on org.gnome.Shell."
|
||||
msgstr ""
|
||||
"У расширений GNOME Shell есть свойство uuid; в этом ключе перечислены "
|
||||
"расширения, которые должны быть загружены. Этим список также можно управлять "
|
||||
"через методы DBus EnableExtension и DisableExtension сервиса org.gnome.Shell."
|
||||
msgid "GNOME Shell extensions have a uuid property; this key lists extensions which should be loaded. Any extension that wants to be loaded needs to be in this list. You can also manipulate this list with the EnableExtension and DisableExtension DBus methods on org.gnome.Shell."
|
||||
msgstr "У расширений GNOME Shell есть свойство uuid; в этом ключе перечислены расширения, которые должны быть загружены. Этим список также можно управлять через методы DBus EnableExtension и DisableExtension сервиса org.gnome.Shell."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr "Собирать ли статистику об использовании приложений"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:6
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
"used ones (e.g. in launchers). While this data will be kept private, you may "
|
||||
"want to disable this for privacy reasons. Please note that doing so won't "
|
||||
"remove already saved data."
|
||||
msgstr ""
|
||||
"Обычно, оболочка отслеживает активные приложения, чтобы определить наиболее "
|
||||
"используемые приложения. Хотя эти данные хранятся как личные, возможно вы "
|
||||
"захотите отключить эту возможность из соображений безопасности. Это не "
|
||||
"приведёт к удалению уже сохранённых данных."
|
||||
msgid "The shell normally monitors active applications in order to present the most used ones (e.g. in launchers). While this data will be kept private, you may want to disable this for privacy reasons. Please note that doing so won't remove already saved data."
|
||||
msgstr "Обычно, оболочка отслеживает активные приложения, чтобы определить наиболее используемые приложения. Хотя эти данные хранятся как личные, возможно вы захотите отключить эту возможность из соображений безопасности. Это не приведёт к удалению уже сохранённых данных."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr "Список идентификаторов desktop-файлов для избранных приложений"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:8
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr ""
|
||||
"Приложения, соответствующие этих идентификаторам, будут показаны в области "
|
||||
"избранных приложений."
|
||||
msgid "The applications corresponding to these identifiers will be displayed in the favorites area."
|
||||
msgstr "Приложения, соответствующие этих идентификаторам, будут показаны в области избранных приложений."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9
|
||||
msgid "History for command (Alt-F2) dialog"
|
||||
@ -124,33 +99,20 @@ msgid "History for the looking glass dialog"
|
||||
msgstr "История просмотра прозрачного диалога"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:11
|
||||
msgid ""
|
||||
"Internally used to store the last IM presence explicitly set by the user. "
|
||||
"The value here is from the TpConnectionPresenceType enumeration."
|
||||
msgstr ""
|
||||
"Используется для хранения статуса о присутствии, установленного "
|
||||
"пользователем. Данное значение берётся из перечисления "
|
||||
"TpConnectionPresenceType."
|
||||
msgid "Internally used to store the last IM presence explicitly set by the user. The value here is from the TpConnectionPresenceType enumeration."
|
||||
msgstr "Используется для хранения статуса о присутствии, установленного пользователем. Данное значение берётся из перечисления TpConnectionPresenceType."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
|
||||
msgid ""
|
||||
"Internally used to store the last session presence status for the user. The "
|
||||
"value here is from the GsmPresenceStatus enumeration."
|
||||
msgstr ""
|
||||
"Используется для хранения статуса о присутствии для последнего сеанса. "
|
||||
"Данное значение берётся из перечисления GsmPresenceStatus."
|
||||
msgid "Internally used to store the last session presence status for the user. The value here is from the GsmPresenceStatus enumeration."
|
||||
msgstr "Используется для хранения статуса о присутствии для последнего сеанса. Данное значение берётся из перечисления GsmPresenceStatus."
|
||||
|
||||
#: ../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 ""
|
||||
"Этот ключ переопределяет автоматическое скрытие пункта «Завершить сеанс» при "
|
||||
"использовании одиночного сеанса."
|
||||
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"
|
||||
@ -182,8 +144,7 @@ msgstr "Комбинация клавиш для переключения зап
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
|
||||
msgid "Keybinding to start/stop the builtin screen recorder."
|
||||
msgstr ""
|
||||
"Комбинация клавиш для запуска/остановки встроенного средства записи экрана."
|
||||
msgstr "Комбинация клавиш для запуска/остановки встроенного средства записи экрана."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
|
||||
msgid "Which keyboard to use"
|
||||
@ -198,12 +159,8 @@ msgid "Framerate used for recording screencasts."
|
||||
msgstr "Частота смены кадров для записи скринкастов."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
msgstr ""
|
||||
"Частота смены кадров в скринкасте, записанном с помощью GNOME Shell (кадров/"
|
||||
"сек)."
|
||||
msgid "The framerate of the resulting screencast recordered by GNOME Shell's screencast recorder in frames-per-second."
|
||||
msgstr "Частота смены кадров в скринкасте, записанном с помощью GNOME Shell (кадров/сек)."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
@ -211,44 +168,16 @@ msgstr "Конвейер gstreamer, используемый для кодиро
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
"the recorded video is recorded. It will normally have a unconnected source "
|
||||
"pad; output from that pad will be written into the output file. However the "
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 "
|
||||
"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."
|
||||
msgstr ""
|
||||
"Устанавливает конвейер GStreamer для кодирования записей. Соответствует "
|
||||
"синтаксису, используемому для gst-launch. Конвейер должен иметь "
|
||||
"неподключенный входной коннектор, где происходит запись видео. Выход "
|
||||
"коннектора обычно отключён, выход с этого коннектора записывается в файл "
|
||||
"вывода. Однако конвейер также может позаботиться о своём выводе, что можно "
|
||||
"использовать для отправки вывода на сервер icecast через shout2send или "
|
||||
"нечто подобное. При сбросе или установке пустого значения будет "
|
||||
"использоваться конвейер по умолчанию. В данный момент это «vp8enc "
|
||||
"min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! "
|
||||
"queue ! webmmux»; запись выполняется в WEBM с помощью кодека VP8. %T "
|
||||
"используется как заполнитель для определения оптимального количества потоков "
|
||||
"в системе."
|
||||
msgid "Sets the GStreamer pipeline used to encode recordings. It follows the syntax used for gst-launch. The pipeline should have an unconnected sink pad where the recorded video is recorded. It will normally have a unconnected source pad; output from that pad will be written into the output file. However the pipeline can also take care of its own output - this might be used to send the output to an icecast server via shout2send or similar. When unset or set to an empty value, the default pipeline will be used. This is currently 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 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."
|
||||
msgstr "Устанавливает конвейер GStreamer для кодирования записей. Соответствует синтаксису, используемому для gst-launch. Конвейер должен иметь неподключенный входной коннектор, где происходит запись видео. Выход коннектора обычно отключён, выход с этого коннектора записывается в файл вывода. Однако конвейер также может позаботиться о своём выводе, что можно использовать для отправки вывода на сервер icecast через shout2send или нечто подобное. При сбросе или установке пустого значения будет использоваться конвейер по умолчанию. В данный момент это «vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux»; запись выполняется в WEBM с помощью кодека VP8. %T используется как заполнитель для определения оптимального количества потоков в системе."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
|
||||
msgid "File extension used for storing the screencast"
|
||||
msgstr "Расширение файла, использующееся для хранения скринкастов"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
msgid ""
|
||||
"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 "
|
||||
"a different container format."
|
||||
msgstr ""
|
||||
"Имя файла записанного скринкаста будет уникальным именем, основанным на "
|
||||
"текущей дате, и использует это расширение. Оно должно быть изменено, если "
|
||||
"запись выполняется в другой контейнерный формат."
|
||||
msgid "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 a different container format."
|
||||
msgstr "Имя файла записанного скринкаста будет уникальным именем, основанным на текущей дате, и использует это расширение. Оно должно быть изменено, если запись выполняется в другой контейнерный формат."
|
||||
|
||||
#: ../js/extensionPrefs/main.js:124
|
||||
#, c-format
|
||||
@ -279,10 +208,14 @@ msgstr "Вход в систему"
|
||||
msgid "Not listed?"
|
||||
msgstr "Нет в списке?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:889 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396
|
||||
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:167
|
||||
#: ../js/gdm/loginDialog.js:889
|
||||
#: ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162
|
||||
#: ../js/ui/endSessionDialog.js:373
|
||||
#: ../js/ui/extensionDownloader.js:195
|
||||
#: ../js/ui/shellMountOperation.js:396
|
||||
#: ../js/ui/status/bluetooth.js:427
|
||||
#: ../js/ui/unlockDialog.js:167
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
@ -300,7 +233,9 @@ msgstr "Окно входа в систему"
|
||||
msgid "Power"
|
||||
msgstr "Питание"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:664 ../js/ui/userMenu.js:668
|
||||
#: ../js/gdm/powerMenu.js:89
|
||||
#: ../js/ui/userMenu.js:664
|
||||
#: ../js/ui/userMenu.js:668
|
||||
#: ../js/ui/userMenu.js:779
|
||||
msgid "Suspend"
|
||||
msgstr "Ждущий режим"
|
||||
@ -309,7 +244,9 @@ msgstr "Ждущий режим"
|
||||
msgid "Restart"
|
||||
msgstr "Перезапустить"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:666 ../js/ui/userMenu.js:668
|
||||
#: ../js/gdm/powerMenu.js:99
|
||||
#: ../js/ui/userMenu.js:666
|
||||
#: ../js/ui/userMenu.js:668
|
||||
#: ../js/ui/userMenu.js:778
|
||||
msgid "Power Off"
|
||||
msgstr "Выключить"
|
||||
@ -355,13 +292,14 @@ msgstr "ПРИЛОЖЕНИЯ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:370
|
||||
msgid "SETTINGS"
|
||||
msgstr "НАСТРОЙКИ"
|
||||
msgstr "ПАРАМЕТРЫ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:675
|
||||
msgid "New Window"
|
||||
msgstr "Новое окно"
|
||||
|
||||
#: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:290
|
||||
#: ../js/ui/appDisplay.js:678
|
||||
#: ../js/ui/dash.js:290
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Удалить из избранного"
|
||||
|
||||
@ -538,7 +476,8 @@ msgstr "Открыть с помощью %s"
|
||||
msgid "Eject"
|
||||
msgstr "Извлечь"
|
||||
|
||||
#: ../js/ui/components/keyring.js:86 ../js/ui/components/polkitAgent.js:260
|
||||
#: ../js/ui/components/keyring.js:86
|
||||
#: ../js/ui/components/polkitAgent.js:260
|
||||
msgid "Password:"
|
||||
msgstr "Пароль:"
|
||||
|
||||
@ -590,11 +529,8 @@ msgstr "Беспроводная сеть требует подтвержден
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:310
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
"'%s'."
|
||||
msgstr ""
|
||||
"Для доступа к беспроводной сети «%s» требуются пароли или ключи шифрования."
|
||||
msgid "Passwords or encryption keys are required to access the wireless network '%s'."
|
||||
msgstr "Для доступа к беспроводной сети «%s» требуются пароли или ключи шифрования."
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:314
|
||||
msgid "Wired 802.1X authentication"
|
||||
@ -645,7 +581,8 @@ msgstr "Подтвердить"
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
#: ../js/ui/components/polkitAgent.js:248 ../js/ui/shellMountOperation.js:381
|
||||
#: ../js/ui/components/polkitAgent.js:248
|
||||
#: ../js/ui/shellMountOperation.js:381
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "Извините, это не сработало. Попробуйте снова."
|
||||
|
||||
@ -850,8 +787,7 @@ msgid "This account is already connected to the server"
|
||||
msgstr "Эта учётная запись уже подключена к серверу"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1334
|
||||
msgid ""
|
||||
"Connection has been replaced by a new connection using the same resource"
|
||||
msgid "Connection has been replaced by a new connection using the same resource"
|
||||
msgstr "Соединение было заменено новым, используя тот же источник"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1336
|
||||
@ -860,27 +796,19 @@ msgstr "Учётная запись уже существует на серве
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1338
|
||||
msgid "Server is currently too busy to handle the connection"
|
||||
msgstr ""
|
||||
"Сервер в настоящее время сильно перегружен, чтобы обработать соединение"
|
||||
msgstr "Сервер в настоящее время сильно перегружен, чтобы обработать соединение"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
msgid "Certificate has been revoked"
|
||||
msgstr "Сертификат аннулирован"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1342
|
||||
msgid ""
|
||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr ""
|
||||
"Сертификат использует небезопасный алгоритм шифрования или он "
|
||||
"криптографически нестоек"
|
||||
msgid "Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr "Сертификат использует небезопасный алгоритм шифрования или он криптографически нестоек"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1344
|
||||
msgid ""
|
||||
"The length of the server certificate, or the depth of the server certificate "
|
||||
"chain, exceed the limits imposed by the cryptography library"
|
||||
msgstr ""
|
||||
"Длина сертификата сервера, или глубина цепочки сертификатов сервера, "
|
||||
"превышает пределы, установленные библиотекой криптографии"
|
||||
msgid "The length of the server certificate, or the depth of the server certificate chain, exceed the limits imposed by the cryptography library"
|
||||
msgstr "Длина сертификата сервера, или глубина цепочки сертификатов сервера, превышает пределы, установленные библиотекой криптографии"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1346
|
||||
msgid "Internal error"
|
||||
@ -905,7 +833,8 @@ msgstr "Изменить учётную запись"
|
||||
msgid "Unknown reason"
|
||||
msgstr "Неизвестная причина"
|
||||
|
||||
#: ../js/ui/dash.js:253 ../js/ui/dash.js:292
|
||||
#: ../js/ui/dash.js:253
|
||||
#: ../js/ui/dash.js:292
|
||||
msgid "Show Applications"
|
||||
msgstr "Показать приложения"
|
||||
|
||||
@ -937,17 +866,14 @@ msgstr "Выйти из системы"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"Нажмите «Выйти из системы», чтобы закрыть эти приложения и выйти из системы."
|
||||
msgstr "Нажмите «Выйти из системы», чтобы закрыть эти приложения и выйти из системы."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d second."
|
||||
msgid_plural "%s will be logged out automatically in %d seconds."
|
||||
msgstr[0] ""
|
||||
"Сеанс пользователя %s будет автоматически завершён через %d секунду."
|
||||
msgstr[1] ""
|
||||
"Сеанс пользователя %s будет автоматически завершён через %d секунды."
|
||||
msgstr[0] "Сеанс пользователя %s будет автоматически завершён через %d секунду."
|
||||
msgstr[1] "Сеанс пользователя %s будет автоматически завершён через %d секунды."
|
||||
msgstr[2] "Сеанс пользователя %s будет автоматически завершён через %d секунд."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:70
|
||||
@ -988,7 +914,8 @@ msgstr[2] "Система будет автоматически выключен
|
||||
msgid "Powering off the system."
|
||||
msgstr "Выключение системы."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:90 ../js/ui/endSessionDialog.js:107
|
||||
#: ../js/ui/endSessionDialog.js:90
|
||||
#: ../js/ui/endSessionDialog.js:107
|
||||
msgctxt "button"
|
||||
msgid "Restart"
|
||||
msgstr "Перезапустить"
|
||||
@ -1005,9 +932,7 @@ msgstr "Перезапустить"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:99
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Нажмите «Перезапустить», чтобы закрыть эти приложения и перезапустить "
|
||||
"систему."
|
||||
msgstr "Нажмите «Перезапустить», чтобы закрыть эти приложения и перезапустить систему."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:101
|
||||
#, c-format
|
||||
@ -1034,7 +959,8 @@ msgstr "Загрузить и установить расширение «%s»
|
||||
msgid "tray"
|
||||
msgstr "лоток"
|
||||
|
||||
#: ../js/ui/keyboard.js:584 ../js/ui/status/keyboard.js:195
|
||||
#: ../js/ui/keyboard.js:584
|
||||
#: ../js/ui/status/keyboard.js:195
|
||||
#: ../js/ui/status/power.js:205
|
||||
msgid "Keyboard"
|
||||
msgstr "Клавиатура"
|
||||
@ -1053,7 +979,8 @@ msgstr "%s не сообщал о каких-либо ошибках."
|
||||
msgid "Hide Errors"
|
||||
msgstr "Скрыть ошибки"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:755 ../js/ui/lookingGlass.js:815
|
||||
#: ../js/ui/lookingGlass.js:755
|
||||
#: ../js/ui/lookingGlass.js:815
|
||||
msgid "Show Errors"
|
||||
msgstr "Показать ошибки"
|
||||
|
||||
@ -1063,7 +990,8 @@ msgstr "Включено"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:767 ../src/gvc/gvc-mixer-control.c:1082
|
||||
#: ../js/ui/lookingGlass.js:767
|
||||
#: ../src/gvc/gvc-mixer-control.c:1082
|
||||
msgid "Disabled"
|
||||
msgstr "Выключено"
|
||||
|
||||
@ -1103,7 +1031,8 @@ msgstr "Панель сообщений"
|
||||
msgid "System Information"
|
||||
msgstr "Системная информация"
|
||||
|
||||
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374
|
||||
#: ../js/ui/notificationDaemon.js:506
|
||||
#: ../src/shell-app.c:374
|
||||
msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "Неизвестно"
|
||||
@ -1211,7 +1140,8 @@ msgstr "Пароль"
|
||||
msgid "Remember Password"
|
||||
msgstr "Запомнить пароль"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:170
|
||||
#: ../js/ui/shellMountOperation.js:400
|
||||
#: ../js/ui/unlockDialog.js:170
|
||||
msgid "Unlock"
|
||||
msgstr "Разблокировать"
|
||||
|
||||
@ -1263,10 +1193,14 @@ msgstr "Высокая контрастность"
|
||||
msgid "Large Text"
|
||||
msgstr "Крупный текст"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:27 ../js/ui/status/bluetooth.js:31
|
||||
#: ../js/ui/status/bluetooth.js:251 ../js/ui/status/bluetooth.js:304
|
||||
#: ../js/ui/status/bluetooth.js:335 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:400 ../js/ui/status/network.js:867
|
||||
#: ../js/ui/status/bluetooth.js:27
|
||||
#: ../js/ui/status/bluetooth.js:31
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
#: ../js/ui/status/bluetooth.js:304
|
||||
#: ../js/ui/status/bluetooth.js:335
|
||||
#: ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:400
|
||||
#: ../js/ui/status/network.js:867
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -1287,7 +1221,8 @@ msgid "Bluetooth Settings"
|
||||
msgstr "Настроить Bluetooth"
|
||||
|
||||
#. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill
|
||||
#: ../js/ui/status/bluetooth.js:103 ../js/ui/status/network.js:208
|
||||
#: ../js/ui/status/bluetooth.js:103
|
||||
#: ../js/ui/status/network.js:208
|
||||
msgid "hardware disabled"
|
||||
msgstr "устройство выключено"
|
||||
|
||||
@ -1295,11 +1230,13 @@ msgstr "устройство выключено"
|
||||
msgid "Connection"
|
||||
msgstr "Соединение"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:207 ../js/ui/status/network.js:458
|
||||
#: ../js/ui/status/bluetooth.js:207
|
||||
#: ../js/ui/status/network.js:458
|
||||
msgid "disconnecting..."
|
||||
msgstr "отключение…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:464
|
||||
#: ../js/ui/status/bluetooth.js:220
|
||||
#: ../js/ui/status/network.js:464
|
||||
#: ../js/ui/status/network.js:934
|
||||
msgid "connecting..."
|
||||
msgstr "подключение…"
|
||||
@ -1329,7 +1266,8 @@ msgstr "Настроить клавиатуру"
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Настроить мышь"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:269 ../js/ui/status/volume.js:234
|
||||
#: ../js/ui/status/bluetooth.js:269
|
||||
#: ../js/ui/status/volume.js:234
|
||||
msgid "Sound Settings"
|
||||
msgstr "Настроить звук"
|
||||
|
||||
@ -1356,7 +1294,8 @@ msgstr "Предоставить единовременно"
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Подтверждение на сопряжение с %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:378 ../js/ui/status/bluetooth.js:408
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#: ../js/ui/status/bluetooth.js:408
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "Устройство %s пытается выполнить сопряжение с этим компьютером"
|
||||
@ -1389,11 +1328,11 @@ msgstr "OK"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:228
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "Показывать раскладку клавиатуры"
|
||||
msgstr "Показать раскладку клавиатуры"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:233
|
||||
msgid "Region and Language Settings"
|
||||
msgstr "Региональные и языковые настройки"
|
||||
msgstr "Региональные и языковые параметры"
|
||||
|
||||
#: ../js/ui/status/lockScreenMenu.js:18
|
||||
msgid "Volume, network, battery"
|
||||
@ -1415,7 +1354,8 @@ msgid "unmanaged"
|
||||
msgstr "не управляется"
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
#: ../js/ui/status/network.js:467 ../js/ui/status/network.js:937
|
||||
#: ../js/ui/status/network.js:467
|
||||
#: ../js/ui/status/network.js:937
|
||||
msgid "authentication required"
|
||||
msgstr "требуется подтверждение подлинности"
|
||||
|
||||
@ -1436,17 +1376,20 @@ msgstr "кабель не подключен"
|
||||
msgid "unavailable"
|
||||
msgstr "недоступное"
|
||||
|
||||
#: ../js/ui/status/network.js:491 ../js/ui/status/network.js:939
|
||||
#: ../js/ui/status/network.js:491
|
||||
#: ../js/ui/status/network.js:939
|
||||
msgid "connection failed"
|
||||
msgstr "сбой подключения"
|
||||
|
||||
#: ../js/ui/status/network.js:552 ../js/ui/status/network.js:1529
|
||||
#: ../js/ui/status/network.js:552
|
||||
#: ../js/ui/status/network.js:1529
|
||||
msgid "More..."
|
||||
msgstr "Ещё…"
|
||||
|
||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
|
||||
#. and we cannot access its settings (including the name)
|
||||
#: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1459
|
||||
#: ../js/ui/status/network.js:588
|
||||
#: ../js/ui/status/network.js:1459
|
||||
msgid "Connected (private)"
|
||||
msgstr "Подключено (частное)"
|
||||
|
||||
@ -1463,7 +1406,8 @@ msgid "Auto dial-up"
|
||||
msgstr "Автоматическое коммутируемое"
|
||||
|
||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
|
||||
#: ../js/ui/status/network.js:853 ../js/ui/status/network.js:1476
|
||||
#: ../js/ui/status/network.js:853
|
||||
#: ../js/ui/status/network.js:1476
|
||||
#, c-format
|
||||
msgid "Auto %s"
|
||||
msgstr "Автоматическое %s"
|
||||
@ -1566,7 +1510,8 @@ msgstr[0] "Осталась %d минута"
|
||||
msgstr[1] "Осталось %d минуты"
|
||||
msgstr[2] "Осталось %d минут"
|
||||
|
||||
#: ../js/ui/status/power.js:112 ../js/ui/status/power.js:186
|
||||
#: ../js/ui/status/power.js:112
|
||||
#: ../js/ui/status/power.js:186
|
||||
#, c-format
|
||||
msgctxt "percent of battery remaining"
|
||||
msgid "%d%%"
|
||||
@ -1618,7 +1563,8 @@ msgid "Unknown"
|
||||
msgstr "Неизвестно"
|
||||
|
||||
#. 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:221
|
||||
msgid "Volume"
|
||||
msgstr "Громкость"
|
||||
|
||||
@ -1683,12 +1629,8 @@ msgid "Your chat status will be set to busy"
|
||||
msgstr "Будет установлен статус «не беспокоить»"
|
||||
|
||||
#: ../js/ui/userMenu.js:804
|
||||
msgid ""
|
||||
"Notifications are now disabled, including chat messages. Your online status "
|
||||
"has been adjusted to let others know that you might not see their messages."
|
||||
msgstr ""
|
||||
"Уведомления отключены, включая сообщения в чате. Ваш статус доступности "
|
||||
"изменён, чтобы другие знали, что вы возможно не видите их сообщения."
|
||||
msgid "Notifications are now disabled, including chat messages. Your online status has been adjusted to let others know that you might not see their messages."
|
||||
msgstr "Уведомления отключены, включая сообщения в чате. Ваш статус доступности изменён, чтобы другие знали, что вы возможно не видите их сообщения."
|
||||
|
||||
#: ../js/ui/viewSelector.js:85
|
||||
msgid "Windows"
|
||||
@ -1735,9 +1677,9 @@ msgstr "Календарь Evolution"
|
||||
#, c-format
|
||||
msgid "%u Output"
|
||||
msgid_plural "%u Outputs"
|
||||
msgstr[0] "%u вывод"
|
||||
msgstr[1] "%u вывода"
|
||||
msgstr[2] "%u выводов"
|
||||
msgstr[0] "%u выход"
|
||||
msgstr[1] "%u выхода"
|
||||
msgstr[2] "%u выходов"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound inputs on a particular device
|
||||
@ -1763,8 +1705,7 @@ msgstr "Режим, используемый GDM для окна входа в
|
||||
|
||||
#: ../src/main.c:344
|
||||
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
|
||||
msgstr ""
|
||||
"Использовать для экрана входа в систему определённый режим, например «gdm»"
|
||||
msgstr "Использовать для экрана входа в систему определённый режим, например «gdm»"
|
||||
|
||||
#: ../src/main.c:350
|
||||
msgid "List possible modes"
|
||||
|
@ -1,52 +0,0 @@
|
||||
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
|
@ -87,6 +87,21 @@ stamp-st.h: Makefile
|
||||
BUILT_SOURCES += 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/st-private.h \
|
||||
st/st-table-private.h \
|
||||
|
@ -8,6 +8,8 @@ noinst_LTLIBRARIES =
|
||||
noinst_PROGRAMS =
|
||||
service_in_files =
|
||||
|
||||
SUBDIRS = gvc
|
||||
|
||||
-include $(INTROSPECTION_MAKEFILE)
|
||||
INTROSPECTION_GIRS =
|
||||
INTROSPECTION_SCANNER_ARGS = --warn-all --warn-error --add-include-path=$(srcdir)
|
||||
@ -79,7 +81,6 @@ CLEANFILES += gnome-shell $(bin_SCRIPTS)
|
||||
|
||||
include Makefile-st.am
|
||||
include Makefile-tray.am
|
||||
include Makefile-gvc.am
|
||||
include Makefile-calendar-server.am
|
||||
include Makefile-hotplug-sniffer.am
|
||||
|
||||
@ -284,7 +285,7 @@ libgnome_shell_la_LIBADD = \
|
||||
$(BLUETOOTH_LIBS) \
|
||||
libst-1.0.la \
|
||||
libtray.la \
|
||||
libgvc.la \
|
||||
gvc/libgvc.la \
|
||||
$(NULL)
|
||||
|
||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||
|
39
src/data-to-c.pl
Executable file
39
src/data-to-c.pl
Executable file
@ -0,0 +1,39 @@
|
||||
#!/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);
|
@ -93,6 +93,7 @@ def start_shell():
|
||||
args.append('--replace')
|
||||
if options.sync:
|
||||
args.append('--sync')
|
||||
args += params
|
||||
return subprocess.Popen(args, env=env)
|
||||
|
||||
def run_shell():
|
||||
@ -156,11 +157,7 @@ parser.add_option("", "--sync", action="store_true")
|
||||
parser.add_option("", "--version", action="callback", callback=show_version,
|
||||
help="Display version and exit")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if args:
|
||||
parser.print_usage()
|
||||
sys.exit(1)
|
||||
options, params = parser.parse_args()
|
||||
|
||||
# Handle ssh logins
|
||||
if 'DISPLAY' not in os.environ:
|
||||
|
1
src/gvc
Submodule
1
src/gvc
Submodule
Submodule src/gvc added at 40cdff2479
@ -1,39 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,252 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,35 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,514 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
||||
|
@ -1,83 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,35 +0,0 @@
|
||||
/* -*- 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 */
|
File diff suppressed because it is too large
Load Diff
@ -1,108 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,230 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,165 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,199 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,120 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,199 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,34 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,964 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/* -*- 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 */
|
@ -1,34 +0,0 @@
|
||||
/* -*- 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 */
|
@ -785,16 +785,19 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
|
||||
}
|
||||
else if (strcmp (element_name, "context") == 0)
|
||||
{
|
||||
char *context = NULL;
|
||||
char *id = NULL;
|
||||
const char **attribute;
|
||||
const char **value;
|
||||
|
||||
for (attribute = attribute_names, value = attribute_values; *attribute; attribute++, value++)
|
||||
{
|
||||
if (strcmp (*attribute, "id") == 0)
|
||||
context = g_strdup (*value);
|
||||
{
|
||||
id = g_strdup (*value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (context < 0)
|
||||
if (!id)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_MARKUP_ERROR,
|
||||
@ -803,7 +806,7 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
|
||||
element_name);
|
||||
return;
|
||||
}
|
||||
data->context = context;
|
||||
data->context = id;
|
||||
}
|
||||
else if (strcmp (element_name, "application") == 0)
|
||||
{
|
||||
@ -816,7 +819,10 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
|
||||
for (attribute = attribute_names, value = attribute_values; *attribute; attribute++, value++)
|
||||
{
|
||||
if (strcmp (*attribute, "id") == 0)
|
||||
appid = g_strdup (*value);
|
||||
{
|
||||
appid = g_strdup (*value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!appid)
|
||||
|
@ -173,48 +173,52 @@ _st_set_text_from_style (ClutterText *text,
|
||||
|
||||
ClutterColor color;
|
||||
StTextDecoration decoration;
|
||||
PangoAttrList *attribs;
|
||||
PangoAttrList *attribs = NULL;
|
||||
const PangoFontDescription *font;
|
||||
gchar *font_string;
|
||||
StTextAlign align;
|
||||
|
||||
st_theme_node_get_foreground_color (theme_node, &color);
|
||||
clutter_text_set_color (text, &color);
|
||||
|
||||
font = st_theme_node_get_font (theme_node);
|
||||
font_string = pango_font_description_to_string (font);
|
||||
clutter_text_set_font_name (text, font_string);
|
||||
g_free (font_string);
|
||||
|
||||
attribs = pango_attr_list_new ();
|
||||
clutter_text_set_font_description (text, (PangoFontDescription *) font);
|
||||
|
||||
decoration = st_theme_node_get_text_decoration (theme_node);
|
||||
if (decoration & ST_TEXT_DECORATION_UNDERLINE)
|
||||
if (decoration)
|
||||
{
|
||||
PangoAttribute *underline = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
|
||||
pango_attr_list_insert (attribs, underline);
|
||||
attribs = pango_attr_list_new ();
|
||||
|
||||
if (decoration & ST_TEXT_DECORATION_UNDERLINE)
|
||||
{
|
||||
PangoAttribute *underline = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
|
||||
pango_attr_list_insert (attribs, underline);
|
||||
}
|
||||
if (decoration & ST_TEXT_DECORATION_LINE_THROUGH)
|
||||
{
|
||||
PangoAttribute *strikethrough = pango_attr_strikethrough_new (TRUE);
|
||||
pango_attr_list_insert (attribs, strikethrough);
|
||||
}
|
||||
/* Pango doesn't have an equivalent attribute for _OVERLINE, and we deliberately
|
||||
* skip BLINK (for now...)
|
||||
*/
|
||||
}
|
||||
if (decoration & ST_TEXT_DECORATION_LINE_THROUGH)
|
||||
{
|
||||
PangoAttribute *strikethrough = pango_attr_strikethrough_new (TRUE);
|
||||
pango_attr_list_insert (attribs, strikethrough);
|
||||
}
|
||||
/* Pango doesn't have an equivalent attribute for _OVERLINE, and we deliberately
|
||||
* skip BLINK (for now...)
|
||||
*/
|
||||
|
||||
clutter_text_set_attributes (text, attribs);
|
||||
|
||||
pango_attr_list_unref (attribs);
|
||||
if (attribs)
|
||||
pango_attr_list_unref (attribs);
|
||||
|
||||
align = st_theme_node_get_text_align (theme_node);
|
||||
if(align == ST_TEXT_ALIGN_JUSTIFY) {
|
||||
clutter_text_set_justify (text, TRUE);
|
||||
clutter_text_set_line_alignment (text, PANGO_ALIGN_LEFT);
|
||||
} else {
|
||||
clutter_text_set_justify (text, FALSE);
|
||||
clutter_text_set_line_alignment (text, (PangoAlignment) align);
|
||||
}
|
||||
if (align == ST_TEXT_ALIGN_JUSTIFY)
|
||||
{
|
||||
clutter_text_set_justify (text, TRUE);
|
||||
clutter_text_set_line_alignment (text, PANGO_ALIGN_LEFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_text_set_justify (text, FALSE);
|
||||
clutter_text_set_line_alignment (text, (PangoAlignment) align);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -270,12 +270,6 @@ scroll_bar_allocate_children (StScrollBar *bar,
|
||||
handle_box.y2 = content_box.y2;
|
||||
}
|
||||
|
||||
/* snap to pixel */
|
||||
handle_box.x1 = (int) handle_box.x1;
|
||||
handle_box.y1 = (int) handle_box.y1;
|
||||
handle_box.x2 = (int) handle_box.x2;
|
||||
handle_box.y2 = (int) handle_box.y2;
|
||||
|
||||
clutter_actor_allocate (priv->handle,
|
||||
&handle_box,
|
||||
flags);
|
||||
|
@ -37,61 +37,7 @@ typedef struct _StScrollViewFadeClass StScrollViewFadeClass;
|
||||
|
||||
#define DEFAULT_FADE_OFFSET 68.0f
|
||||
|
||||
static const gchar *fade_glsl_shader =
|
||||
"uniform sampler2D tex;\n"
|
||||
"uniform float height;\n"
|
||||
"uniform float width;\n"
|
||||
"uniform float offset_bottom;\n"
|
||||
"uniform float offset_top;\n"
|
||||
"uniform float offset_right;\n"
|
||||
"uniform float offset_left;\n"
|
||||
/*
|
||||
* Used to pass the fade area to the shader
|
||||
*
|
||||
* [0][0] = x1
|
||||
* [0][1] = y1
|
||||
* [1][0] = x2
|
||||
* [1][1] = y2
|
||||
*
|
||||
*/
|
||||
"uniform mat2 fade_area;\n"
|
||||
"\n"
|
||||
"void main ()\n"
|
||||
"{\n"
|
||||
" vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord_in[0].xy));\n"
|
||||
" float y = height * cogl_tex_coord_in[0].y;\n"
|
||||
" float x = width * cogl_tex_coord_in[0].x;\n"
|
||||
" float ratio = 1.0;\n"
|
||||
" float fade_bottom_start = fade_area[1][1] - offset_bottom;\n"
|
||||
" float fade_right_start = fade_area[1][0] - offset_right;\n"
|
||||
" float ratio_top = y / offset_top;\n"
|
||||
" float ratio_bottom = (fade_area[1][1] - y)/(fade_area[1][1] - fade_bottom_start);\n"
|
||||
" float ratio_left = x / offset_left;\n"
|
||||
" float ratio_right = (fade_area[1][0] - x)/(fade_area[1][0] - fade_right_start);\n"
|
||||
" bool in_scroll_area = fade_area[0][0] <= x && fade_area[1][0] >= x;\n"
|
||||
" bool fade_top = y < offset_top && in_scroll_area && (y >= fade_area[0][1]);\n"
|
||||
" bool fade_bottom = y > fade_bottom_start && in_scroll_area && (y <= fade_area[1][1]);\n"
|
||||
" bool fade_left = x < offset_left && in_scroll_area && (x >= fade_area[0][0]);\n"
|
||||
" bool fade_right = x > fade_right_start && in_scroll_area && (x <= fade_area[1][0]);\n"
|
||||
"\n"
|
||||
" if (fade_top) {\n"
|
||||
" ratio *= ratio_top;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (fade_bottom) {\n"
|
||||
" ratio *= ratio_bottom;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (fade_left) {\n"
|
||||
" ratio *= ratio_left;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (fade_right) {\n"
|
||||
" ratio *= ratio_right;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" cogl_color_out = color * ratio;\n"
|
||||
"}";
|
||||
#include "st-scroll-view-fade-generated.c"
|
||||
|
||||
struct _StScrollViewFade
|
||||
{
|
||||
@ -107,10 +53,10 @@ struct _StScrollViewFade
|
||||
gint height_uniform;
|
||||
gint width_uniform;
|
||||
gint fade_area_uniform;
|
||||
gint offset_top_uniform;
|
||||
gint offset_bottom_uniform;
|
||||
gint offset_left_uniform;
|
||||
gint offset_right_uniform;
|
||||
gint vfade_offset_uniform;
|
||||
gint hfade_offset_uniform;
|
||||
gint vvalue_uniform;
|
||||
gint hvalue_uniform;
|
||||
|
||||
StAdjustment *vadjustment;
|
||||
StAdjustment *hadjustment;
|
||||
@ -175,14 +121,14 @@ st_scroll_view_fade_pre_paint (ClutterEffect *effect)
|
||||
cogl_program_get_uniform_location (self->program, "width");
|
||||
self->fade_area_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "fade_area");
|
||||
self->offset_top_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "offset_top");
|
||||
self->offset_bottom_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "offset_bottom");
|
||||
self->offset_left_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "offset_left");
|
||||
self->offset_right_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "offset_right");
|
||||
self->vfade_offset_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "vfade_offset");
|
||||
self->hfade_offset_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "hfade_offset");
|
||||
self->vvalue_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "vvalue");
|
||||
self->hvalue_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "hvalue");
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (st_scroll_view_fade_parent_class);
|
||||
@ -261,38 +207,24 @@ st_scroll_view_fade_paint_target (ClutterOffscreenEffect *effect)
|
||||
if (h_scroll_visible)
|
||||
fade_area[1][1] -= clutter_actor_get_height (hscroll);
|
||||
|
||||
st_adjustment_get_values (self->vadjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
if (self->vvalue_uniform > -1)
|
||||
{
|
||||
st_adjustment_get_values (self->vadjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
value = (value - lower) / (upper - page_size - lower);
|
||||
cogl_program_set_uniform_1f (self->program, self->vvalue_uniform, value);
|
||||
}
|
||||
|
||||
if (self->offset_top_uniform > -1) {
|
||||
if (value > lower + 0.1)
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_top_uniform, self->vfade_offset);
|
||||
else
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_top_uniform, 0.0f);
|
||||
}
|
||||
|
||||
if (self->offset_bottom_uniform > -1) {
|
||||
if (value < upper - page_size - 0.1)
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_bottom_uniform, self->vfade_offset);
|
||||
else
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_bottom_uniform, 0.0f);
|
||||
}
|
||||
|
||||
st_adjustment_get_values (self->hadjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
|
||||
if (self->offset_left_uniform > -1) {
|
||||
if (value > lower + 0.1)
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_left_uniform, self->hfade_offset);
|
||||
else
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_left_uniform, 0.0f);
|
||||
}
|
||||
|
||||
if (self->offset_right_uniform > -1) {
|
||||
if (value < upper - page_size - 0.1)
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_right_uniform, self->hfade_offset);
|
||||
else
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_right_uniform, 0.0f);
|
||||
}
|
||||
if (self->hvalue_uniform > -1)
|
||||
{
|
||||
st_adjustment_get_values (self->hadjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
value = (value - lower) / (upper - page_size - lower);
|
||||
cogl_program_set_uniform_1f (self->program, self->hvalue_uniform, value);
|
||||
}
|
||||
|
||||
if (self->vfade_offset_uniform > -1)
|
||||
cogl_program_set_uniform_1f (self->program, self->vfade_offset_uniform, self->vfade_offset);
|
||||
if (self->hfade_offset_uniform > -1)
|
||||
cogl_program_set_uniform_1f (self->program, self->hfade_offset_uniform, self->hfade_offset);
|
||||
if (self->tex_uniform > -1)
|
||||
cogl_program_set_uniform_1i (self->program, self->tex_uniform, 0);
|
||||
if (self->height_uniform > -1)
|
||||
@ -549,7 +481,7 @@ st_scroll_view_fade_init (StScrollViewFade *self)
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
|
||||
cogl_shader_source (shader, fade_glsl_shader);
|
||||
cogl_shader_source (shader, (const char *) st_scroll_view_fade_glsl);
|
||||
cogl_shader_compile (shader);
|
||||
if (!cogl_shader_is_compiled (shader))
|
||||
{
|
||||
@ -571,8 +503,10 @@ st_scroll_view_fade_init (StScrollViewFade *self)
|
||||
self->height_uniform = -1;
|
||||
self->width_uniform = -1;
|
||||
self->fade_area_uniform = -1;
|
||||
self->offset_top_uniform = -1;
|
||||
self->offset_bottom_uniform = -1;
|
||||
self->vfade_offset_uniform = -1;
|
||||
self->hfade_offset_uniform = -1;
|
||||
self->vvalue_uniform = -1;
|
||||
self->hvalue_uniform = -1;
|
||||
self->vfade_offset = DEFAULT_FADE_OFFSET;
|
||||
self->hfade_offset = DEFAULT_FADE_OFFSET;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user