Compare commits
157 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c64f195e96 | ||
![]() |
247546d531 | ||
![]() |
44252b052d | ||
![]() |
226032d2e1 | ||
![]() |
53f28074ad | ||
![]() |
2993e02c33 | ||
![]() |
628bfc8311 | ||
![]() |
27bfaf9b35 | ||
![]() |
e4e87d03c5 | ||
![]() |
956d89fbec | ||
![]() |
1ad62527ea | ||
![]() |
1d79d74e97 | ||
![]() |
b90183665f | ||
![]() |
73fde364c8 | ||
![]() |
21b05e8150 | ||
![]() |
e8391a726d | ||
![]() |
fb85a476a1 | ||
![]() |
047acb887e | ||
![]() |
eaadeb8ef4 | ||
![]() |
03946a9621 | ||
![]() |
820f689f77 | ||
![]() |
724f99cc62 | ||
![]() |
83125c4849 | ||
![]() |
d8a1ce0871 | ||
![]() |
e156e1a438 | ||
![]() |
83f3084415 | ||
![]() |
81e93d083e | ||
![]() |
542353b8d8 | ||
![]() |
8868d3aa6d | ||
![]() |
c419649fe7 | ||
![]() |
130c726fff | ||
![]() |
ac478727cc | ||
![]() |
331c73002f | ||
![]() |
95a587e81b | ||
![]() |
38a45b4f0f | ||
![]() |
c730cd3296 | ||
![]() |
c10a18ab71 | ||
![]() |
ca2f7597b4 | ||
![]() |
3c70435969 | ||
![]() |
0a1b9867fc | ||
![]() |
d8177a8f3b | ||
![]() |
52417a8363 | ||
![]() |
8191e10665 | ||
![]() |
a6f39a12d7 | ||
![]() |
79a42e097d | ||
![]() |
4a5e276551 | ||
![]() |
35abf39971 | ||
![]() |
c1d107a682 | ||
![]() |
31f67d9142 | ||
![]() |
3a0197c8db | ||
![]() |
c4f744d7ec | ||
![]() |
61b1679719 | ||
![]() |
cdbb1bb665 | ||
![]() |
1020d8a0f8 | ||
![]() |
1f6811ca06 | ||
![]() |
c256154190 | ||
![]() |
60225ef86d | ||
![]() |
48498d83d3 | ||
![]() |
14757dbd6c | ||
![]() |
df89d4dc59 | ||
![]() |
ace549c1bf | ||
![]() |
1198ffd297 | ||
![]() |
1aac5c43e4 | ||
![]() |
4d785d249f | ||
![]() |
efbf102b63 | ||
![]() |
4d1668b01c | ||
![]() |
cad6f31c1a | ||
![]() |
294f59103f | ||
![]() |
f88f51dd99 | ||
![]() |
c1eaf97bc6 | ||
![]() |
1420f62dfa | ||
![]() |
3ff194247a | ||
![]() |
36b1cd13c9 | ||
![]() |
bcede26d77 | ||
![]() |
fbf1ee8a01 | ||
![]() |
1360747c9e | ||
![]() |
1d95841da0 | ||
![]() |
494fcfecf8 | ||
![]() |
75705b45ef | ||
![]() |
1ad1e48741 | ||
![]() |
ddb682e4fe | ||
![]() |
5216b77600 | ||
![]() |
c93d91d80b | ||
![]() |
f9e3467b70 | ||
![]() |
13bea1a01b | ||
![]() |
76c930e471 | ||
![]() |
9f6cd75170 | ||
![]() |
c107882828 | ||
![]() |
d18e084cd5 | ||
![]() |
2eb779740c | ||
![]() |
3ce20568d0 | ||
![]() |
d45ab6f15e | ||
![]() |
cd7197e605 | ||
![]() |
3f6c1aadef | ||
![]() |
29e8290b65 | ||
![]() |
3074e48405 | ||
![]() |
12c2939b64 | ||
![]() |
c7eed59562 | ||
![]() |
73903400c5 | ||
![]() |
dc7cc9b517 | ||
![]() |
b18c239240 | ||
![]() |
3c66f1a4d9 | ||
![]() |
1dff5fb5b2 | ||
![]() |
e2561d15b5 | ||
![]() |
326c3732b8 | ||
![]() |
5dd020f2e2 | ||
![]() |
b6edbd46b9 | ||
![]() |
c330036fef | ||
![]() |
d0a864b9b9 | ||
![]() |
9bed5b725e | ||
![]() |
f374ecfc75 | ||
![]() |
dd8ca02425 | ||
![]() |
ff3f9bdd7d | ||
![]() |
fab02ae82f | ||
![]() |
d43c5ec27a | ||
![]() |
f7de35b852 | ||
![]() |
cde0045851 | ||
![]() |
f844613292 | ||
![]() |
ff2e44de53 | ||
![]() |
17aa8e0488 | ||
![]() |
a33df9b046 | ||
![]() |
c25f399f7c | ||
![]() |
bd47d07fbc | ||
![]() |
72282237e1 | ||
![]() |
dfb44aa51d | ||
![]() |
5516cad087 | ||
![]() |
ab60c31629 | ||
![]() |
52dd030087 | ||
![]() |
98240c2857 | ||
![]() |
65bfd6c6d2 | ||
![]() |
1034e33c35 | ||
![]() |
d7528b878c | ||
![]() |
eb2e66c539 | ||
![]() |
30e9a2a7d0 | ||
![]() |
e842694316 | ||
![]() |
b33d87a762 | ||
![]() |
0ff3599d91 | ||
![]() |
28d79a1235 | ||
![]() |
522d21154b | ||
![]() |
7c231916c1 | ||
![]() |
a40bb67fc6 | ||
![]() |
4c350b90c7 | ||
![]() |
47dee22b05 | ||
![]() |
13c0e575f6 | ||
![]() |
ea8736b13a | ||
![]() |
303d53e7f5 | ||
![]() |
31295dfe83 | ||
![]() |
69ea4553cb | ||
![]() |
0d8d77356e | ||
![]() |
8b78032248 | ||
![]() |
ad277a563c | ||
![]() |
db26fb201e | ||
![]() |
9f00be50d6 | ||
![]() |
77d21e53d0 | ||
![]() |
ba0b4ba590 | ||
![]() |
b9fc7a3050 | ||
![]() |
aa053a906d |
102
NEWS
102
NEWS
@@ -1,29 +1,95 @@
|
||||
3.9.1
|
||||
3.8.4
|
||||
=====
|
||||
* Fix initial text in logout dialog [Matthias; #702056]
|
||||
* Clear login messages when the user answers [John; #702458]
|
||||
* Align the "Not Listed?" label properly in the login screen [Mathieu; #702307]
|
||||
* Workaround crash causing bugs in code [Florian; #610279]
|
||||
* Improve time stamp in chat messages (frequency and formatting)
|
||||
[Carlos; #687809, #687809]
|
||||
* Fix unlock screen after prematurely stopping curtain drag [Lionel; #703126]
|
||||
* Fix autorun notification [Matthis; 703418
|
||||
* Fix background occasionally turning solid blue on monitor changes [Lionel: #703001]
|
||||
* Increase message tray performance [Giovanni; #700194]
|
||||
* Fix focus of notifications after they're expanded [Jasper; #698778]
|
||||
* Fix orientation of gradient on app menu in RTL locales [Jasper; #704583]
|
||||
* Support filenames in addition to file uris for background
|
||||
[Giovanni, Ray; #702121]
|
||||
* misc bug fixes [Adel, Florian, Emilio, Alban, Jasper; #702338, #704265,
|
||||
#698863, #698484]
|
||||
|
||||
Contributors:
|
||||
Mathieu Bridon, Alban Browaeys, Giovanni Campagna, Matthias Clasen, Adel Gadllah,
|
||||
Emilio Pozuelo Monfort, Linonel Landwerlin, Carlos Soriano, Ray Strode,
|
||||
John Wendell
|
||||
|
||||
3.8.3
|
||||
=====
|
||||
* Fix child menu regression introduced in 3.8.2 [Florian; #699678]
|
||||
* Fix alt-tab not always switching back to the previous window [Florian; #700356]
|
||||
* Fix VPN network icon regression introduced in 3.8.2 [Florian; #700394]
|
||||
* Allow switch-to-workspace-n keybindings in overview [Florian; #649977]
|
||||
* Update man page [Matthias; #700339]
|
||||
* Add FocusSearch DBus method [Florian; #700536]
|
||||
* gdm: Update the session chooser style [Allan; #695742]
|
||||
* Fix some app folders getting truncated at the top [Florian; #694371]
|
||||
* Fix duplicate cursors in screenshots with magnification [Florian; #700488]
|
||||
* popupMenu: Allow for an optional border for slider handle [Florian; #697917]
|
||||
* Synchronize input source switching with key events [Rui; #697007]
|
||||
* Switch input source on modifiers-only accelerator [Rui; #697008]
|
||||
* Allow input source switching in message tray [Rui; #697009]
|
||||
* Tweak timeout for activating windows during XDND [Adel; #700150]
|
||||
* Fix fullscreen windows not being unredirected when legacy tray icons
|
||||
are around [Adel; #701224]
|
||||
* Fix ellipsization in control buttons in app picker [Carlos; #696307]
|
||||
* Fix DND to empty dash [Florian; #684618]
|
||||
* Fix OSD window appearing below system modal dialogs [Rui; #701269]
|
||||
* Clear clipboard on screen lock to prevent information leak [Florian; #698922]
|
||||
* Allow session mode specific overrides schema [Florian; #701717]
|
||||
* Fix incomplete app menu if multiple actions only become available later
|
||||
[Xavier; #694612]
|
||||
* Fix showing the OSD when a fullscreen app is unredirected [Adel, #701224]
|
||||
* window-switcher: Only show windows from current workspace by default
|
||||
[Florian; #701214
|
||||
* Misc bug fixes [Florian, Rui, Giovanni, Stef; #700409, #700625, #700807,
|
||||
#700842, #700900, #700944, #700190, #700972, #700877]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Xavier Claessens, Matthias Clasen, Allan Day,
|
||||
Adel Gadllah, Rui Matos, Florian Müllner, Carlos Soriano, Stef Walter
|
||||
|
||||
Translations:
|
||||
Cheng-Chia Tseng [zh_HK, zh_TW], eternalhui [zh_CN]
|
||||
|
||||
3.8.2
|
||||
=====
|
||||
* Add additional toggle-overview keybinding [Matthias; #698251]
|
||||
* Disable <super> shortcut when sticky keys are enabled [Matthias; #685974]
|
||||
* Disable tray context menu while a notification displays [Jasper; #695800]
|
||||
* Watch GApplication busy state [Cosimo; #697207]
|
||||
* Disable style transitions if animations are disabled [Jasper; #698391]
|
||||
* Filter out hidden applications from "Frequent" view [Giovanni; #696949]
|
||||
* Fix window previews swapping place randomly [Jasper; #694469, #698776]
|
||||
* Add support for serialized GIcons in remote search providers [Cosimo; #698761]
|
||||
* Fix hotcorner regression in RTL locales [Jasper; #698884]
|
||||
* Allow some keybindings to work while a top bar menu is open [Florian; #698938]
|
||||
* Make open-app-menu keybinding a toggle action [Florian; #686756]
|
||||
* Only recognize common URL schemes in notification messages [Monica; #661225]
|
||||
* Misc fixes and cleanups [Tim, Jasper, Florian, Giovanni, Owen; #698531,
|
||||
#698622, #698427, #698483, #698513, #697203, #698959, #698918, #699029,
|
||||
#699075, #696720, #649748]
|
||||
* ctrlAltTab: Use symbolic icons for desktop windows [Matthias; #697914]
|
||||
* gdm: Fix regression where domain login hint not shown [Stef; #698200]
|
||||
* Hide "Open Calendar" item when no calendar app is installed [Lionel; #697725]
|
||||
* Update how branding appears on login screen [Florian; #694912, #699877]
|
||||
* Allow OSD popups to grow if necessary [Marta; #696523]
|
||||
* Fix offset of shadow offscreen rendering [Lionel; #698301]
|
||||
* Fix insensitive button preventing empty keyring password [Stef; #696304]
|
||||
* Allow cancelling keyring dialog between prompts [Stef; #682830]
|
||||
* modalDialog: Show spinner while working [Stef; #684438]
|
||||
* Provide a DBus API for screencasting [Florian; #696247]
|
||||
* Implement app folder keynav and shortcuts [Florian; #695314]
|
||||
* polkitAgent: Allow retrying after mistyped passwords [Stef; #684431]
|
||||
* Add input purpose and hints to StEntry and StIMText [Daiki; #691392]
|
||||
* Set input-purpose property for password entries [Rui; #700043]
|
||||
* Misc fixes and cleanups [Jasper, Florian, Giovanni, Tim, Rui; #697203,
|
||||
#698959, #696720, #698531, #676285, #698812, #699189]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Cosimo Cecchi, Monica Chelliah, Matthias Clasen, Tim Lunn,
|
||||
Florian Müllner, Jasper St. Pierre, Michael Wood, Owen W. Taylor
|
||||
Giovanni Campagna, Matthias Clasen, Lionel Landwerlin, Tim Lunn, Rui Matos,
|
||||
Simon McVittie, Marta Milakovic, Florian Müllner, Jasper St. Pierre,
|
||||
Daiki Ueno, Stef Walter
|
||||
|
||||
Translations:
|
||||
Fran Diéguez [gl], Muhammet Kara [tr], Daniel Mustieles [es],
|
||||
Gil Forcada [ia], Anish A [ml], Dimitris Spingos [el], Marek Černocký [cs],
|
||||
Žygimantas Beručka [lt]
|
||||
Muhammet Kara [tr], Nik Kalach [ia], Žygimantas Beručka [lt],
|
||||
Kjartan Maraas [nb]
|
||||
|
||||
3.8.1
|
||||
=====
|
||||
|
12
configure.ac
12
configure.ac
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[3.9.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.8.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||
@@ -63,18 +63,18 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||
CLUTTER_MIN_VERSION=1.13.4
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
GJS_MIN_VERSION=1.35.4
|
||||
MUTTER_MIN_VERSION=3.9.1
|
||||
MUTTER_MIN_VERSION=3.8.3
|
||||
GTK_MIN_VERSION=3.7.9
|
||||
GIO_MIN_VERSION=2.37.0
|
||||
GIO_MIN_VERSION=2.35.0
|
||||
LIBECAL_MIN_VERSION=3.5.3
|
||||
LIBEDATASERVER_MIN_VERSION=3.5.3
|
||||
TELEPATHY_GLIB_MIN_VERSION=0.17.5
|
||||
POLKIT_MIN_VERSION=0.100
|
||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
||||
GCR_MIN_VERSION=3.3.90
|
||||
GCR_MIN_VERSION=3.7.5
|
||||
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
|
||||
GNOME_MENUS_REQUIRED_VERSION=3.5.3
|
||||
NETWORKMANAGER_MIN_VERSION=0.9.8
|
||||
NETWORKMANAGER_MIN_VERSION=0.9.6
|
||||
PULSE_MIN_VERS=2.0
|
||||
|
||||
# Collect more than 20 libraries for a prize!
|
||||
@@ -96,7 +96,7 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
|
||||
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
|
||||
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
|
||||
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
|
||||
libsecret-unstable gcr-3 >= $GCR_MIN_VERSION)
|
||||
libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION)
|
||||
|
||||
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
|
||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
|
||||
|
@@ -11,9 +11,6 @@
|
||||
<KeyListEntry name="focus-active-notification"
|
||||
_description="Focus the active notification"/>
|
||||
|
||||
<KeyListEntry name="toggle-overview"
|
||||
_description="Show the overview"/>
|
||||
|
||||
<KeyListEntry name="toggle-application-view"
|
||||
_description="Show all applications"/>
|
||||
|
||||
|
@@ -15,6 +15,7 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
|
||||
|
||||
introspectiondir = $(datadir)/dbus-1/interfaces
|
||||
introspection_DATA = \
|
||||
org.gnome.Shell.Screencast.xml \
|
||||
org.gnome.Shell.Screenshot.xml \
|
||||
org.gnome.ShellSearchProvider.xml \
|
||||
org.gnome.ShellSearchProvider2.xml
|
||||
|
96
data/org.gnome.Shell.Screencast.xml
Normal file
96
data/org.gnome.Shell.Screencast.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<!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.Screencast:
|
||||
@short_description: Screencast interface
|
||||
|
||||
The interface used to record screen contents.
|
||||
-->
|
||||
<interface name="org.gnome.Shell.Screencast">
|
||||
|
||||
<!--
|
||||
Screencast:
|
||||
@file_template: the template for the filename to use
|
||||
@options: a dictionary of optional parameters
|
||||
@success: whether the screencast was started successfully
|
||||
@filename_used: the file where the screencast is being saved
|
||||
|
||||
Records a screencast of the whole screen and saves it
|
||||
(by default) as webm video under a filename derived from
|
||||
@file_template. The template is either a relative or absolute
|
||||
filename which may contain some escape sequences - %d and %t
|
||||
will be replaced by the start date and time of the recording.
|
||||
If a relative name is used, the screencast will be saved in the
|
||||
$XDG_VIDEOS_DIR if it exists, or the home directory otherwise.
|
||||
The actual filename of the saved video is returned in @filename_used.
|
||||
The set of optional parameters in @options currently consists of:
|
||||
'draw-cursor'(b): whether the cursor should be included in the
|
||||
recording (true)
|
||||
'framerate'(i): the number of frames per second that should be
|
||||
recorded if possible (30)
|
||||
'pipeline'(s): the GStreamer pipeline used to encode recordings
|
||||
in gst-launch format; if not specified, the
|
||||
recorder will produce vp8 (webm) video (unset)
|
||||
-->
|
||||
<method name="Screencast">
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
ScreencastArea:
|
||||
@x: the X coordinate of the area to capture
|
||||
@y: the Y coordinate of the area to capture
|
||||
@width: the width of the area to capture
|
||||
@height: the height of the area to capture
|
||||
@file_template: the template for the filename to use
|
||||
@options: a dictionary of optional parameters
|
||||
@success: whether the screencast was started successfully
|
||||
@filename_used: the file where the screencast is being saved
|
||||
|
||||
Records a screencast of the passed in area and saves it
|
||||
(by default) as webm video under a filename derived from
|
||||
@file_template. The template is either a relative or absolute
|
||||
filename which may contain some escape sequences - %d and %t
|
||||
will be replaced by the start date and time of the recording.
|
||||
If a relative name is used, the screencast will be saved in the
|
||||
$XDG_VIDEOS_DIR if it exists, or the home directory otherwise.
|
||||
The actual filename of the saved video is returned in @filename_used.
|
||||
The set of optional parameters in @options currently consists of:
|
||||
'draw-cursor'(b): whether the cursor should be included in the
|
||||
recording (true)
|
||||
'framerate'(i): the number of frames per second that should be
|
||||
recorded if possible (30)
|
||||
'pipeline'(s): the GStreamer pipeline used to encode recordings
|
||||
in gst-launch format; if not specified, the
|
||||
recorder will produce vp8 (webm) video (unset)
|
||||
-->
|
||||
<method name="ScreencastArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
StopScreencast:
|
||||
@success: whether stopping the recording was successful
|
||||
|
||||
Stop the recording started by either Screencast or ScreencastArea.
|
||||
-->
|
||||
<method name="StopScreencast">
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
@@ -46,7 +46,7 @@
|
||||
<!--
|
||||
GetResultMetas:
|
||||
@identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet()
|
||||
@metas: A dictionary describing the given search result, containing a human-readable 'name' (string), along with the result identifier this meta is for, 'id' (string). Optionally, 'icon' (a serialized GIcon as obtained by g_icon_serialize) can be specified if the result can be better served with a thumbnail of the content (such as with images). 'gicon' (a serialized GIcon as obtained by g_icon_to_string) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) are deprecated values that can also be used for that purpose. A 'description' field (string) may also be specified if more context would help the user find the desired result.
|
||||
@metas: A dictionary describing the given search result, containing a human-readable 'name' (string), along with the result identifier this meta is for, 'id' (string). 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
|
||||
-->
|
||||
|
@@ -117,13 +117,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
||||
Overview.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="toggle-overview" type="as">
|
||||
<default>["<Super>s"]</default>
|
||||
<_summary>Keybinding to open the overview</_summary>
|
||||
<_description>
|
||||
Keybinding to open the Activities Overview.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="toggle-message-tray" type="as">
|
||||
<default>["<Super>m"]</default>
|
||||
<_summary>Keybinding to toggle the visibility of the message tray</_summary>
|
||||
@@ -214,7 +207,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
||||
</_description>
|
||||
</key>
|
||||
<key type="b" name="current-workspace-only">
|
||||
<default>false</default>
|
||||
<default>true</default>
|
||||
<summary>Limit switcher to current workspace.</summary>
|
||||
<description>
|
||||
If true, only windows from the current workspace are shown in the switcher.
|
||||
|
@@ -125,10 +125,6 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
/* PopupMenu */
|
||||
|
||||
.popup-menu-ornament {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.popup-menu-boxpointer,
|
||||
.candidate-popup-boxpointer {
|
||||
-arrow-border-radius: 8px;
|
||||
@@ -804,6 +800,11 @@ StScrollBar StButton#vhandle:active {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.empty-dash-drop-target {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Search Box */
|
||||
|
||||
#searchEntry {
|
||||
@@ -891,12 +892,11 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.app-view-controls {
|
||||
width: 250px;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.app-view-control {
|
||||
padding: 4px 16px;
|
||||
padding: 4px 32px;
|
||||
}
|
||||
|
||||
.search-display > StBoxLayout,
|
||||
@@ -2312,6 +2312,7 @@ StScrollBar StButton#vhandle:active {
|
||||
font-weight: bold;
|
||||
color: #666666;
|
||||
padding-top: 1em;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.login-dialog-not-listed-button:focus .login-dialog-not-listed-label,
|
||||
@@ -2342,52 +2343,47 @@ StScrollBar StButton#vhandle:active {
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
.login-dialog-session-list {
|
||||
color: #ffffff;
|
||||
font-size: 10.5pt;
|
||||
.login-dialog-session-list,
|
||||
.login-dialog-session-list-item {
|
||||
color: #babdb6;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-button:focus,
|
||||
.login-dialog-session-list-button:active,
|
||||
.login-dialog-session-list-button:hover,
|
||||
.login-dialog-session-list-item:focus,
|
||||
.login-dialog-session-list-item:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-button {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-button:focus {
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-button:active {
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-button:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-scroll-view {
|
||||
background-gradient-start: rgba(80,80,80,0.3);
|
||||
background-gradient-end: rgba(80,80,80,0.7);
|
||||
background-gradient-direction: vertical;
|
||||
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(80,80,80,1.0);
|
||||
padding: .5em;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-item:focus {
|
||||
background-color: #666666;
|
||||
.login-dialog-session-list-item {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-triangle {
|
||||
padding-right: .5em;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-item-box {
|
||||
spacing: .25em;
|
||||
padding-left: 6px;
|
||||
spacing: 6px;
|
||||
}
|
||||
|
||||
.login-dialog-session-list-item-dot {
|
||||
width: .75em;
|
||||
height: .75em;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.login-dialog-logo-bin {
|
||||
padding: 24px 0px;
|
||||
}
|
||||
|
||||
.login-dialog .modal-dialog-button-box {
|
||||
|
@@ -46,6 +46,7 @@
|
||||
<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-keybinding-modes.xml"/>
|
||||
<xi:include href="xml/shell-wm.xml"/>
|
||||
<xi:include href="xml/shell-xfixes-cursor.xml"/>
|
||||
<xi:include href="xml/shell-util.xml"/>
|
||||
|
@@ -78,6 +78,7 @@ nobase_dist_js_DATA = \
|
||||
ui/popupMenu.js \
|
||||
ui/remoteSearch.js \
|
||||
ui/runDialog.js \
|
||||
ui/screencast.js \
|
||||
ui/screenshot.js \
|
||||
ui/screenShield.js \
|
||||
ui/scripting.js \
|
||||
|
@@ -28,6 +28,7 @@ const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Lang = imports.lang;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Realmd = imports.gdm.realmd;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
@@ -39,7 +40,6 @@ 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,44 +48,10 @@ const UserWidget = imports.ui.userWidget;
|
||||
const _FADE_ANIMATION_TIME = 0.25;
|
||||
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;
|
||||
const _LOGO_ICON_HEIGHT = 48;
|
||||
|
||||
let _loginDialog = null;
|
||||
|
||||
const LogoMenuButton = new Lang.Class({
|
||||
Name: 'LogoMenuButton',
|
||||
Extends: PanelMenu.Button,
|
||||
|
||||
_init: function() {
|
||||
this.parent(0.0, null, true);
|
||||
|
||||
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
|
||||
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
|
||||
Lang.bind(this, this._updateLogo));
|
||||
|
||||
this._iconBin = new St.Bin();
|
||||
this.actor.add_actor(this._iconBin);
|
||||
|
||||
this._updateLogo();
|
||||
},
|
||||
|
||||
_updateLogo: function() {
|
||||
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
|
||||
let icon = null;
|
||||
|
||||
if (path) {
|
||||
let file = Gio.file_new_for_path(path);
|
||||
let cache = St.TextureCache.get_default();
|
||||
icon = cache.load_uri_async(file.get_uri(), -1, _LOGO_ICON_HEIGHT);
|
||||
}
|
||||
this._iconBin.set_child(icon);
|
||||
}
|
||||
});
|
||||
|
||||
const UserListItem = new Lang.Class({
|
||||
Name: 'UserListItem',
|
||||
|
||||
@@ -552,6 +518,12 @@ const LoginDialog = new Lang.Class({
|
||||
Lang.bind(this, this._updateBanner));
|
||||
this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
|
||||
Lang.bind(this, this._updateDisableUserList));
|
||||
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
|
||||
Lang.bind(this, this._updateLogo));
|
||||
|
||||
this._textureCache = St.TextureCache.get_default();
|
||||
this._textureCache.connect('texture-file-changed',
|
||||
Lang.bind(this, this._updateLogoTexture));
|
||||
|
||||
this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
|
||||
vertical: true });
|
||||
@@ -609,7 +581,6 @@ const LoginDialog = new Lang.Class({
|
||||
this._promptBox.add(this._promptLoginHint);
|
||||
|
||||
this._signInButton = null;
|
||||
this._workSpinner = null;
|
||||
|
||||
this._sessionList = new SessionList();
|
||||
this._sessionList.connect('session-activated',
|
||||
@@ -644,6 +615,11 @@ const LoginDialog = new Lang.Class({
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
|
||||
this._logoBin = new St.Bin({ style_class: 'login-dialog-logo-bin', y_expand: true });
|
||||
this._logoBin.set_y_align(Clutter.ActorAlign.END);
|
||||
this.backgroundStack.add_actor(this._logoBin);
|
||||
this._updateLogo();
|
||||
|
||||
if (!this._userManager.is_loaded)
|
||||
this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
|
||||
Lang.bind(this, function() {
|
||||
@@ -690,6 +666,24 @@ const LoginDialog = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_updateLogoTexture: function(cache, uri) {
|
||||
if (this._logoFileUri != uri)
|
||||
return;
|
||||
|
||||
let icon = null;
|
||||
if (this._logoFileUri)
|
||||
icon = this._textureCache.load_uri_async(this._logoFileUri,
|
||||
-1, _LOGO_ICON_HEIGHT);
|
||||
this._logoBin.set_child(icon);
|
||||
},
|
||||
|
||||
_updateLogo: function() {
|
||||
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
|
||||
|
||||
this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
|
||||
this._updateLogoTexture(this._textureCache, this._logoFileUri);
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
this._userVerifier.clear();
|
||||
|
||||
@@ -708,7 +702,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._promptEntry.text = '';
|
||||
|
||||
this._updateSensitivity(true);
|
||||
this._setWorking(false);
|
||||
this.setWorking(false);
|
||||
},
|
||||
|
||||
_onDefaultSessionChanged: function(client, sessionId) {
|
||||
@@ -774,11 +768,6 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_prepareDialog: function(forSecret, hold) {
|
||||
let spinnerIcon = global.datadir + '/theme/process-working.svg';
|
||||
this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
this._workSpinner.actor.show();
|
||||
|
||||
this.buttonLayout.visible = true;
|
||||
this.clearButtons();
|
||||
|
||||
@@ -791,12 +780,11 @@ const LoginDialog = new Lang.Class({
|
||||
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.placeSpinner({ 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();
|
||||
}),
|
||||
@@ -849,7 +837,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._promptEntryActivateId = 0;
|
||||
}
|
||||
|
||||
this._setWorking(false);
|
||||
this.setWorking(false);
|
||||
this._promptBox.hide();
|
||||
this._promptLoginHint.hide();
|
||||
|
||||
@@ -862,36 +850,9 @@ const LoginDialog = new Lang.Class({
|
||||
this._promptLoginHint.hide();
|
||||
|
||||
this.clearButtons();
|
||||
this._workSpinner = null;
|
||||
this._signInButton = null;
|
||||
},
|
||||
|
||||
_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() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_askQuestion: function(verifier, serviceName, question, passwordChar) {
|
||||
this._promptLabel.set_text(question);
|
||||
|
||||
@@ -906,7 +867,7 @@ const LoginDialog = new Lang.Class({
|
||||
function() {
|
||||
let text = this._promptEntry.get_text();
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(true);
|
||||
this.setWorking(true);
|
||||
this._userVerifier.answerQuery(serviceName, text);
|
||||
}];
|
||||
|
||||
@@ -914,17 +875,40 @@ const LoginDialog = new Lang.Class({
|
||||
return batch.run();
|
||||
},
|
||||
|
||||
_showRealmLoginHint: function(realmManager, hint) {
|
||||
if (!hint)
|
||||
return;
|
||||
|
||||
hint = hint.replace(/%U/g, 'user');
|
||||
hint = hint.replace(/%D/g, 'DOMAIN');
|
||||
hint = hint.replace(/%[^UD]/g, '');
|
||||
|
||||
// Translators: this message is shown below the username entry field
|
||||
// to clue the user in on how to login to the local network realm
|
||||
this._showLoginHint(null, _("(e.g., user or %s)").format(hint));
|
||||
},
|
||||
|
||||
_askForUsernameAndLogIn: function() {
|
||||
this._promptLabel.set_text(_("Username: "));
|
||||
this._promptEntry.set_text('');
|
||||
this._promptEntry.clutter_text.set_password_char('');
|
||||
|
||||
let realmManager = new Realmd.Manager();
|
||||
let signalId = realmManager.connect('login-format-changed',
|
||||
Lang.bind(this, this._showRealmLoginHint));
|
||||
this._showRealmLoginHint(realmManager.loginFormat);
|
||||
|
||||
let tasks = [this._showPrompt,
|
||||
|
||||
function() {
|
||||
let userName = this._promptEntry.get_text();
|
||||
this._promptEntry.reactive = false;
|
||||
return this._beginVerificationForUser(userName);
|
||||
},
|
||||
|
||||
function() {
|
||||
realmManager.disconnect(signalId)
|
||||
realmManager.release();
|
||||
}];
|
||||
|
||||
let batch = new Batch.ConsecutiveBatch(this, tasks);
|
||||
|
@@ -63,7 +63,7 @@ const Manager = new Lang.Class({
|
||||
Lang.bind(this, this._reloadRealms))
|
||||
this._realms = {};
|
||||
|
||||
this._aggregateProvider.connect('g-properties-changed',
|
||||
this._signalId = this._aggregateProvider.connect('g-properties-changed',
|
||||
Lang.bind(this, function(proxy, properties) {
|
||||
if ('Realms' in properties.deep_unpack())
|
||||
this._reloadRealms();
|
||||
@@ -106,7 +106,7 @@ const Manager = new Lang.Class({
|
||||
realm.connect('g-properties-changed',
|
||||
Lang.bind(this, function(proxy, properties) {
|
||||
if ('Configured' in properties.deep_unpack())
|
||||
this._reloadRealm();
|
||||
this._reloadRealm(realm);
|
||||
}));
|
||||
},
|
||||
|
||||
@@ -134,6 +134,18 @@ const Manager = new Lang.Class({
|
||||
this._updateLoginFormat();
|
||||
|
||||
return this._loginFormat;
|
||||
},
|
||||
|
||||
release: function() {
|
||||
Service(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
'/org/freedesktop/realmd',
|
||||
function(service) {
|
||||
service.ReleaseRemote();
|
||||
});
|
||||
this._aggregateProvider.disconnect(this._signalId);
|
||||
this._realms = { };
|
||||
this._updateLoginFormat();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(Manager.prototype)
|
||||
|
@@ -9,7 +9,6 @@ const Signals = imports.signals;
|
||||
|
||||
const Batch = imports.gdm.batch;
|
||||
const Fprint = imports.gdm.fingerprint;
|
||||
const Realmd = imports.gdm.realmd;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
@@ -117,7 +116,6 @@ const ShellUserVerifier = new Lang.Class({
|
||||
this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
|
||||
|
||||
this._fprintManager = new Fprint.FprintManager();
|
||||
this._realmManager = new Realmd.Manager();
|
||||
this._messageQueue = [];
|
||||
this._messageQueueTimeoutId = 0;
|
||||
this.hasPendingMessages = false;
|
||||
@@ -166,6 +164,7 @@ const ShellUserVerifier = new Lang.Class({
|
||||
|
||||
answerQuery: function(serviceName, answer) {
|
||||
if (!this._userVerifier.hasPendingMessages) {
|
||||
this._clearMessageQueue();
|
||||
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
|
||||
} else {
|
||||
let signalId = this._userVerifier.connect('no-more-messages',
|
||||
@@ -377,30 +376,11 @@ const ShellUserVerifier = new Lang.Class({
|
||||
this._queueMessage(problem, 'login-dialog-message-warning');
|
||||
},
|
||||
|
||||
_showRealmLoginHint: function() {
|
||||
if (this._realmManager.loginFormat) {
|
||||
let hint = this._realmManager.loginFormat;
|
||||
|
||||
hint = hint.replace(/%U/g, 'user');
|
||||
hint = hint.replace(/%D/g, 'DOMAIN');
|
||||
hint = hint.replace(/%[^UD]/g, '');
|
||||
|
||||
// Translators: this message is shown below the username entry field
|
||||
// to clue the user in on how to login to the local network realm
|
||||
this.emit('show-login-hint',
|
||||
_("(e.g., user or %s)").format(hint));
|
||||
}
|
||||
},
|
||||
|
||||
_onInfoQuery: function(client, serviceName, question) {
|
||||
// We only expect questions to come from the main auth service
|
||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
||||
return;
|
||||
|
||||
this._showRealmLoginHint();
|
||||
this._realmLoginHintSignalId = this._realmManager.connect('login-format-changed',
|
||||
Lang.bind(this, this._showRealmLoginHint));
|
||||
|
||||
this.emit('ask-question', serviceName, question, '');
|
||||
},
|
||||
|
||||
@@ -476,11 +456,6 @@ const ShellUserVerifier = new Lang.Class({
|
||||
}
|
||||
|
||||
this.emit('hide-login-hint');
|
||||
|
||||
if (this._realmLoginHintSignalId) {
|
||||
this._realmManager.disconnect(this._realmLoginHintSignalId);
|
||||
this._realmLoginHintSignalId = 0;
|
||||
}
|
||||
},
|
||||
});
|
||||
Signals.addSignalMethods(ShellUserVerifier.prototype);
|
||||
|
@@ -58,6 +58,7 @@ const Map = new Lang.Class({
|
||||
|
||||
_init: function(iterable) {
|
||||
this._pool = { };
|
||||
this._size = 0;
|
||||
|
||||
if (iterable) {
|
||||
for (let i = 0; i < iterable.length; i++) {
|
||||
@@ -99,6 +100,7 @@ const Map = new Lang.Class({
|
||||
node.value = value;
|
||||
} else {
|
||||
this._pool[hash] = { key: key, value: value };
|
||||
this._size++;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -108,6 +110,7 @@ const Map = new Lang.Class({
|
||||
|
||||
if (node && _sameValue(node.key, key)) {
|
||||
delete this._pool[hash];
|
||||
this._size--;
|
||||
return [node.key, node.value];
|
||||
} else {
|
||||
return [null, null];
|
||||
@@ -136,6 +139,6 @@ const Map = new Lang.Class({
|
||||
},
|
||||
|
||||
size: function() {
|
||||
return Object.getOwnPropertyNames(this._pool).length;
|
||||
return this._size;
|
||||
},
|
||||
});
|
||||
|
@@ -18,7 +18,7 @@ const _urlRegexp = new RegExp(
|
||||
'(^|' + _leadingJunk + ')' +
|
||||
'(' +
|
||||
'(?:' +
|
||||
'(?:http|https|ftp)://' + // scheme://
|
||||
'[a-z][\\w-]+://' + // scheme://
|
||||
'|' +
|
||||
'www\\d{0,3}[.]' + // www.
|
||||
'|' +
|
||||
|
@@ -234,7 +234,7 @@ const AppSwitcherPopup = new Lang.Class({
|
||||
_finish : function(timestamp) {
|
||||
let appIcon = this._items[this._selectedIndex];
|
||||
if (this._currentWindow < 0)
|
||||
appIcon.app.activate_full(-1, timestamp);
|
||||
appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp);
|
||||
else
|
||||
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
|
||||
|
||||
|
@@ -187,6 +187,9 @@ const AllView = new Lang.Class({
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this._grid.actor.y_align = Clutter.ActorAlign.START;
|
||||
this._grid.actor.y_expand = true;
|
||||
|
||||
let box = new St.BoxLayout({ vertical: true });
|
||||
this._stack = new St.Widget({ layout_manager: new AllViewLayout() });
|
||||
this._stack.add_actor(this._grid.actor);
|
||||
@@ -276,8 +279,12 @@ const AllView = new Lang.Class({
|
||||
this._eventBlocker.reactive = isOpen;
|
||||
this._currentPopup = isOpen ? popup : null;
|
||||
this._updateIconOpacities(isOpen);
|
||||
if (isOpen)
|
||||
if (isOpen) {
|
||||
this._ensureIconVisible(popup.actor);
|
||||
this._grid.actor.y = popup.parentOffset;
|
||||
} else {
|
||||
this._grid.actor.y = 0;
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
@@ -316,8 +323,6 @@ const FrequentView = new Lang.Class({
|
||||
loadApps: function() {
|
||||
let mostUsed = this._usage.get_most_used ("");
|
||||
for (let i = 0; i < mostUsed.length; i++) {
|
||||
if (!mostUsed[i].get_app_info().should_show())
|
||||
continue;
|
||||
let appIcon = new AppIcon(mostUsed[i]);
|
||||
this._grid.addItem(appIcon.actor, -1);
|
||||
}
|
||||
@@ -329,6 +334,42 @@ const Views = {
|
||||
ALL: 1
|
||||
};
|
||||
|
||||
const ControlsBoxLayout = Lang.Class({
|
||||
Name: 'ControlsBoxLayout',
|
||||
Extends: Clutter.BoxLayout,
|
||||
|
||||
/**
|
||||
* Override the BoxLayout behavior to use the maximum preferred width of all
|
||||
* buttons for each child
|
||||
*/
|
||||
vfunc_get_preferred_width: function(container, forHeight) {
|
||||
let maxMinWidth = 0;
|
||||
let maxNaturalWidth = 0;
|
||||
for (let child = container.get_first_child();
|
||||
child;
|
||||
child = child.get_next_sibling()) {
|
||||
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
|
||||
maxMinWidth = Math.max(maxMinWidth, minWidth);
|
||||
maxNaturalWidth = Math.max(maxNaturalWidth, natWidth);
|
||||
}
|
||||
let childrenCount = container.get_n_children();
|
||||
let totalSpacing = this.spacing * (childrenCount - 1);
|
||||
return [maxMinWidth * childrenCount + totalSpacing,
|
||||
maxNaturalWidth * childrenCount + totalSpacing];
|
||||
},
|
||||
|
||||
vfunc_set_container: function(container) {
|
||||
if(this._styleChangedId) {
|
||||
this._container.disconnect(this._styleChangedId);
|
||||
this._styleChangedId = 0;
|
||||
}
|
||||
if(container != null)
|
||||
this._styleChangedId = container.connect('style-changed', Lang.bind(this,
|
||||
function() { this.spacing = this._container.get_theme_node().get_length('spacing'); }));
|
||||
this._container = container;
|
||||
}
|
||||
});
|
||||
|
||||
const AppDisplay = new Lang.Class({
|
||||
Name: 'AppDisplay',
|
||||
|
||||
@@ -369,9 +410,9 @@ const AppDisplay = new Lang.Class({
|
||||
x_expand: true, y_expand: true });
|
||||
this.actor.add(this._viewStack, { expand: true });
|
||||
|
||||
let layout = new Clutter.BoxLayout({ homogeneous: true });
|
||||
this._controls = new St.Widget({ style_class: 'app-view-controls',
|
||||
layout_manager: layout });
|
||||
let layout = new ControlsBoxLayout({ homogeneous: true });
|
||||
this._controls = new St.Widget({ style_class: 'app-view-controls' });
|
||||
this._controls.set_layout_manager(layout);
|
||||
this.actor.add(new St.Bin({ child: this._controls }));
|
||||
|
||||
|
||||
@@ -574,7 +615,11 @@ const FolderIcon = new Lang.Class({
|
||||
// Position the popup above or below the source icon
|
||||
if (side == St.Side.BOTTOM) {
|
||||
this._popup.actor.show();
|
||||
this._popup.actor.y = this.actor.y - this._popup.actor.height;
|
||||
let closeButtonOffset = -this._popup.closeButton.translation_y;
|
||||
let y = this.actor.y - this._popup.actor.height;
|
||||
let yWithButton = y - closeButtonOffset;
|
||||
this._popup.parentOffset = yWithButton < 0 ? -yWithButton : 0;
|
||||
this._popup.actor.y = Math.max(y, closeButtonOffset);
|
||||
this._popup.actor.hide();
|
||||
} else {
|
||||
this._popup.actor.y = this.actor.y + this.actor.height;
|
||||
@@ -597,6 +642,7 @@ const AppFolderPopup = new Lang.Class({
|
||||
this._arrowSide = side;
|
||||
|
||||
this._isOpen = false;
|
||||
this.parentOffset = 0;
|
||||
|
||||
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
visible: false,
|
||||
@@ -620,17 +666,31 @@ const AppFolderPopup = new Lang.Class({
|
||||
this.actor.add_actor(this._boxPointer.actor);
|
||||
this._boxPointer.bin.set_child(this._view.actor);
|
||||
|
||||
let closeButton = Util.makeCloseButton();
|
||||
closeButton.connect('clicked', Lang.bind(this, this.popdown));
|
||||
this.actor.add_actor(closeButton);
|
||||
this.closeButton = Util.makeCloseButton();
|
||||
this.closeButton.connect('clicked', Lang.bind(this, this.popdown));
|
||||
this.actor.add_actor(this.closeButton);
|
||||
|
||||
this._boxPointer.actor.bind_property('opacity', closeButton, 'opacity',
|
||||
this._boxPointer.actor.bind_property('opacity', this.closeButton, 'opacity',
|
||||
GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
global.focus_manager.add_group(this.actor);
|
||||
|
||||
source.actor.connect('destroy', Lang.bind(this,
|
||||
function() {
|
||||
this.actor.destroy();
|
||||
}));
|
||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress));
|
||||
},
|
||||
|
||||
_onKeyPress: function(actor, event) {
|
||||
if (!this._isOpen)
|
||||
return false;
|
||||
|
||||
if (event.get_key_symbol() != Clutter.KEY_Escape)
|
||||
return false;
|
||||
|
||||
this.popdown();
|
||||
return true;
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
@@ -645,6 +705,7 @@ const AppFolderPopup = new Lang.Class({
|
||||
return;
|
||||
|
||||
this.actor.show();
|
||||
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
|
||||
this._boxPointer.setArrowActor(this._source.actor);
|
||||
this._boxPointer.show(BoxPointer.PopupAnimation.FADE |
|
||||
|
@@ -318,9 +318,9 @@ const Background = new Lang.Class({
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
this.isLoaded = false;
|
||||
|
||||
this._settings.connect('changed', Lang.bind(this, function() {
|
||||
this.emit('changed');
|
||||
}));
|
||||
this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() {
|
||||
this.emit('changed');
|
||||
}));
|
||||
|
||||
this._load();
|
||||
},
|
||||
@@ -361,6 +361,10 @@ const Background = new Lang.Class({
|
||||
|
||||
this.actor.disconnect(this._destroySignalId);
|
||||
this._destroySignalId = 0;
|
||||
|
||||
if (this._settingsChangedSignalId != 0)
|
||||
this._settings.disconnect(this._settingsChangedSignalId);
|
||||
this._settingsChangedSignalId = 0;
|
||||
},
|
||||
|
||||
_setLoaded: function() {
|
||||
@@ -571,7 +575,16 @@ const Background = new Lang.Class({
|
||||
}
|
||||
|
||||
let uri = this._settings.get_string(PICTURE_URI_KEY);
|
||||
let filename = Gio.File.new_for_uri(uri).get_path();
|
||||
let filename;
|
||||
if (GLib.uri_parse_scheme(uri) != null)
|
||||
filename = Gio.File.new_for_uri(uri).get_path();
|
||||
else
|
||||
filename = uri;
|
||||
|
||||
if (!filename) {
|
||||
this._setLoaded();
|
||||
return;
|
||||
}
|
||||
|
||||
this._loadFile(filename);
|
||||
},
|
||||
|
@@ -589,12 +589,12 @@ const BoxPointer = new Lang.Class({
|
||||
return St.Side.TOP;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
if (sourceAllocation.y2 + boxWidth > monitor.x + monitor.width &&
|
||||
if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width &&
|
||||
boxWidth < sourceAllocation.x1 - monitor.x)
|
||||
return St.Side.RIGHT;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
if (sourceAllocation.y1 - boxWidth < monitor.x &&
|
||||
if (sourceAllocation.x1 - boxWidth < monitor.x &&
|
||||
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
|
||||
return St.Side.LEFT;
|
||||
break;
|
||||
|
@@ -31,7 +31,7 @@ function shouldAutorunMount(mount, forTransient) {
|
||||
if (!volume || (!volume.allowAutorun && forTransient))
|
||||
return false;
|
||||
|
||||
if (!root.is_native() || isMountRootHidden(root))
|
||||
if (root.is_native() && isMountRootHidden(root))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@@ -25,7 +25,7 @@ const KeyringDialog = new Lang.Class({
|
||||
this.prompt = new Shell.KeyringPrompt();
|
||||
this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword));
|
||||
this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm));
|
||||
this.prompt.connect('hide-prompt', Lang.bind(this, this._onHidePrompt));
|
||||
this.prompt.connect('prompt-close', Lang.bind(this, this._onHidePrompt));
|
||||
|
||||
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
|
||||
vertical: false });
|
||||
@@ -63,11 +63,17 @@ const KeyringDialog = new Lang.Class({
|
||||
|
||||
this._cancelButton = this.addButton({ label: '',
|
||||
action: Lang.bind(this, this._onCancelButton),
|
||||
key: Clutter.Escape });
|
||||
key: Clutter.Escape },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.START });
|
||||
this.placeSpinner({ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._continueButton = this.addButton({ label: '',
|
||||
action: Lang.bind(this, this._onContinueButton),
|
||||
default: true },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.END });
|
||||
{ expand: false, x_fill: false, x_align: St.Align.END });
|
||||
|
||||
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
||||
@@ -143,11 +149,19 @@ const KeyringDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateSensitivity: function(sensitive) {
|
||||
this._passwordEntry.reactive = sensitive;
|
||||
this._passwordEntry.clutter_text.editable = sensitive;
|
||||
if (this._passwordEntry) {
|
||||
this._passwordEntry.reactive = sensitive;
|
||||
this._passwordEntry.clutter_text.editable = sensitive;
|
||||
}
|
||||
|
||||
if (this._confirmEntry) {
|
||||
this._confirmEntry.reactive = sensitive;
|
||||
this._confirmEntry.clutter_text.editable = sensitive;
|
||||
}
|
||||
|
||||
this._continueButton.can_focus = sensitive;
|
||||
this._continueButton.reactive = sensitive;
|
||||
this.setWorking(!sensitive);
|
||||
},
|
||||
|
||||
_ensureOpen: function() {
|
||||
|
@@ -31,7 +31,6 @@ const AuthenticationDialog = new Lang.Class({
|
||||
this.message = message;
|
||||
this.userNames = userNames;
|
||||
this._wasDismissed = false;
|
||||
this._completed = false;
|
||||
|
||||
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
|
||||
vertical: false });
|
||||
@@ -161,26 +160,32 @@ const AuthenticationDialog = new Lang.Class({
|
||||
|
||||
this._cancelButton = this.addButton({ label: _("Cancel"),
|
||||
action: Lang.bind(this, this.cancel),
|
||||
key: Clutter.Escape });
|
||||
key: Clutter.Escape },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.START });
|
||||
this.placeSpinner({ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._okButton = this.addButton({ label: _("Authenticate"),
|
||||
action: Lang.bind(this, this._onAuthenticateButtonPressed),
|
||||
default: true },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.END });
|
||||
{ expand: false, x_fill: false, x_align: St.Align.END });
|
||||
|
||||
this._doneEmitted = false;
|
||||
|
||||
this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
|
||||
this._cookie = cookie;
|
||||
},
|
||||
|
||||
performAuthentication: function() {
|
||||
this.destroySession();
|
||||
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
|
||||
cookie: this._cookie });
|
||||
this._session.connect('completed', Lang.bind(this, this._onSessionCompleted));
|
||||
this._session.connect('request', Lang.bind(this, this._onSessionRequest));
|
||||
this._session.connect('show-error', Lang.bind(this, this._onSessionShowError));
|
||||
this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo));
|
||||
},
|
||||
|
||||
startAuthentication: function() {
|
||||
this._session.initiate();
|
||||
},
|
||||
|
||||
@@ -202,14 +207,14 @@ const AuthenticationDialog = new Lang.Class({
|
||||
log('polkitAuthenticationAgent: Failed to show modal dialog.' +
|
||||
' Dismissing authentication request for action-id ' + this.actionId +
|
||||
' cookie ' + this._cookie);
|
||||
this._emitDone(false, true);
|
||||
this._emitDone(true);
|
||||
}
|
||||
},
|
||||
|
||||
_emitDone: function(keepVisible, dismissed) {
|
||||
_emitDone: function(dismissed) {
|
||||
if (!this._doneEmitted) {
|
||||
this._doneEmitted = true;
|
||||
this.emit('done', keepVisible, dismissed);
|
||||
this.emit('done', dismissed);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -219,6 +224,7 @@ const AuthenticationDialog = new Lang.Class({
|
||||
|
||||
this._okButton.can_focus = sensitive;
|
||||
this._okButton.reactive = sensitive;
|
||||
this.setWorking(!sensitive);
|
||||
},
|
||||
|
||||
_onEntryActivate: function() {
|
||||
@@ -237,12 +243,16 @@ const AuthenticationDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_onSessionCompleted: function(session, gainedAuthorization) {
|
||||
if (this._completed)
|
||||
if (this._completed || this._doneEmitted)
|
||||
return;
|
||||
|
||||
this._completed = true;
|
||||
|
||||
if (!gainedAuthorization) {
|
||||
/* Yay, all done */
|
||||
if (gainedAuthorization) {
|
||||
this._emitDone(false);
|
||||
|
||||
} else {
|
||||
/* Unless we are showing an existing error message from the PAM
|
||||
* module (the PAM module could be reporting the authentication
|
||||
* error providing authentication-method specific information),
|
||||
@@ -258,8 +268,10 @@ const AuthenticationDialog = new Lang.Class({
|
||||
this._infoMessageLabel.hide();
|
||||
this._nullMessageLabel.hide();
|
||||
}
|
||||
|
||||
/* Try and authenticate again */
|
||||
this.performAuthentication();
|
||||
}
|
||||
this._emitDone(!gainedAuthorization, false);
|
||||
},
|
||||
|
||||
_onSessionRequest: function(session, request, echo_on) {
|
||||
@@ -303,6 +315,7 @@ const AuthenticationDialog = new Lang.Class({
|
||||
if (this._session) {
|
||||
if (!this._completed)
|
||||
this._session.cancel();
|
||||
this._completed = false;
|
||||
this._session = null;
|
||||
}
|
||||
},
|
||||
@@ -317,7 +330,7 @@ const AuthenticationDialog = new Lang.Class({
|
||||
cancel: function() {
|
||||
this._wasDismissed = true;
|
||||
this.close(global.get_current_time());
|
||||
this._emitDone(false, true);
|
||||
this._emitDone(true);
|
||||
},
|
||||
});
|
||||
Signals.addSignalMethods(AuthenticationDialog.prototype);
|
||||
@@ -327,7 +340,6 @@ const AuthenticationAgent = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
this._currentDialog = null;
|
||||
this._isCompleting = false;
|
||||
this._handle = null;
|
||||
this._native = new Shell.PolkitAuthenticationAgent();
|
||||
this._native.connect('initiate', Lang.bind(this, this._onInitiate));
|
||||
@@ -364,45 +376,24 @@ const AuthenticationAgent = new Lang.Class({
|
||||
// discussion.
|
||||
|
||||
this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone));
|
||||
this._currentDialog.startAuthentication();
|
||||
this._currentDialog.performAuthentication();
|
||||
},
|
||||
|
||||
_onCancel: function(nativeAgent) {
|
||||
this._completeRequest(false, false);
|
||||
this._completeRequest(false);
|
||||
},
|
||||
|
||||
_onDialogDone: function(dialog, keepVisible, dismissed) {
|
||||
this._completeRequest(keepVisible, dismissed);
|
||||
_onDialogDone: function(dialog, dismissed) {
|
||||
this._completeRequest(dismissed);
|
||||
},
|
||||
|
||||
_reallyCompleteRequest: function(dismissed) {
|
||||
_completeRequest: function(dismissed) {
|
||||
this._currentDialog.close();
|
||||
this._currentDialog.destroySession();
|
||||
this._currentDialog = null;
|
||||
this._isCompleting = false;
|
||||
|
||||
this._native.complete(dismissed)
|
||||
this._native.complete(dismissed);
|
||||
},
|
||||
|
||||
_completeRequest: function(keepVisible, wasDismissed) {
|
||||
if (this._isCompleting)
|
||||
return;
|
||||
|
||||
this._isCompleting = true;
|
||||
|
||||
if (keepVisible) {
|
||||
// Give the user 2 seconds to read 'Authentication Failure' before
|
||||
// dismissing the dialog
|
||||
Mainloop.timeout_add(2000,
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
this._reallyCompleteRequest(wasDismissed);
|
||||
return false;
|
||||
}));
|
||||
} else {
|
||||
this._reallyCompleteRequest(wasDismissed);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const Component = AuthenticationAgent;
|
||||
|
@@ -18,7 +18,7 @@ const Params = imports.misc.params;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
// See Notification.appendMessage
|
||||
const SCROLLBACK_IMMEDIATE_TIME = 60; // 1 minute
|
||||
const SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes
|
||||
const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
|
||||
const SCROLLBACK_RECENT_LENGTH = 20;
|
||||
const SCROLLBACK_IDLE_LENGTH = 5;
|
||||
@@ -967,7 +967,8 @@ const ChatNotification = new Lang.Class({
|
||||
let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate),
|
||||
group: 'meta',
|
||||
styles: ['chat-meta-message'],
|
||||
childProps: { expand: true, x_fill: false },
|
||||
childProps: { expand: true, x_fill: false,
|
||||
x_align: St.Align.END },
|
||||
noTimestamp: true,
|
||||
timestamp: lastMessageTime });
|
||||
|
||||
|
@@ -89,19 +89,25 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
let items = this._items.filter(function (item) { return item.proxy.mapped; });
|
||||
|
||||
// And add the windows metacity would show in its Ctrl-Alt-Tab list
|
||||
if (!Main.overview.visible) {
|
||||
if (Main.sessionMode.hasWindows && !Main.overview.visible) {
|
||||
let screen = global.screen;
|
||||
let display = screen.get_display();
|
||||
let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ());
|
||||
let windowTracker = Shell.WindowTracker.get_default();
|
||||
let textureCache = St.TextureCache.get_default();
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let icon;
|
||||
let app = windowTracker.get_window_app(windows[i]);
|
||||
if (app)
|
||||
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
|
||||
else
|
||||
icon = textureCache.bind_pixbuf_property(windows[i], 'icon');
|
||||
let icon = null;
|
||||
let iconName = null;
|
||||
if (windows[i].get_window_type () == Meta.WindowType.DESKTOP) {
|
||||
iconName = 'video-display-symbolic';
|
||||
} else {
|
||||
let app = windowTracker.get_window_app(windows[i]);
|
||||
if (app)
|
||||
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
|
||||
else
|
||||
icon = textureCache.bind_pixbuf_property(windows[i], 'icon');
|
||||
}
|
||||
|
||||
items.push({ name: windows[i].title,
|
||||
proxy: windows[i].get_compositor_private(),
|
||||
focusCallback: Lang.bind(windows[i],
|
||||
@@ -109,6 +115,7 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
Main.activateWindow(this, timestamp);
|
||||
}),
|
||||
iconActor: icon,
|
||||
iconName: iconName,
|
||||
sortGroup: SortGroup.MIDDLE });
|
||||
}
|
||||
}
|
||||
|
@@ -326,6 +326,16 @@ const DragPlaceholderItem = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const EmptyDropTargetItem = new Lang.Class({
|
||||
Name: 'EmptyDropTargetItem',
|
||||
Extends: DashItemContainer,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
|
||||
}
|
||||
});
|
||||
|
||||
const DashActor = new Lang.Class({
|
||||
Name: 'DashActor',
|
||||
Extends: St.Widget,
|
||||
@@ -441,6 +451,12 @@ const Dash = new Lang.Class({
|
||||
dragMotion: Lang.bind(this, this._onDragMotion)
|
||||
};
|
||||
DND.addDragMonitor(this._dragMonitor);
|
||||
|
||||
if (this._box.get_n_children() == 0) {
|
||||
this._emptyDropTarget = new EmptyDropTargetItem();
|
||||
this._box.insert_child_at_index(this._emptyDropTarget, 0);
|
||||
this._emptyDropTarget.show(true);
|
||||
}
|
||||
},
|
||||
|
||||
_onDragCancelled: function() {
|
||||
@@ -457,6 +473,7 @@ const Dash = new Lang.Class({
|
||||
|
||||
_endDrag: function() {
|
||||
this._clearDragPlaceholder();
|
||||
this._clearEmptyDropTarget();
|
||||
this._showAppsIcon.setDragApp(null);
|
||||
DND.removeDragMonitor(this._dragMonitor);
|
||||
},
|
||||
@@ -797,9 +814,21 @@ const Dash = new Lang.Class({
|
||||
|
||||
_clearDragPlaceholder: function() {
|
||||
if (this._dragPlaceholder) {
|
||||
this._animatingPlaceholdersCount++;
|
||||
this._dragPlaceholder.animateOutAndDestroy();
|
||||
this._dragPlaceholder.connect('destroy',
|
||||
Lang.bind(this, function() {
|
||||
this._animatingPlaceholdersCount--;
|
||||
}));
|
||||
this._dragPlaceholder = null;
|
||||
this._dragPlaceholderPos = -1;
|
||||
}
|
||||
this._dragPlaceholderPos = -1;
|
||||
},
|
||||
|
||||
_clearEmptyDropTarget: function() {
|
||||
if (this._emptyDropTarget) {
|
||||
this._emptyDropTarget.animateOutAndDestroy();
|
||||
this._emptyDropTarget = null;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -827,23 +856,18 @@ const Dash = new Lang.Class({
|
||||
numChildren--;
|
||||
}
|
||||
|
||||
let pos = Math.floor(y * numChildren / boxHeight);
|
||||
let pos;
|
||||
if (!this._emptyDropTarget)
|
||||
pos = Math.floor(y * numChildren / boxHeight);
|
||||
else
|
||||
pos = 0; // always insert at the top when dash is empty
|
||||
|
||||
if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
|
||||
this._dragPlaceholderPos = pos;
|
||||
|
||||
// Don't allow positioning before or after self
|
||||
if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
|
||||
if (this._dragPlaceholder) {
|
||||
this._dragPlaceholder.animateOutAndDestroy();
|
||||
this._animatingPlaceholdersCount++;
|
||||
this._dragPlaceholder.connect('destroy',
|
||||
Lang.bind(this, function() {
|
||||
this._animatingPlaceholdersCount--;
|
||||
}));
|
||||
}
|
||||
this._dragPlaceholder = null;
|
||||
|
||||
this._clearDragPlaceholder();
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
}
|
||||
|
||||
@@ -868,9 +892,9 @@ const Dash = new Lang.Class({
|
||||
|
||||
// Remove the drag placeholder if we are not in the
|
||||
// "favorites zone"
|
||||
if (pos > numFavorites && this._dragPlaceholder) {
|
||||
if (pos > numFavorites)
|
||||
this._clearDragPlaceholder();
|
||||
}
|
||||
|
||||
if (!this._dragPlaceholder)
|
||||
return DND.DragMotionResult.NO_DROP;
|
||||
|
||||
|
@@ -100,7 +100,6 @@ const DateMenuButton = new Lang.Class({
|
||||
|
||||
Shell.AppSystem.get_default().connect('installed-changed',
|
||||
Lang.bind(this, this._appInstalledChanged));
|
||||
this._appInstalledChanged();
|
||||
|
||||
item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop');
|
||||
if (item) {
|
||||
@@ -157,14 +156,16 @@ const DateMenuButton = new Lang.Class({
|
||||
},
|
||||
|
||||
_appInstalledChanged: function() {
|
||||
let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
|
||||
this._openClocksItem.actor.visible = app !== null;
|
||||
this._calendarApp = undefined;
|
||||
this._updateEventsVisibility();
|
||||
},
|
||||
|
||||
_updateEventsVisibility: function() {
|
||||
let visible = this._eventSource.hasCalendars;
|
||||
this._openCalendarItem.actor.visible = visible;
|
||||
this._openClocksItem.actor.visible = visible;
|
||||
this._openCalendarItem.actor.visible = visible &&
|
||||
(this._getCalendarApp() != null);
|
||||
this._openClocksItem.actor.visible = visible &&
|
||||
(this._getClockApp() != null);
|
||||
this._separator.visible = visible;
|
||||
if (visible) {
|
||||
let alignment = 0.25;
|
||||
@@ -217,10 +218,26 @@ const DateMenuButton = new Lang.Class({
|
||||
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
|
||||
},
|
||||
|
||||
_getCalendarApp: function() {
|
||||
if (this._calendarApp !== undefined)
|
||||
return this._calendarApp;
|
||||
|
||||
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
|
||||
if (apps && (apps.length > 0))
|
||||
this._calendarApp = apps[0];
|
||||
else
|
||||
this._calendarApp = null;
|
||||
return this._calendarApp;
|
||||
},
|
||||
|
||||
_getClockApp: function() {
|
||||
return Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
|
||||
},
|
||||
|
||||
_onOpenCalendarActivate: function() {
|
||||
this.menu.close();
|
||||
|
||||
let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
|
||||
let app = this._getCalendarApp();
|
||||
if (app.get_id() == 'evolution.desktop')
|
||||
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
|
||||
app.launch([], global.create_app_launch_context());
|
||||
@@ -228,7 +245,7 @@ const DateMenuButton = new Lang.Class({
|
||||
|
||||
_onOpenClocksActivate: function() {
|
||||
this.menu.close();
|
||||
let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
|
||||
let app = this._getClockApp();
|
||||
app.activate();
|
||||
}
|
||||
});
|
||||
|
@@ -149,16 +149,16 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
_grabEvents: function() {
|
||||
if (!this._eventsGrabbed) {
|
||||
Clutter.grab_pointer(_getEventHandlerActor());
|
||||
Clutter.grab_keyboard(_getEventHandlerActor());
|
||||
this._eventsGrabbed = true;
|
||||
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
|
||||
if (this._eventsGrabbed)
|
||||
Clutter.grab_pointer(_getEventHandlerActor());
|
||||
}
|
||||
},
|
||||
|
||||
_ungrabEvents: function() {
|
||||
if (this._eventsGrabbed) {
|
||||
Clutter.ungrab_pointer();
|
||||
Clutter.ungrab_keyboard();
|
||||
Main.popModal(_getEventHandlerActor());
|
||||
this._eventsGrabbed = false;
|
||||
}
|
||||
},
|
||||
|
@@ -420,6 +420,7 @@ const EndSessionDialog = new Lang.Class({
|
||||
_startTimer: function() {
|
||||
let startTime = GLib.get_monotonic_time();
|
||||
this._secondsLeft = this._totalSecondsToStayOpen;
|
||||
this._updateDescription();
|
||||
|
||||
this._timerId = Mainloop.timeout_add_seconds(1, Lang.bind(this,
|
||||
function() {
|
||||
|
@@ -5,6 +5,8 @@ imports.gi.versions.Gio = '2.0';
|
||||
imports.gi.versions.Gdk = '3.0';
|
||||
imports.gi.versions.GdkPixbuf = '2.0';
|
||||
imports.gi.versions.Gtk = '3.0';
|
||||
imports.gi.versions.TelepathyGLib = '0.12';
|
||||
imports.gi.versions.TelepathyLogger = '0.2';
|
||||
|
||||
const Clutter = imports.gi.Clutter;;
|
||||
const Gettext = imports.gettext;
|
||||
|
@@ -118,22 +118,6 @@ const MonitorConstraint = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const Monitor = new Lang.Class({
|
||||
Name: 'Monitor',
|
||||
|
||||
_init: function(index, geometry) {
|
||||
this.index = index;
|
||||
this.x = geometry.x;
|
||||
this.y = geometry.y;
|
||||
this.width = geometry.width;
|
||||
this.height = geometry.height;
|
||||
},
|
||||
|
||||
get inFullscreen() {
|
||||
return global.screen.get_monitor_in_fullscreen(this.index);
|
||||
}
|
||||
})
|
||||
|
||||
const defaultParams = {
|
||||
trackFullscreen: false,
|
||||
affectsStruts: false,
|
||||
@@ -277,7 +261,7 @@ const LayoutManager = new Lang.Class({
|
||||
this.monitors = [];
|
||||
let nMonitors = screen.get_n_monitors();
|
||||
for (let i = 0; i < nMonitors; i++)
|
||||
this.monitors.push(new Monitor(i, screen.get_monitor_geometry(i)));
|
||||
this.monitors.push(screen.get_monitor_geometry(i));
|
||||
|
||||
if (nMonitors == 1) {
|
||||
this.primaryIndex = this.bottomIndex = 0;
|
||||
@@ -299,10 +283,8 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
_updateHotCorners: function() {
|
||||
// destroy old hot corners
|
||||
this.hotCorners.forEach(function(corner) {
|
||||
if (corner)
|
||||
corner.destroy();
|
||||
});
|
||||
for (let i = 0; i < this.hotCorners.length; i++)
|
||||
this.hotCorners[i].destroy();
|
||||
this.hotCorners = [];
|
||||
|
||||
let size = this.panelBox.height;
|
||||
@@ -313,9 +295,9 @@ const LayoutManager = new Lang.Class({
|
||||
let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
|
||||
let cornerY = monitor.y;
|
||||
|
||||
let haveTopLeftCorner = true;
|
||||
|
||||
if (i != this.primaryIndex) {
|
||||
let haveTopLeftCorner = true;
|
||||
|
||||
// Check if we have a top left (right for RTL) corner.
|
||||
// I.e. if there is no monitor directly above or to the left(right)
|
||||
let besideX = this._rtl ? monitor.x + 1 : cornerX - 1;
|
||||
@@ -342,15 +324,14 @@ const LayoutManager = new Lang.Class({
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!haveTopLeftCorner)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (haveTopLeftCorner) {
|
||||
let corner = new HotCorner(this, monitor, cornerX, cornerY);
|
||||
corner.setBarrierSize(size);
|
||||
this.hotCorners.push(corner);
|
||||
} else {
|
||||
this.hotCorners.push(null);
|
||||
}
|
||||
let corner = new HotCorner(this, monitor, cornerX, cornerY);
|
||||
corner.setBarrierSize(size);
|
||||
this.hotCorners.push(corner);
|
||||
}
|
||||
|
||||
this.emit('hot-corners-changed');
|
||||
@@ -366,7 +347,7 @@ const LayoutManager = new Lang.Class({
|
||||
BackgroundMenu.addBackgroundMenu(bgManager.background.actor);
|
||||
}));
|
||||
|
||||
this._bgManagers.push(bgManager);
|
||||
this._bgManagers[monitorIndex] = bgManager;
|
||||
|
||||
return bgManager.background;
|
||||
},
|
||||
@@ -427,8 +408,7 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
let size = this.panelBox.height;
|
||||
this.hotCorners.forEach(function(corner) {
|
||||
if (corner)
|
||||
corner.setBarrierSize(size);
|
||||
corner.setBarrierSize(size);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -748,6 +728,8 @@ const LayoutManager = new Lang.Class({
|
||||
// and shown otherwise)
|
||||
addChrome: function(actor, params) {
|
||||
this.uiGroup.add_actor(actor);
|
||||
if (this.uiGroup.contains(global.top_window_group))
|
||||
this.uiGroup.set_child_below_sibling(actor, global.top_window_group);
|
||||
this._trackActor(actor, params);
|
||||
},
|
||||
|
||||
@@ -920,8 +902,13 @@ const LayoutManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateFullscreen: function() {
|
||||
for (let i = 0; i < this.monitors.length; i++)
|
||||
this.monitors[i].inFullscreen = global.screen.get_monitor_in_fullscreen (i);
|
||||
|
||||
this._updateVisibility();
|
||||
this._queueUpdateRegions();
|
||||
|
||||
this.emit('fullscreen-changed');
|
||||
},
|
||||
|
||||
_windowsRestacked: function() {
|
||||
|
@@ -38,12 +38,8 @@ const Magnifier = imports.ui.magnifier;
|
||||
const XdndHandler = imports.ui.xdndHandler;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
|
||||
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
|
||||
|
||||
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
|
||||
const STICKY_KEYS_ENABLE = 'stickykeys-enable';
|
||||
|
||||
let componentManager = null;
|
||||
let panel = null;
|
||||
let overview = null;
|
||||
@@ -71,8 +67,7 @@ let layoutManager = null;
|
||||
let _startDate;
|
||||
let _defaultCssStylesheet = null;
|
||||
let _cssStylesheet = null;
|
||||
let _overridesSettings = null;
|
||||
let _a11ySettings = null;
|
||||
let _workspacesSettings = null;
|
||||
|
||||
function _sessionUpdated() {
|
||||
_loadDefaultStylesheet();
|
||||
@@ -110,6 +105,7 @@ function start() {
|
||||
|
||||
function _sessionsLoaded() {
|
||||
sessionMode.connect('updated', _sessionUpdated);
|
||||
_initializePrefs();
|
||||
_initializeUI();
|
||||
|
||||
shellDBusService = new ShellDBus.GnomeShell();
|
||||
@@ -118,6 +114,21 @@ function _sessionsLoaded() {
|
||||
_sessionUpdated();
|
||||
}
|
||||
|
||||
function _initializePrefs() {
|
||||
let keys = new Gio.Settings({ schema: sessionMode.overridesSchema }).list_keys();
|
||||
for (let i = 0; i < keys.length; i++)
|
||||
Meta.prefs_override_preference_schema (keys[i], sessionMode.overridesSchema);
|
||||
|
||||
let workspacesSchema;
|
||||
if (keys.indexOf('dynamic-workspaces') > -1)
|
||||
workspacesSchema = sessionMode.overridesSchema;
|
||||
else
|
||||
workspacesSchema = 'org.gnome.mutter';
|
||||
|
||||
_workspacesSettings = new Gio.Settings({ schema: workspacesSchema });
|
||||
_workspacesSettings.connect('changed::dynamic-workspaces', _queueCheckWorkspaces);
|
||||
}
|
||||
|
||||
function _initializeUI() {
|
||||
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
|
||||
// also initialize ShellAppSystem first. ShellAppSystem
|
||||
@@ -161,14 +172,9 @@ function _initializeUI() {
|
||||
layoutManager.init();
|
||||
overview.init();
|
||||
|
||||
_a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA });
|
||||
|
||||
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
|
||||
false, -1, 1);
|
||||
global.display.connect('overlay-key', Lang.bind(overview, function () {
|
||||
if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE))
|
||||
overview.toggle();
|
||||
}));
|
||||
global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
|
||||
|
||||
// Provide the bus object for gnome-session to
|
||||
// initiate logouts.
|
||||
@@ -188,9 +194,6 @@ function _initializeUI() {
|
||||
Scripting.runPerfScript(module, perfOutput);
|
||||
}
|
||||
|
||||
_overridesSettings = new Gio.Settings({ schema: OVERRIDES_SCHEMA });
|
||||
_overridesSettings.connect('changed::dynamic-workspaces', _queueCheckWorkspaces);
|
||||
|
||||
global.screen.connect('notify::n-workspaces', _nWorkspacesChanged);
|
||||
|
||||
global.screen.connect('window-entered-monitor', _windowEnteredMonitor);
|
||||
|
@@ -1530,11 +1530,7 @@ const MessageTrayContextMenu = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateClearSensitivity: function() {
|
||||
let sources = this._tray.getSources();
|
||||
sources = sources.filter(function(source) {
|
||||
return !source.trayIcon && !source.isChat && !source.resident;
|
||||
});
|
||||
this._clearItem.setSensitive(sources.length > 0);
|
||||
this._clearItem.setSensitive(this._tray.clearableCount > 0);
|
||||
},
|
||||
|
||||
setPosition: function(x, y) {
|
||||
@@ -1557,22 +1553,23 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
this.actor = new St.Widget({ name: 'message-tray',
|
||||
reactive: true,
|
||||
track_hover: true,
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.START,
|
||||
});
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this._onTrayHoverChanged));
|
||||
|
||||
this._notificationWidget = new St.Widget({ name: 'notification-container',
|
||||
reactive: true,
|
||||
track_hover: true,
|
||||
y_align: Clutter.ActorAlign.START,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_expand: true,
|
||||
x_expand: true,
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
this._notificationWidget.connect('key-release-event', Lang.bind(this, this._onNotificationKeyRelease));
|
||||
this._notificationWidget.connect('notify::hover', Lang.bind(this, this._onNotificationHoverChanged));
|
||||
|
||||
this.actor.add_actor(this._notificationWidget);
|
||||
|
||||
this._notificationBin = new St.Bin({ y_expand: true });
|
||||
this._notificationBin.set_y_align(Clutter.ActorAlign.START);
|
||||
@@ -1627,25 +1624,24 @@ const MessageTray = new Lang.Class({
|
||||
{ keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY });
|
||||
this._grabHelper.addActor(this._summaryBoxPointer.actor);
|
||||
this._grabHelper.addActor(this.actor);
|
||||
this._grabHelper.addActor(this._notificationWidget);
|
||||
|
||||
Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, this._onKeyboardVisibleChanged));
|
||||
|
||||
this._trayState = State.HIDDEN;
|
||||
this._traySummoned = false;
|
||||
this._useLongerNotificationLeftTimeout = false;
|
||||
this._useLongerTrayLeftTimeout = false;
|
||||
this._trayLeftTimeoutId = 0;
|
||||
|
||||
// pointerInNotification is sort of a misnomer -- it tracks whether
|
||||
// pointerInTray is sort of a misnomer -- it tracks whether
|
||||
// a message tray notification should expand. The value is
|
||||
// partially driven by the hover state of the notification, but has
|
||||
// partially driven by the hover state of the tray, but has
|
||||
// a lot of complex state related to timeouts and the current
|
||||
// state of the pointer when a notification pops up.
|
||||
this._pointerInNotification = false;
|
||||
this._pointerInTray = false;
|
||||
|
||||
// This tracks this._notificationWidget.hover and is used to fizzle
|
||||
// out non-changing hover notifications in onNotificationHoverChanged.
|
||||
this._notificationHovered = false;
|
||||
// This tracks this.actor.hover and is used to fizzle
|
||||
// out non-changing hover notifications in onTrayHoverChanged.
|
||||
this._trayHovered = false;
|
||||
|
||||
this._keyboardVisible = false;
|
||||
this._notificationClosed = false;
|
||||
@@ -1657,9 +1653,12 @@ const MessageTray = new Lang.Class({
|
||||
this._desktopCloneState = State.HIDDEN;
|
||||
this._notificationRemoved = false;
|
||||
this._reNotifyAfterHideNotification = null;
|
||||
this._inFullscreen = false;
|
||||
this._desktopClone = null;
|
||||
this._inCtrlAltTab = false;
|
||||
|
||||
this.clearableCount = 0;
|
||||
|
||||
this._lightbox = new Lightbox.Lightbox(global.overlay_group,
|
||||
{ inhibitEvents: true,
|
||||
fadeInTime: ANIMATION_TIME,
|
||||
@@ -1668,12 +1667,11 @@ const MessageTray = new Lang.Class({
|
||||
});
|
||||
|
||||
Main.layoutManager.trayBox.add_actor(this.actor);
|
||||
Main.layoutManager.trayBox.add_actor(this._notificationWidget);
|
||||
Main.layoutManager.trackChrome(this.actor);
|
||||
Main.layoutManager.trackChrome(this._notificationWidget);
|
||||
Main.layoutManager.trackChrome(this._closeButton);
|
||||
|
||||
global.screen.connect('in-fullscreen-changed', Lang.bind(this, this._updateState));
|
||||
Main.layoutManager.connect('fullscreen-changed', Lang.bind(this, this._updateState));
|
||||
Main.layoutManager.connect('hot-corners-changed', Lang.bind(this, this._hotCornersChanged));
|
||||
|
||||
// If the overview shows or hides while we're in
|
||||
@@ -1721,6 +1719,9 @@ const MessageTray = new Lang.Class({
|
||||
this.actor.add_action(clickAction);
|
||||
|
||||
clickAction.connect('clicked', Lang.bind(this, function(action) {
|
||||
if (this._trayState != State.SHOWN)
|
||||
return;
|
||||
|
||||
let button = action.get_button();
|
||||
if (button == 3)
|
||||
this._openContextMenu();
|
||||
@@ -1731,7 +1732,7 @@ const MessageTray = new Lang.Class({
|
||||
clickAction.connect('long-press', Lang.bind(this, function(action, actor, state) {
|
||||
switch (state) {
|
||||
case Clutter.LongPressState.QUERY:
|
||||
return true;
|
||||
return this._trayState == State.SHOWN;
|
||||
case Clutter.LongPressState.ACTIVATE:
|
||||
this._openContextMenu();
|
||||
}
|
||||
@@ -1747,7 +1748,7 @@ const MessageTray = new Lang.Class({
|
||||
let [x, y, mask] = global.get_pointer();
|
||||
this._contextMenu.setPosition(Math.round(x), Math.round(y));
|
||||
this._grabHelper.grab({ actor: this._contextMenu.actor,
|
||||
modal: true,
|
||||
grabFocus: true,
|
||||
onUngrab: Lang.bind(this, function () {
|
||||
this._contextMenu.close(BoxPointer.PopupAnimation.FULL);
|
||||
})
|
||||
@@ -1793,12 +1794,12 @@ const MessageTray = new Lang.Class({
|
||||
y == monitor.y + monitor.height - 1);
|
||||
if (shouldDwell) {
|
||||
// We only set up dwell timeout when the user is not hovering over the tray
|
||||
// (!this._notificationHovered). This avoids bringing up the message tray after the
|
||||
// (!this.actor.hover). This avoids bringing up the message tray after the
|
||||
// user clicks on a notification with the pointer on the bottom pixel
|
||||
// of the monitor. The _trayDwelling variable is used so that we only try to
|
||||
// fire off one tray dwell - if it fails (because, say, the user has the mouse down),
|
||||
// we don't try again until the user moves the mouse up and down again.
|
||||
if (!this._trayDwelling && !this._notificationHovered && this._trayDwellTimeoutId == 0) {
|
||||
if (!this._trayDwelling && !this.actor.hover && this._trayDwellTimeoutId == 0) {
|
||||
// Save the interaction timestamp so we can detect user input
|
||||
let focusWindow = global.display.focus_window;
|
||||
this._trayDwellUserTime = focusWindow ? focusWindow.user_time : 0;
|
||||
@@ -1896,6 +1897,9 @@ const MessageTray = new Lang.Class({
|
||||
this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount);
|
||||
}
|
||||
|
||||
if (!source.trayIcon && !source.isChat && !source.resident)
|
||||
this.clearableCount++;
|
||||
|
||||
this._sources.set(source, obj);
|
||||
|
||||
obj.notifyId = source.connect('notify', Lang.bind(this, this._onNotify));
|
||||
@@ -1937,6 +1941,9 @@ const MessageTray = new Lang.Class({
|
||||
if (source.isChat)
|
||||
this._chatSummaryItemsCount--;
|
||||
|
||||
if (!source.trayIcon && !source.isChat && !source.resident)
|
||||
this.clearableCount--;
|
||||
|
||||
source.disconnect(obj.notifyId);
|
||||
source.disconnect(obj.destroyId);
|
||||
source.disconnect(obj.mutedChangedId);
|
||||
@@ -2021,6 +2028,7 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
hide: function() {
|
||||
this._traySummoned = false;
|
||||
this.actor.set_hover(false);
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
@@ -2087,21 +2095,25 @@ const MessageTray = new Lang.Class({
|
||||
this._grabHelper.addActor(corner.actor);
|
||||
},
|
||||
|
||||
_onNotificationHoverChanged: function() {
|
||||
if (this._notificationWidget.hover == this._notificationHovered)
|
||||
_onTrayHoverChanged: function() {
|
||||
if (this.actor.hover == this._trayHovered)
|
||||
return;
|
||||
|
||||
this._notificationHovered = this._notificationWidget.hover;
|
||||
if (this._notificationHovered) {
|
||||
this._trayHovered = this.actor.hover;
|
||||
if (this._trayHovered) {
|
||||
// No dwell inside notifications at the bottom of the screen
|
||||
this._cancelTrayDwell();
|
||||
|
||||
this._useLongerNotificationLeftTimeout = false;
|
||||
if (this._notificationLeftTimeoutId) {
|
||||
Mainloop.source_remove(this._notificationLeftTimeoutId);
|
||||
this._notificationLeftTimeoutId = 0;
|
||||
this._notificationLeftMouseX = -1;
|
||||
this._notificationLeftMouseY = -1;
|
||||
// Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
|
||||
if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
|
||||
return;
|
||||
|
||||
this._useLongerTrayLeftTimeout = false;
|
||||
if (this._trayLeftTimeoutId) {
|
||||
Mainloop.source_remove(this._trayLeftTimeoutId);
|
||||
this._trayLeftTimeoutId = 0;
|
||||
this._trayLeftMouseX = -1;
|
||||
this._trayLeftMouseY = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2110,32 +2122,32 @@ const MessageTray = new Lang.Class({
|
||||
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, this._showNotificationMouseX, this._showNotificationMouseY);
|
||||
this._showNotificationMouseX = -1;
|
||||
this._showNotificationMouseY = -1;
|
||||
// Don't set this._pointerInNotification to true if the pointer was initially in the area where the notification
|
||||
// Don't set this._pointerInTray to true if the pointer was initially in the area where the notification
|
||||
// popped up. That way we will not be expanding notifications that happen to pop up over the pointer
|
||||
// automatically. Instead, the user is able to expand the notification by mousing away from it and then
|
||||
// mousing back in. Because this is an expected action, we set the boolean flag that indicates that a longer
|
||||
// timeout should be used before popping down the notification.
|
||||
if (this.actor.contains(actorAtShowNotificationPosition)) {
|
||||
this._useLongerNotificationLeftTimeout = true;
|
||||
this._useLongerTrayLeftTimeout = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._pointerInNotification = true;
|
||||
this._pointerInTray = true;
|
||||
this._updateState();
|
||||
} else {
|
||||
// We record the position of the mouse the moment it leaves the tray. These coordinates are used in
|
||||
// this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us
|
||||
// this._onTrayLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us
|
||||
// to consider that the user intended to leave the tray and therefore hide the tray. If the mouse is still
|
||||
// close to its previous position, we extend the timeout once.
|
||||
let [x, y, mods] = global.get_pointer();
|
||||
this._notificationLeftMouseX = x;
|
||||
this._notificationLeftMouseY = y;
|
||||
this._trayLeftMouseX = x;
|
||||
this._trayLeftMouseY = y;
|
||||
|
||||
// We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it.
|
||||
// We wait for a longer period if the notification popped up where the mouse pointer was already positioned.
|
||||
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
|
||||
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
|
||||
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout));
|
||||
let timeout = this._useLongerTrayLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
|
||||
this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2159,22 +2171,22 @@ const MessageTray = new Lang.Class({
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
_onNotificationLeftTimeout: function() {
|
||||
_onTrayLeftTimeout: function() {
|
||||
let [x, y, mods] = global.get_pointer();
|
||||
// We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side or up.
|
||||
// We don't check how far down the mouse moved because any point above the tray, but below the exit coordinate,
|
||||
// is close to the tray.
|
||||
if (this._notificationLeftMouseX > -1 &&
|
||||
y > this._notificationLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD &&
|
||||
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
|
||||
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
|
||||
this._notificationLeftMouseX = -1;
|
||||
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
|
||||
Lang.bind(this, this._onNotificationLeftTimeout));
|
||||
if (this._trayLeftMouseX > -1 &&
|
||||
y > this._trayLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD &&
|
||||
x < this._trayLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
|
||||
x > this._trayLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
|
||||
this._trayLeftMouseX = -1;
|
||||
this._trayLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
|
||||
Lang.bind(this, this._onTrayLeftTimeout));
|
||||
} else {
|
||||
this._notificationLeftTimeoutId = 0;
|
||||
this._useLongerNotificationLeftTimeout = false;
|
||||
this._pointerInNotification = false;
|
||||
this._trayLeftTimeoutId = 0;
|
||||
this._useLongerTrayLeftTimeout = false;
|
||||
this._pointerInTray = false;
|
||||
this._updateNotificationTimeout(0);
|
||||
this._updateState();
|
||||
}
|
||||
@@ -2182,7 +2194,7 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_escapeTray: function() {
|
||||
this._pointerInNotification = false;
|
||||
this._pointerInTray = false;
|
||||
this._traySummoned = false;
|
||||
this._setClickedSummaryItem(null);
|
||||
this._updateNotificationTimeout(0);
|
||||
@@ -2191,7 +2203,7 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
// All of the logic for what happens when occurs here; the various
|
||||
// event handlers merely update variables such as
|
||||
// 'this._pointerInNotification', 'this._traySummoned', etc, and
|
||||
// 'this._pointerInTray', 'this._traySummoned', etc, and
|
||||
// _updateState() figures out what (if anything) needs to be done
|
||||
// at the present time.
|
||||
_updateState: function() {
|
||||
@@ -2202,12 +2214,12 @@ const MessageTray = new Lang.Class({
|
||||
let notificationsLimited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen;
|
||||
let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && Main.sessionMode.hasNotifications;
|
||||
let nextNotification = notificationQueue.length > 0 ? notificationQueue[0] : null;
|
||||
let notificationPinned = this._pointerInNotification && !this._notificationRemoved;
|
||||
let notificationPinned = this._pointerInTray && !this._notificationRemoved;
|
||||
let notificationExpanded = this._notification && this._notification.expanded;
|
||||
let notificationExpired = this._notificationTimeoutId == 0 &&
|
||||
!(this._notification && this._notification.urgency == Urgency.CRITICAL) &&
|
||||
!(this._notification && this._notification.focused) &&
|
||||
!this._pointerInNotification;
|
||||
!this._pointerInTray;
|
||||
let notificationLockedOut = !Main.sessionMode.hasNotifications && this._notification;
|
||||
let notificationMustClose = this._notificationRemoved || notificationLockedOut || (notificationExpired && this._userActiveWhileNotificationShown) || this._notificationClosed;
|
||||
let canShowNotification = notificationsPending && this._trayState == State.HIDDEN;
|
||||
@@ -2237,10 +2249,15 @@ const MessageTray = new Lang.Class({
|
||||
let canShowSummaryBoxPointer = this._trayState == State.SHOWN;
|
||||
// We only have sources with empty notification stacks for legacy tray icons. Currently, we never attempt
|
||||
// to show notifications for legacy tray icons, but this would be necessary if we did.
|
||||
let requestedNotificationStackIsEmpty = (this._clickedSummaryItemMouseButton == 1 && this._clickedSummaryItem.source.notifications.length == 0);
|
||||
let wrongSummaryNotificationStack = (this._clickedSummaryItemMouseButton == 1 &&
|
||||
let requestedNotificationStackIsEmpty = (haveClickedSummaryItem &&
|
||||
this._clickedSummaryItemMouseButton == 1 &&
|
||||
this._clickedSummaryItem.source.notifications.length == 0);
|
||||
let wrongSummaryNotificationStack = (haveClickedSummaryItem &&
|
||||
this._clickedSummaryItemMouseButton == 1 &&
|
||||
this._summaryBoxPointer.bin.child != this._clickedSummaryItem.notificationStackWidget);
|
||||
let wrongSummaryRightClickMenu = (this._clickedSummaryItemMouseButton == 3 &&
|
||||
let wrongSummaryRightClickMenu = (haveClickedSummaryItem &&
|
||||
this._clickedSummaryItemMouseButton == 3 &&
|
||||
this._clickedSummaryItem.rightClickMenu != null &&
|
||||
this._summaryBoxPointer.bin.child != this._clickedSummaryItem.rightClickMenu);
|
||||
let wrongSummaryBoxPointer = (haveClickedSummaryItem &&
|
||||
(wrongSummaryNotificationStack || wrongSummaryRightClickMenu));
|
||||
@@ -2420,7 +2437,7 @@ const MessageTray = new Lang.Class({
|
||||
let [x, y, mods] = global.get_pointer();
|
||||
// We save the position of the mouse at the time when we started showing the notification
|
||||
// in order to determine if the notification popped up under it. We make that check if
|
||||
// the user starts moving the mouse and _onNotificationHoverChanged() gets called. We don't
|
||||
// the user starts moving the mouse and _onTrayHoverChanged() gets called. We don't
|
||||
// expand the notification if it just happened to pop up under the mouse unless the user
|
||||
// explicitly mouses away from it and then mouses back in.
|
||||
this._showNotificationMouseX = x;
|
||||
@@ -2482,13 +2499,13 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
_notificationTimeout: function() {
|
||||
let [x, y, mods] = global.get_pointer();
|
||||
if (y > this._lastSeenMouseY + 10 && !this._notificationHovered) {
|
||||
if (y > this._lastSeenMouseY + 10 && !this.actor.hover) {
|
||||
// The mouse is moving towards the notification, so don't
|
||||
// hide it yet. (We just create a new timeout (and destroy
|
||||
// the old one) each time because the bookkeeping is
|
||||
// simpler.)
|
||||
this._updateNotificationTimeout(1000);
|
||||
} else if (this._useLongerNotificationLeftTimeout && !this._notificationLeftTimeoutId &&
|
||||
} else if (this._useLongerTrayLeftTimeout && !this._trayLeftTimeoutId &&
|
||||
(x != this._lastSeenMouseX || y != this._lastSeenMouseY)) {
|
||||
// Refresh the timeout if the notification originally
|
||||
// popped up under the pointer, and the pointer is hovering
|
||||
@@ -2532,12 +2549,12 @@ const MessageTray = new Lang.Class({
|
||||
this._notificationUnfocusedId = 0;
|
||||
}
|
||||
|
||||
this._useLongerNotificationLeftTimeout = false;
|
||||
if (this._notificationLeftTimeoutId) {
|
||||
Mainloop.source_remove(this._notificationLeftTimeoutId);
|
||||
this._notificationLeftTimeoutId = 0;
|
||||
this._notificationLeftMouseX = -1;
|
||||
this._notificationLeftMouseY = -1;
|
||||
this._useLongerTrayLeftTimeout = false;
|
||||
if (this._trayLeftTimeoutId) {
|
||||
Mainloop.source_remove(this._trayLeftTimeoutId);
|
||||
this._trayLeftTimeoutId = 0;
|
||||
this._trayLeftMouseX = -1;
|
||||
this._trayLeftMouseY = -1;
|
||||
}
|
||||
|
||||
if (this._notificationRemoved) {
|
||||
@@ -2567,9 +2584,14 @@ const MessageTray = new Lang.Class({
|
||||
if (notification.isTransient)
|
||||
notification.destroy(NotificationDestroyedReason.EXPIRED);
|
||||
|
||||
this._closeButton.hide();
|
||||
this._pointerInNotification = false;
|
||||
this._notificationRemoved = false;
|
||||
this._closeButton.hide();
|
||||
this._pointerInTray = false;
|
||||
|
||||
// Clutter will send a leave-event the next time the mouse
|
||||
// moves, but we need to set this here now to update the
|
||||
// state machine.
|
||||
this.actor.hover = false;
|
||||
this._notificationBin.child = null;
|
||||
this._notificationWidget.hide();
|
||||
},
|
||||
@@ -2582,16 +2604,16 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_expandNotification: function(autoExpanding) {
|
||||
// Don't focus notifications that are auto-expanding.
|
||||
if (!autoExpanding)
|
||||
this._ensureNotificationFocused();
|
||||
|
||||
if (!this._notificationExpandedId)
|
||||
this._notificationExpandedId =
|
||||
this._notification.connect('expanded',
|
||||
Lang.bind(this, this._onNotificationExpanded));
|
||||
// Don't animate changes in notifications that are auto-expanding.
|
||||
this._notification.expand(!autoExpanding);
|
||||
|
||||
// Don't focus notifications that are auto-expanding.
|
||||
if (!autoExpanding)
|
||||
this._ensureNotificationFocused();
|
||||
},
|
||||
|
||||
_onNotificationExpanded: function() {
|
||||
@@ -2660,7 +2682,7 @@ const MessageTray = new Lang.Class({
|
||||
}
|
||||
|
||||
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
|
||||
modal: true,
|
||||
grabFocus: true,
|
||||
onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) });
|
||||
|
||||
this._summaryBoxPointer.actor.opacity = 0;
|
||||
|
@@ -22,6 +22,10 @@ const Tweener = imports.ui.tweener;
|
||||
const OPEN_AND_CLOSE_TIME = 0.1;
|
||||
const FADE_OUT_DIALOG_TIME = 1.0;
|
||||
|
||||
const WORK_SPINNER_ICON_SIZE = 24;
|
||||
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
const WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
const State = {
|
||||
OPENED: 0,
|
||||
CLOSED: 1,
|
||||
@@ -65,7 +69,9 @@ const ModalDialog = new Lang.Class({
|
||||
this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||
this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));
|
||||
|
||||
this._backgroundBin = new St.Bin();
|
||||
this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
this._backgroundBin = new St.Bin({ child: this.backgroundStack,
|
||||
x_fill: true, y_fill: true });
|
||||
this._monitorConstraint = new Layout.MonitorConstraint();
|
||||
this._backgroundBin.add_constraint(this._monitorConstraint);
|
||||
this._group.add_actor(this._backgroundBin);
|
||||
@@ -81,15 +87,10 @@ const ModalDialog = new Lang.Class({
|
||||
{ inhibitEvents: true });
|
||||
this._lightbox.highlight(this._backgroundBin);
|
||||
|
||||
let stack = new Shell.Stack();
|
||||
this._backgroundBin.child = stack;
|
||||
|
||||
this._eventBlocker = new Clutter.Actor({ reactive: true });
|
||||
stack.add_actor(this._eventBlocker);
|
||||
stack.add_actor(this.dialogLayout);
|
||||
} else {
|
||||
this._backgroundBin.child = this.dialogLayout;
|
||||
this.backgroundStack.add_actor(this._eventBlocker);
|
||||
}
|
||||
this.backgroundStack.add_actor(this.dialogLayout);
|
||||
|
||||
|
||||
this.contentLayout = new St.BoxLayout({ vertical: true });
|
||||
@@ -110,6 +111,8 @@ const ModalDialog = new Lang.Class({
|
||||
this._initialKeyFocus = this.dialogLayout;
|
||||
this._initialKeyFocusDestroyId = 0;
|
||||
this._savedKeyFocus = null;
|
||||
|
||||
this._workSpinner = null;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@@ -183,6 +186,44 @@ const ModalDialog = new Lang.Class({
|
||||
return button;
|
||||
},
|
||||
|
||||
placeSpinner: function(layoutInfo) {
|
||||
/* This is here because of recursive imports */
|
||||
const Panel = imports.ui.panel;
|
||||
let spinnerIcon = global.datadir + '/theme/process-working.svg';
|
||||
this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
this._workSpinner.actor.show();
|
||||
|
||||
this.buttonLayout.add(this._workSpinner.actor, layoutInfo);
|
||||
},
|
||||
|
||||
setWorking: function(working) {
|
||||
if (!this._workSpinner)
|
||||
return;
|
||||
|
||||
Tweener.removeTweens(this._workSpinner.actor);
|
||||
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() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyPressEvent: function(object, event) {
|
||||
this._pressedKey = event.get_key_symbol();
|
||||
},
|
||||
|
@@ -8,6 +8,7 @@ const Layout = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Meta = imports.gi.Meta;
|
||||
|
||||
const HIDE_TIMEOUT = 1500;
|
||||
const FADE_TIME = 0.1;
|
||||
@@ -71,6 +72,7 @@ const OsdWindow = new Lang.Class({
|
||||
Name: 'OsdWindow',
|
||||
|
||||
_init: function() {
|
||||
this._popupSize = 0;
|
||||
this.actor = new St.Widget({ x_expand: true,
|
||||
y_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
@@ -80,6 +82,15 @@ const OsdWindow = new Lang.Class({
|
||||
vertical: true });
|
||||
this.actor.add_actor(this._box);
|
||||
|
||||
this._box.connect('style-changed', Lang.bind(this, this._onStyleChanged));
|
||||
this._box.connect('notify::height', Lang.bind(this,
|
||||
function() {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
||||
function() {
|
||||
this._box.width = this._box.height;
|
||||
}));
|
||||
}));
|
||||
|
||||
this._icon = new St.Icon();
|
||||
this._box.add(this._icon, { expand: true });
|
||||
|
||||
@@ -125,8 +136,10 @@ const OsdWindow = new Lang.Class({
|
||||
return;
|
||||
|
||||
if (!this.actor.visible) {
|
||||
Meta.disable_unredirect_for_screen(global.screen);
|
||||
this.actor.show();
|
||||
this.actor.opacity = 0;
|
||||
this.actor.get_parent().set_child_above_sibling(this.actor, null);
|
||||
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 255,
|
||||
@@ -154,7 +167,11 @@ const OsdWindow = new Lang.Class({
|
||||
{ opacity: 0,
|
||||
time: FADE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, this._reset) });
|
||||
onComplete: Lang.bind(this, function() {
|
||||
this._reset();
|
||||
Meta.enable_unredirect_for_screen(global.screen);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
@@ -169,11 +186,25 @@ const OsdWindow = new Lang.Class({
|
||||
let scalew = monitor.width / 640.0;
|
||||
let scaleh = monitor.height / 480.0;
|
||||
let scale = Math.min(scalew, scaleh);
|
||||
let size = 110 * Math.max(1, scale);
|
||||
this._popupSize = 110 * Math.max(1, scale);
|
||||
|
||||
this._box.set_size(size, size);
|
||||
this._box.translation_y = monitor.height / 4;
|
||||
this._icon.icon_size = this._popupSize / 2;
|
||||
this._box.style_changed();
|
||||
},
|
||||
|
||||
this._icon.icon_size = size / 2;
|
||||
_onStyleChanged: function() {
|
||||
let themeNode = this._box.get_theme_node();
|
||||
let horizontalPadding = themeNode.get_horizontal_padding();
|
||||
let verticalPadding = themeNode.get_vertical_padding();
|
||||
let topBorder = themeNode.get_border_width(St.Side.TOP);
|
||||
let bottomBorder = themeNode.get_border_width(St.Side.BOTTOM);
|
||||
let leftBorder = themeNode.get_border_width(St.Side.LEFT);
|
||||
let rightBorder = themeNode.get_border_width(St.Side.RIGHT);
|
||||
|
||||
let minWidth = this._popupSize - verticalPadding - leftBorder - rightBorder;
|
||||
let minHeight = this._popupSize - horizontalPadding - topBorder - bottomBorder;
|
||||
|
||||
this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight));
|
||||
}
|
||||
});
|
||||
|
@@ -11,6 +11,7 @@ const Shell = imports.gi.Shell;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
|
||||
const Background = imports.ui.background;
|
||||
const Dash = imports.ui.dash;
|
||||
const DND = imports.ui.dnd;
|
||||
const LayoutManager = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
@@ -19,6 +20,7 @@ const OverviewControls = imports.ui.overviewControls;
|
||||
const Panel = imports.ui.panel;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
|
||||
// Time for initial animation going into Overview mode
|
||||
@@ -29,7 +31,7 @@ const ANIMATION_TIME = 0.25;
|
||||
// and don't want the shading animation to get cut off
|
||||
const SHADE_ANIMATION_TIME = .20;
|
||||
|
||||
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
|
||||
const DND_WINDOW_SWITCH_TIMEOUT = 750;
|
||||
|
||||
const OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
|
||||
|
||||
@@ -131,6 +133,14 @@ const Overview = new Lang.Class({
|
||||
y_expand: true });
|
||||
this._overview._delegate = this;
|
||||
|
||||
this._groupStack = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true,
|
||||
clip_to_allocation: true });
|
||||
this._group = new St.BoxLayout({ name: 'overview-group',
|
||||
reactive: true,
|
||||
x_expand: true, y_expand: true });
|
||||
this._groupStack.add_actor(this._group);
|
||||
|
||||
this._backgroundGroup = new Meta.BackgroundGroup();
|
||||
global.overlay_group.add_child(this._backgroundGroup);
|
||||
this._backgroundGroup.hide();
|
||||
@@ -167,6 +177,7 @@ const Overview = new Lang.Class({
|
||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
|
||||
global.screen.connect('restacked', Lang.bind(this, this._onRestacked));
|
||||
this._group.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._windowSwitchTimestamp = 0;
|
||||
@@ -265,13 +276,28 @@ const Overview = new Lang.Class({
|
||||
this._overview.add_actor(this._searchEntryBin);
|
||||
|
||||
// Create controls
|
||||
this._controls = new OverviewControls.ControlsManager(this._searchEntry);
|
||||
this._dash = this._controls.dash;
|
||||
this._viewSelector = this._controls.viewSelector;
|
||||
this._dash = new Dash.Dash();
|
||||
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
|
||||
this._dash.showAppsButton);
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
this._controls = new OverviewControls.ControlsManager(this._dash,
|
||||
this._thumbnailsBox,
|
||||
this._viewSelector);
|
||||
|
||||
this._controls.dashActor.x_align = Clutter.ActorAlign.START;
|
||||
this._controls.dashActor.y_expand = true;
|
||||
|
||||
// Put the dash in a separate layer to allow content to be centered
|
||||
this._groupStack.add_actor(this._controls.dashActor);
|
||||
|
||||
// Pack all the actors into the group
|
||||
this._group.add_actor(this._controls.dashSpacer);
|
||||
this._group.add(this._viewSelector.actor, { x_fill: true,
|
||||
expand: true });
|
||||
this._group.add_actor(this._controls.thumbnailsActor);
|
||||
|
||||
// Add our same-line elements after the search entry
|
||||
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
|
||||
this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
this._overview.add(this._groupStack, { y_fill: true, expand: true });
|
||||
|
||||
this._stack.add_actor(this._controls.indicatorActor);
|
||||
|
||||
@@ -435,6 +461,7 @@ const Overview = new Lang.Class({
|
||||
|
||||
beginItemDrag: function(source) {
|
||||
this.emit('item-drag-begin');
|
||||
this._inDrag = true;
|
||||
},
|
||||
|
||||
cancelledItemDrag: function(source) {
|
||||
@@ -443,10 +470,12 @@ const Overview = new Lang.Class({
|
||||
|
||||
endItemDrag: function(source) {
|
||||
this.emit('item-drag-end');
|
||||
this._inDrag = false;
|
||||
},
|
||||
|
||||
beginWindowDrag: function(source) {
|
||||
this.emit('window-drag-begin');
|
||||
this._inDrag = true;
|
||||
},
|
||||
|
||||
cancelledWindowDrag: function(source) {
|
||||
@@ -455,6 +484,7 @@ const Overview = new Lang.Class({
|
||||
|
||||
endWindowDrag: function(source) {
|
||||
this.emit('window-drag-end');
|
||||
this._inDrag = false;
|
||||
},
|
||||
|
||||
// show:
|
||||
@@ -473,6 +503,11 @@ const Overview = new Lang.Class({
|
||||
this._animateVisible();
|
||||
},
|
||||
|
||||
focusSearch: function() {
|
||||
this.show();
|
||||
this._searchEntry.grab_key_focus();
|
||||
},
|
||||
|
||||
fadeInDesktop: function() {
|
||||
this._desktopFade.opacity = 0;
|
||||
this._desktopFade.show();
|
||||
@@ -578,6 +613,8 @@ const Overview = new Lang.Class({
|
||||
shouldToggleByCornerOrButton: function() {
|
||||
if (this.animationInProgress)
|
||||
return false;
|
||||
if (this._inDrag)
|
||||
return false;
|
||||
if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
|
||||
return true;
|
||||
return false;
|
||||
|
@@ -6,12 +6,10 @@ const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Dash = imports.ui.dash;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
|
||||
const SIDE_CONTROLS_ANIMATION_TIME = 0.16;
|
||||
|
||||
@@ -271,11 +269,6 @@ const ThumbnailsSlider = new Lang.Class({
|
||||
return alwaysZoomOut;
|
||||
},
|
||||
|
||||
getNonExpandedWidth: function() {
|
||||
let child = this.actor.get_first_child();
|
||||
return child.get_theme_node().get_length('visible-width');
|
||||
},
|
||||
|
||||
getSlide: function() {
|
||||
if (!this.visible)
|
||||
return 0;
|
||||
@@ -287,16 +280,18 @@ const ThumbnailsSlider = new Lang.Class({
|
||||
let child = this.actor.get_first_child();
|
||||
let preferredHeight = child.get_preferred_height(-1)[1];
|
||||
let expandedWidth = child.get_preferred_width(preferredHeight)[1];
|
||||
let visibleWidth = child.get_theme_node().get_length('visible-width');
|
||||
|
||||
return this.getNonExpandedWidth() / expandedWidth;
|
||||
return visibleWidth / expandedWidth;
|
||||
},
|
||||
|
||||
getVisibleWidth: function() {
|
||||
let alwaysZoomOut = this._getAlwaysZoomOut();
|
||||
if (alwaysZoomOut)
|
||||
return this.parent();
|
||||
else
|
||||
return this.getNonExpandedWidth();
|
||||
|
||||
let child = this.actor.get_first_child();
|
||||
return child.get_theme_node().get_length('visible-width');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -314,10 +309,6 @@ const DashSlider = new Lang.Class({
|
||||
// available allocation
|
||||
this._dash.actor.x_expand = true;
|
||||
this._dash.actor.y_expand = true;
|
||||
|
||||
this.actor.x_align = Clutter.ActorAlign.START;
|
||||
this.actor.y_expand = true;
|
||||
|
||||
this.actor.add_actor(this._dash.actor);
|
||||
|
||||
this._dash.connect('icon-size-changed', Lang.bind(this, this.updateSlide));
|
||||
@@ -488,77 +479,39 @@ const MessagesIndicator = new Lang.Class({
|
||||
const ControlsManager = new Lang.Class({
|
||||
Name: 'ControlsManager',
|
||||
|
||||
_init: function(searchEntry) {
|
||||
this.dash = new Dash.Dash();
|
||||
this._dashSlider = new DashSlider(this.dash);
|
||||
this._dashSpacer = new DashSpacer();
|
||||
this._dashSpacer.setDashActor(this._dashSlider.actor);
|
||||
_init: function(dash, thumbnails, viewSelector) {
|
||||
this._dashSlider = new DashSlider(dash);
|
||||
this.dashActor = this._dashSlider.actor;
|
||||
this.dashSpacer = new DashSpacer();
|
||||
this.dashSpacer.setDashActor(this.dashActor);
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox);
|
||||
this._thumbnailsSlider = new ThumbnailsSlider(thumbnails);
|
||||
this.thumbnailsActor = this._thumbnailsSlider.actor;
|
||||
|
||||
this.viewSelector = new ViewSelector.ViewSelector(searchEntry,
|
||||
this.dash.showAppsButton);
|
||||
this.viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
|
||||
this.viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
|
||||
|
||||
this._indicator = new MessagesIndicator(this.viewSelector);
|
||||
this._indicator = new MessagesIndicator(viewSelector);
|
||||
this.indicatorActor = this._indicator.actor;
|
||||
|
||||
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true,
|
||||
clip_to_allocation: true });
|
||||
this._group = new St.BoxLayout({ name: 'overview-group',
|
||||
reactive: true,
|
||||
x_expand: true, y_expand: true });
|
||||
this.actor.add_actor(this._group);
|
||||
|
||||
this.actor.add_actor(this._dashSlider.actor);
|
||||
|
||||
this._group.add_actor(this._dashSpacer);
|
||||
this._group.add(this.viewSelector.actor, { x_fill: true,
|
||||
expand: true });
|
||||
this._group.add_actor(this._thumbnailsSlider.actor);
|
||||
|
||||
this._group.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesGeometry));
|
||||
this._viewSelector = viewSelector;
|
||||
this._viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
|
||||
this._viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
|
||||
|
||||
Main.overview.connect('showing', Lang.bind(this, this._updateSpacerVisibility));
|
||||
Main.overview.connect('item-drag-begin', Lang.bind(this,
|
||||
function() {
|
||||
let activePage = this.viewSelector.getActivePage();
|
||||
let activePage = this._viewSelector.getActivePage();
|
||||
if (activePage != ViewSelector.ViewPage.WINDOWS)
|
||||
this.viewSelector.fadeHalf();
|
||||
this._viewSelector.fadeHalf();
|
||||
}));
|
||||
Main.overview.connect('item-drag-end', Lang.bind(this,
|
||||
function() {
|
||||
this.viewSelector.fadeIn();
|
||||
this._viewSelector.fadeIn();
|
||||
}));
|
||||
Main.overview.connect('item-drag-cancelled', Lang.bind(this,
|
||||
function() {
|
||||
this.viewSelector.fadeIn();
|
||||
this._viewSelector.fadeIn();
|
||||
}));
|
||||
},
|
||||
|
||||
_updateWorkspacesGeometry: function() {
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
let [width, height] = this.actor.get_transformed_size();
|
||||
let geometry = { x: x, y: y, width: width, height: height };
|
||||
|
||||
let spacing = this.actor.get_theme_node().get_length('spacing');
|
||||
let dashWidth = this._dashSlider.getVisibleWidth() + spacing;
|
||||
let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing;
|
||||
|
||||
geometry.width -= dashWidth;
|
||||
geometry.width -= thumbnailsWidth;
|
||||
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.LTR)
|
||||
geometry.x += dashWidth;
|
||||
else
|
||||
geometry.x += thumbnailsWidth;
|
||||
|
||||
this.viewSelector.setWorkspacesFullGeometry(geometry);
|
||||
},
|
||||
|
||||
_setVisibility: function() {
|
||||
// Ignore the case when we're leaving the overview, since
|
||||
// actors will be made visible again when entering the overview
|
||||
@@ -568,7 +521,7 @@ const ControlsManager = new Lang.Class({
|
||||
(Main.overview.animationInProgress && !Main.overview.visibleTarget))
|
||||
return;
|
||||
|
||||
let activePage = this.viewSelector.getActivePage();
|
||||
let activePage = this._viewSelector.getActivePage();
|
||||
let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS ||
|
||||
activePage == ViewSelector.ViewPage.APPS);
|
||||
let thumbnailsVisible = (activePage == ViewSelector.ViewPage.WINDOWS);
|
||||
@@ -588,8 +541,8 @@ const ControlsManager = new Lang.Class({
|
||||
if (Main.overview.animationInProgress && !Main.overview.visibleTarget)
|
||||
return;
|
||||
|
||||
let activePage = this.viewSelector.getActivePage();
|
||||
this._dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS);
|
||||
let activePage = this._viewSelector.getActivePage();
|
||||
this.dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS);
|
||||
},
|
||||
|
||||
_onPageEmpty: function() {
|
||||
|
@@ -371,13 +371,16 @@ const AppMenuButton = new Lang.Class({
|
||||
this._updateIconBoxClip();
|
||||
},
|
||||
|
||||
_syncIcon: function() {
|
||||
let icon = this._targetApp.get_faded_icon(2 * PANEL_ICON_SIZE, this._iconBox.text_direction);
|
||||
this._iconBox.set_child(icon);
|
||||
},
|
||||
|
||||
_onIconThemeChanged: function() {
|
||||
if (this._iconBox.child == null)
|
||||
return;
|
||||
|
||||
this._iconBox.child.destroy();
|
||||
let icon = this._targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
|
||||
this._iconBox.set_child(icon);
|
||||
this._syncIcon();
|
||||
},
|
||||
|
||||
_updateIconBoxClip: function() {
|
||||
@@ -568,14 +571,9 @@ const AppMenuButton = new Lang.Class({
|
||||
}
|
||||
|
||||
if (targetApp == this._targetApp) {
|
||||
if (targetApp &&
|
||||
targetApp.get_state() != Shell.AppState.STARTING &&
|
||||
targetApp.get_state() != Shell.AppState.BUSY) {
|
||||
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING) {
|
||||
this.stopAnimation();
|
||||
this._maybeSetMenu();
|
||||
} else if (targetApp &&
|
||||
targetApp.get_state() == Shell.AppState.BUSY) {
|
||||
this.startAnimation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -600,16 +598,13 @@ const AppMenuButton = new Lang.Class({
|
||||
}
|
||||
|
||||
this._targetApp = targetApp;
|
||||
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
|
||||
|
||||
this._label.setText(targetApp.get_name());
|
||||
this.setName(targetApp.get_name());
|
||||
|
||||
this._iconBox.set_child(icon);
|
||||
this._syncIcon();
|
||||
this._iconBox.show();
|
||||
|
||||
if (targetApp.get_state() == Shell.AppState.STARTING ||
|
||||
targetApp.get_state() == Shell.AppState.BUSY)
|
||||
if (targetApp.get_state() == Shell.AppState.STARTING)
|
||||
this.startAnimation();
|
||||
else
|
||||
this._maybeSetMenu();
|
||||
@@ -929,7 +924,6 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
|
||||
'volume': imports.ui.status.volume.Indicator,
|
||||
'battery': imports.ui.status.power.Indicator,
|
||||
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
|
||||
'logo': imports.gdm.loginDialog.LogoMenuButton,
|
||||
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
|
||||
'powerMenu': imports.gdm.powerMenu.PowerMenuButton,
|
||||
'userMenu': imports.ui.userMenu.UserMenuButton
|
||||
|
@@ -19,12 +19,6 @@ const Tweener = imports.ui.tweener;
|
||||
|
||||
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
|
||||
|
||||
const Ornament = {
|
||||
NONE: 0,
|
||||
DOT: 1,
|
||||
CHECK: 2,
|
||||
};
|
||||
|
||||
function _ensureStyle(actor) {
|
||||
if (actor.get_children) {
|
||||
let children = actor.get_children();
|
||||
@@ -59,9 +53,7 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
this.actor._delegate = this;
|
||||
|
||||
this._children = [];
|
||||
this._ornament = Ornament.NONE;
|
||||
this._ornamentLabel = new St.Label({ style_class: 'popup-menu-ornament' });
|
||||
this.actor.add_actor(this._ornamentLabel);
|
||||
this._dot = null;
|
||||
this._columnWidths = null;
|
||||
this._spacing = 0;
|
||||
this.active = false;
|
||||
@@ -184,24 +176,40 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
this._removeChild(child);
|
||||
},
|
||||
|
||||
setOrnament: function(ornament) {
|
||||
if (ornament == this._ornament)
|
||||
return;
|
||||
setShowDot: function(show) {
|
||||
if (show) {
|
||||
if (this._dot)
|
||||
return;
|
||||
|
||||
this._ornament = ornament;
|
||||
this._dot = new St.DrawingArea({ style_class: 'popup-menu-item-dot' });
|
||||
this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
|
||||
this.actor.add_actor(this._dot);
|
||||
this.actor.add_accessible_state (Atk.StateType.CHECKED);
|
||||
} else {
|
||||
if (!this._dot)
|
||||
return;
|
||||
|
||||
if (ornament == Ornament.DOT) {
|
||||
this._ornamentLabel.text = '\u2022';
|
||||
this.actor.add_accessible_state(Atk.StateType.CHECKED);
|
||||
} else if (ornament == Ornament.CHECK) {
|
||||
this._ornamentLabel.text = '\u2713';
|
||||
this.actor.add_accessible_state(Atk.StateType.CHECKED);
|
||||
} else if (ornament == Ornament.NONE) {
|
||||
this._ornamentLabel.text = '';
|
||||
this.actor.remove_accessible_state(Atk.StateType.CHECKED);
|
||||
this._dot.destroy();
|
||||
this._dot = null;
|
||||
this.actor.remove_accessible_state (Atk.StateType.CHECKED);
|
||||
}
|
||||
},
|
||||
|
||||
_onRepaintDot: function(area) {
|
||||
let cr = area.get_context();
|
||||
let [width, height] = area.get_surface_size();
|
||||
let color = area.get_theme_node().get_foreground_color();
|
||||
|
||||
cr.setSourceRGBA (
|
||||
color.red / 255,
|
||||
color.green / 255,
|
||||
color.blue / 255,
|
||||
color.alpha / 255);
|
||||
cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
cr.$dispose();
|
||||
},
|
||||
|
||||
// This returns column widths in logical order (i.e. from the dot
|
||||
// to the image), not in visual order (left to right)
|
||||
getColumnWidths: function() {
|
||||
@@ -272,25 +280,26 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
let height = box.y2 - box.y1;
|
||||
let direction = this.actor.get_text_direction();
|
||||
|
||||
// The ornament is placed outside box
|
||||
// one quarter of padding from the border of the container
|
||||
// (so 3/4 from the inner border)
|
||||
// (padding is box.x1)
|
||||
let ornamentBox = new Clutter.ActorBox();
|
||||
let ornamentWidth = box.x1;
|
||||
if (this._dot) {
|
||||
// The dot is placed outside box
|
||||
// one quarter of padding from the border of the container
|
||||
// (so 3/4 from the inner border)
|
||||
// (padding is box.x1)
|
||||
let dotBox = new Clutter.ActorBox();
|
||||
let dotWidth = Math.round(box.x1 / 2);
|
||||
|
||||
ornamentBox.x1 = 0;
|
||||
ornamentBox.x2 = ornamentWidth;
|
||||
ornamentBox.y1 = box.y1;
|
||||
ornamentBox.y2 = box.y2;
|
||||
|
||||
if (direction == Clutter.TextDirection.RTL) {
|
||||
ornamentBox.x1 += box.x2;
|
||||
ornamentBox.x2 += box.x2;
|
||||
if (direction == Clutter.TextDirection.LTR) {
|
||||
dotBox.x1 = Math.round(box.x1 / 4);
|
||||
dotBox.x2 = dotBox.x1 + dotWidth;
|
||||
} else {
|
||||
dotBox.x2 = box.x2 + 3 * Math.round(box.x1 / 4);
|
||||
dotBox.x1 = dotBox.x2 - dotWidth;
|
||||
}
|
||||
dotBox.y1 = Math.round(box.y1 + (height - dotWidth) / 2);
|
||||
dotBox.y2 = dotBox.y1 + dotWidth;
|
||||
this._dot.allocate(dotBox, flags);
|
||||
}
|
||||
|
||||
this._ornamentLabel.allocate(ornamentBox, flags);
|
||||
|
||||
let x;
|
||||
if (direction == Clutter.TextDirection.LTR)
|
||||
x = box.x1;
|
||||
@@ -544,6 +553,10 @@ const PopupSliderMenuItem = new Lang.Class({
|
||||
|
||||
let handleRadius = themeNode.get_length('-slider-handle-radius');
|
||||
|
||||
let handleBorderWidth = themeNode.get_length('-slider-handle-border-width');
|
||||
let [hasHandleColor, handleBorderColor] =
|
||||
themeNode.lookup_color('-slider-handle-border-color', false);
|
||||
|
||||
let sliderWidth = width - 2 * handleRadius;
|
||||
let sliderHeight = themeNode.get_length('-slider-height');
|
||||
|
||||
@@ -595,7 +608,16 @@ const PopupSliderMenuItem = new Lang.Class({
|
||||
color.blue / 255,
|
||||
color.alpha / 255);
|
||||
cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
cr.fillPreserve();
|
||||
if (hasHandleColor && handleBorderWidth) {
|
||||
cr.setSourceRGBA(
|
||||
handleBorderColor.red / 255,
|
||||
handleBorderColor.green / 255,
|
||||
handleBorderColor.blue / 255,
|
||||
handleBorderColor.alpha / 255);
|
||||
cr.setLineWidth(handleBorderWidth);
|
||||
cr.stroke();
|
||||
}
|
||||
cr.$dispose();
|
||||
},
|
||||
|
||||
@@ -1466,12 +1488,23 @@ const PopupMenuSection = new Lang.Class({
|
||||
this.actor = this.box;
|
||||
this.actor._delegate = this;
|
||||
this.isOpen = true;
|
||||
|
||||
// an array of externally managed separators
|
||||
this.separators = [];
|
||||
},
|
||||
|
||||
// deliberately ignore any attempt to open() or close(), but emit the
|
||||
// corresponding signal so children can still pick it up
|
||||
open: function() { this.emit('open-state-changed', true); },
|
||||
close: function() { this.emit('open-state-changed', false); },
|
||||
|
||||
destroy: function() {
|
||||
for (let i = 0; i < this.separators.length; i++)
|
||||
this.separators[i].destroy();
|
||||
this.separators = [];
|
||||
|
||||
this.parent();
|
||||
}
|
||||
});
|
||||
|
||||
const PopupSubMenuMenuItem = new Lang.Class({
|
||||
@@ -1788,11 +1821,13 @@ const RemoteMenu = new Lang.Class({
|
||||
this.model = model;
|
||||
this.actionGroup = actionGroup;
|
||||
|
||||
this._actions = {};
|
||||
this._trackMenu(model, this);
|
||||
this._actions = { };
|
||||
this._modelChanged(this.model, 0, 0, this.model.get_n_items(), this);
|
||||
|
||||
this._actionStateChangeId = this.actionGroup.connect('action-state-changed', Lang.bind(this, this._actionStateChanged));
|
||||
this._actionEnableChangeId = this.actionGroup.connect('action-enabled-changed', Lang.bind(this, this._actionEnabledChanged));
|
||||
|
||||
this._skipSignalConnection = false;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@@ -1809,8 +1844,39 @@ const RemoteMenu = new Lang.Class({
|
||||
this.parent();
|
||||
},
|
||||
|
||||
_actionAdded: function(model, item, index) {
|
||||
let action_id = item.action_id;
|
||||
_createMenuItem: function(model, index) {
|
||||
let labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null);
|
||||
let label = labelValue ? labelValue.deep_unpack() : '';
|
||||
// remove all underscores that are not followed by another underscore
|
||||
label = label.replace(/_([^_])/, '$1');
|
||||
|
||||
let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
|
||||
if (section_link) {
|
||||
let item = new PopupMenuSection();
|
||||
if (label) {
|
||||
let title = new PopupMenuItem(label, { reactive: false,
|
||||
style_class: 'popup-subtitle-menu-item' });
|
||||
item._titleMenuItem = title;
|
||||
title._ignored = true;
|
||||
item.addMenuItem(title);
|
||||
}
|
||||
this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
|
||||
return [item, true, ''];
|
||||
}
|
||||
|
||||
let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
|
||||
|
||||
if (submenu_link) {
|
||||
let item = new PopupSubMenuMenuItem(label);
|
||||
this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu);
|
||||
return [item, false, ''];
|
||||
}
|
||||
|
||||
let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
|
||||
if (!this.actionGroup.has_action(action_id)) {
|
||||
// the action may not be there yet, wait for action-added
|
||||
return [null, false, 'action-added::' + action_id];
|
||||
}
|
||||
|
||||
if (!this._actions[action_id])
|
||||
this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id),
|
||||
@@ -1818,7 +1884,7 @@ const RemoteMenu = new Lang.Class({
|
||||
items: [ ],
|
||||
};
|
||||
let action = this._actions[action_id];
|
||||
let target, destroyId, specificSignalId;
|
||||
let item, target, destroyId, specificSignalId;
|
||||
|
||||
if (action.state) {
|
||||
// Docs have get_state_hint(), except that the DBus protocol
|
||||
@@ -1829,28 +1895,28 @@ const RemoteMenu = new Lang.Class({
|
||||
|
||||
switch (String.fromCharCode(action.state.classify())) {
|
||||
case 'b':
|
||||
item = new PopupSwitchMenuItem(label, action.state.get_boolean());
|
||||
action.items.push(item);
|
||||
item.setOrnament(action.state.get_boolean() ?
|
||||
Ornament.CHECK : Ornament.NONE);
|
||||
specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
|
||||
specificSignalId = item.connect('toggled', Lang.bind(this, function(item) {
|
||||
this.actionGroup.activate_action(action_id, null);
|
||||
}));
|
||||
break;
|
||||
case 's':
|
||||
action.items.push(item);
|
||||
item = new PopupMenuItem(label);
|
||||
item._remoteTarget = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null).deep_unpack();
|
||||
item.setOrnament(action.state.deep_unpack() == item._remoteTarget ?
|
||||
Ornament.DOT : Ornament.NONE);
|
||||
action.items.push(item);
|
||||
item.setShowDot(action.state.deep_unpack() == item._remoteTarget);
|
||||
specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
|
||||
this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget));
|
||||
}));
|
||||
break;
|
||||
default:
|
||||
log('Action "%s" has state of type %s, which is not supported'.format(action_id, action.state.get_type_string()));
|
||||
return;
|
||||
return [null, false, 'action-state-changed::' + action_id];
|
||||
}
|
||||
} else {
|
||||
target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null);
|
||||
item = new PopupMenuItem(label);
|
||||
action.items.push(item);
|
||||
specificSignalId = item.connect('activate', Lang.bind(this, function() {
|
||||
this.actionGroup.activate_action(action_id, target);
|
||||
@@ -1867,52 +1933,97 @@ const RemoteMenu = new Lang.Class({
|
||||
if (pos != -1)
|
||||
action.items.splice(pos, 1);
|
||||
}));
|
||||
},
|
||||
|
||||
_trackMenu: function(model, item) {
|
||||
item._tracker = Shell.MenuTracker.new(model,
|
||||
null, /* action namespace */
|
||||
Lang.bind(this, this._insertItem, item),
|
||||
Lang.bind(this, this._removeItem, item));
|
||||
return [item, false, ''];
|
||||
},
|
||||
|
||||
item.connect('destroy', function() {
|
||||
item._tracker.destroy();
|
||||
item._tracker = null;
|
||||
});
|
||||
},
|
||||
_modelChanged: function(model, position, removed, added, target) {
|
||||
let j, k;
|
||||
let j0, k0;
|
||||
|
||||
_createMenuItem: function(model, index) {
|
||||
let labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null);
|
||||
let label = labelValue ? labelValue.deep_unpack() : '';
|
||||
// remove all underscores that are not followed by another underscore
|
||||
label = label.replace(/_([^_])/, '$1');
|
||||
let currentItems = target._getMenuItems();
|
||||
|
||||
let submenuModel = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
|
||||
if (submenuModel) {
|
||||
let item = new PopupSubMenuMenuItem(label);
|
||||
this._trackMenu(submenuModel, item.menu);
|
||||
return item;
|
||||
k0 = 0;
|
||||
// skip ignored items at the beginning
|
||||
while (k0 < currentItems.length && currentItems[k0]._ignored)
|
||||
k0++;
|
||||
// find the right menu item matching the model item
|
||||
for (j0 = 0; k0 < currentItems.length && j0 < position; j0++, k0++) {
|
||||
if (currentItems[k0]._ignored)
|
||||
k0++;
|
||||
}
|
||||
|
||||
let item = new PopupMenuItem(label);
|
||||
let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
|
||||
item.actor.can_focus = item.actor.reactive = false;
|
||||
if (removed == -1) {
|
||||
// special flag to indicate we should destroy everything
|
||||
for (k = k0; k < currentItems.length; k++)
|
||||
currentItems[k].destroy();
|
||||
} else {
|
||||
for (j = j0, k = k0; k < currentItems.length && j < j0 + removed; j++, k++) {
|
||||
currentItems[k].destroy();
|
||||
|
||||
item.action_id = action_id;
|
||||
|
||||
if (this.actionGroup.has_action(action_id)) {
|
||||
this._actionAdded(model, item, index);
|
||||
return item;
|
||||
if (currentItems[k]._ignored)
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
let signalId = this.actionGroup.connect('action-added', Lang.bind(this, function(actionGroup, actionName) {
|
||||
actionGroup.disconnect(signalId);
|
||||
if (this._actions[actionName]) return;
|
||||
for (j = j0, k = k0; j < j0 + added; j++, k++) {
|
||||
let [item, addSeparator, changeSignal] = this._createMenuItem(model, j);
|
||||
|
||||
this._actionAdded(model, item, index);
|
||||
}));
|
||||
if (item) {
|
||||
// separators must be added in the parent to make autohiding work
|
||||
if (addSeparator) {
|
||||
let separator = new PopupSeparatorMenuItem();
|
||||
item.separators.push(separator);
|
||||
separator._ignored = true;
|
||||
target.addMenuItem(separator, k+1);
|
||||
k++;
|
||||
}
|
||||
|
||||
return item;
|
||||
target.addMenuItem(item, k);
|
||||
|
||||
if (addSeparator) {
|
||||
let separator = new PopupSeparatorMenuItem();
|
||||
item.separators.push(separator);
|
||||
separator._ignored = true;
|
||||
target.addMenuItem(separator, k+1);
|
||||
k++;
|
||||
}
|
||||
} else if (changeSignal && !this._skipSignalConnection) {
|
||||
let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function(actionGroup, actionName) {
|
||||
actionGroup.disconnect(signalId);
|
||||
if (this._actions[actionName]) return;
|
||||
|
||||
/* force a full update but do not reconnect signals if other
|
||||
* actions are missing */
|
||||
this._skipSignalConnection = true;
|
||||
this._modelChanged(model, 0, -1, model.get_n_items(), target);
|
||||
this._skipSignalConnection = false;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (!model._changedId) {
|
||||
model._changedId = model.connect('items-changed', Lang.bind(this, this._modelChanged, target));
|
||||
model._destroyId = target.connect('destroy', function() {
|
||||
if (model._changedId)
|
||||
model.disconnect(model._changedId);
|
||||
if (model._destroyId)
|
||||
target.disconnect(model._destroyId);
|
||||
model._changedId = 0;
|
||||
model._destroyId = 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (target instanceof PopupMenuSection) {
|
||||
if (target._titleMenuItem)
|
||||
target.actor.visible = target.numMenuItems != 1;
|
||||
else
|
||||
target.actor.visible = target.numMenuItems != 0;
|
||||
} else {
|
||||
let sourceItem = target.sourceActor._delegate;
|
||||
if (sourceItem instanceof PopupSubMenuMenuItem)
|
||||
sourceItem.actor.visible = target.numMenuItems != 0;
|
||||
}
|
||||
},
|
||||
|
||||
_actionStateChanged: function(actionGroup, action_id) {
|
||||
@@ -1925,8 +2036,7 @@ const RemoteMenu = new Lang.Class({
|
||||
switch (String.fromCharCode(action.state.classify())) {
|
||||
case 'b':
|
||||
for (let i = 0; i < action.items.length; i++)
|
||||
action.items[i].setOrnament(action.state.get_boolean() ?
|
||||
Ornament.CHECK : Ornament.NONE);
|
||||
action.items[i].setToggleState(action.state.get_boolean());
|
||||
break;
|
||||
case 'd':
|
||||
for (let i = 0; i < action.items.length; i++)
|
||||
@@ -1934,8 +2044,7 @@ const RemoteMenu = new Lang.Class({
|
||||
break;
|
||||
case 's':
|
||||
for (let i = 0; i < action.items.length; i++)
|
||||
action.items[i].setOrnament(action.items[i]._remoteTarget == action.state.deep_unpack() ?
|
||||
Ornament.DOT : Ornament.NONE);
|
||||
action.items[i].setShowDot(action.items[i]._remoteTarget == action.state.deep_unpack());
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1952,23 +2061,7 @@ const RemoteMenu = new Lang.Class({
|
||||
item.actor.reactive = item.actor.can_focus = action.enabled;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_insertItem: function(position, model, item_index, action_namespace, is_separator, target) {
|
||||
let item;
|
||||
|
||||
if (is_separator)
|
||||
item = new PopupSeparatorMenuItem();
|
||||
else
|
||||
item = this._createMenuItem(model, item_index);
|
||||
|
||||
target.addMenuItem(item, position);
|
||||
},
|
||||
|
||||
_removeItem: function(position, target) {
|
||||
let items = target._getMenuItems();
|
||||
items[position].destroy();
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/* Basic implementation of a menu manager.
|
||||
@@ -2013,7 +2106,7 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
removeMenu: function(menu) {
|
||||
if (menu == this.activeMenu)
|
||||
this._closeMenu(menu);
|
||||
this._closeMenu(false, menu);
|
||||
|
||||
let position = this._findMenu(menu);
|
||||
if (position == -1) // not a menu we manage
|
||||
@@ -2049,7 +2142,7 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
_onMenuOpenState: function(menu, open) {
|
||||
if (open) {
|
||||
if (this.activeMenu)
|
||||
if (this.activeMenu && !this.activeMenu.isChildMenu(menu))
|
||||
this.activeMenu.close(BoxPointer.PopupAnimation.FADE);
|
||||
this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor,
|
||||
onUngrab: Lang.bind(this, this._closeMenu, menu) });
|
||||
|
@@ -187,9 +187,7 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
|
||||
createIcon: function(size, meta) {
|
||||
let gicon;
|
||||
if (meta['icon']) {
|
||||
gicon = Gio.icon_deserialize(meta['icon']);
|
||||
} else if (meta['gicon']) {
|
||||
if (meta['gicon']) {
|
||||
gicon = Gio.icon_new_for_string(meta['gicon']);
|
||||
} else if (meta['icon-data']) {
|
||||
let [width, height, rowStride, hasAlpha,
|
||||
@@ -242,12 +240,8 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
let metas = results[0];
|
||||
let resultMetas = [];
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
for (let prop in metas[i]) {
|
||||
// we can use the serialized icon variant directly
|
||||
if (prop != 'icon')
|
||||
metas[i][prop] = metas[i][prop].deep_unpack();
|
||||
}
|
||||
|
||||
for (let prop in metas[i])
|
||||
metas[i][prop] = metas[i][prop].deep_unpack();
|
||||
resultMetas.push({ id: metas[i]['id'],
|
||||
name: metas[i]['name'],
|
||||
description: metas[i]['description'],
|
||||
|
@@ -478,6 +478,7 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
this._lockDialogGroup = new St.Widget({ x_expand: true,
|
||||
y_expand: true,
|
||||
reactive: true,
|
||||
opacity: 0,
|
||||
pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
|
||||
name: 'lockDialogGroup' });
|
||||
@@ -709,6 +710,8 @@ const ScreenShield = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDragEnd: function(action, actor, eventX, eventY, modifiers) {
|
||||
if (this._lockScreenState != MessageTray.State.HIDING)
|
||||
return;
|
||||
if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) {
|
||||
// Complete motion automatically
|
||||
let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
|
||||
@@ -1115,6 +1118,9 @@ const ScreenShield = new Lang.Class({
|
||||
deactivate: function(animate) {
|
||||
this._hideLockScreen(animate, 0);
|
||||
|
||||
if (this._hasLockScreen)
|
||||
this._clearLockScreen();
|
||||
|
||||
if (Main.sessionMode.currentMode == 'lock-screen')
|
||||
Main.sessionMode.popMode('lock-screen');
|
||||
if (Main.sessionMode.currentMode == 'unlock-dialog')
|
||||
@@ -1131,9 +1137,6 @@ const ScreenShield = new Lang.Class({
|
||||
},
|
||||
|
||||
_completeDeactivate: function() {
|
||||
if (this._hasLockScreen)
|
||||
this._clearLockScreen();
|
||||
|
||||
if (this._dialog && !this._isGreeter) {
|
||||
this._dialog.destroy();
|
||||
this._dialog = null;
|
||||
@@ -1200,6 +1203,12 @@ const ScreenShield = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the clipboard - otherwise, its contents may be leaked
|
||||
// to unauthorized parties by pasting into the unlock dialog's
|
||||
// password entry and unmasking the entry
|
||||
St.Clipboard.get_default().set_text(St.ClipboardType.CLIPBOARD, '');
|
||||
St.Clipboard.get_default().set_text(St.ClipboardType.PRIMARY, '');
|
||||
|
||||
this._isLocked = true;
|
||||
this.activate(animate);
|
||||
|
||||
|
140
js/ui/screencast.js
Normal file
140
js/ui/screencast.js
Normal file
@@ -0,0 +1,140 @@
|
||||
// -*- 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 Shell = imports.gi.Shell;
|
||||
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ScreencastIface = <interface name="org.gnome.Shell.Screencast">
|
||||
<method name="Screencast">
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="ScreencastArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="StopScreencast">
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
const ScreencastService = new Lang.Class({
|
||||
Name: 'ScreencastService',
|
||||
|
||||
_init: function() {
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreencastIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screencast');
|
||||
|
||||
Gio.DBus.session.own_name('org.gnome.Shell.Screencast', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
|
||||
this._recorders = new Hash.Map();
|
||||
|
||||
Main.sessionMode.connect('updated',
|
||||
Lang.bind(this, this._sessionModeChanged));
|
||||
},
|
||||
|
||||
_ensureRecorderForSender: function(sender) {
|
||||
let recorder = this._recorders.get(sender);
|
||||
if (!recorder) {
|
||||
recorder = new Shell.Recorder({ stage: global.stage });
|
||||
recorder._watchNameId =
|
||||
Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
|
||||
Lang.bind(this, this._onNameVanished));
|
||||
this._recorders.set(sender, recorder);
|
||||
}
|
||||
return recorder;
|
||||
},
|
||||
|
||||
_sessionModeChanged: function() {
|
||||
if (Main.sessionMode.allowScreencast)
|
||||
return;
|
||||
|
||||
for (let sender in this._recorders.keys())
|
||||
this._recorders.delete(sender);
|
||||
},
|
||||
|
||||
_onNameVanished: function(connection, name) {
|
||||
this._stopRecordingForSender(name);
|
||||
},
|
||||
|
||||
_stopRecordingForSender: function(sender) {
|
||||
let recorder = this._recorders.get(sender);
|
||||
if (!recorder)
|
||||
return false;
|
||||
|
||||
Gio.bus_unwatch_name(recorder._watchNameId);
|
||||
recorder.close();
|
||||
this._recorders.delete(sender);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_applyOptionalParameters: function(recorder, options) {
|
||||
for (let option in options)
|
||||
options[option] = options[option].deep_unpack();
|
||||
|
||||
if (options['pipeline'])
|
||||
recorder.set_pipeline(options['pipeline']);
|
||||
if (options['framerate'])
|
||||
recorder.set_framerate(options['framerate']);
|
||||
if (options['draw-cursor'])
|
||||
recorder.set_draw_cursor(options['draw-cursor']);
|
||||
},
|
||||
|
||||
ScreencastAsync: function(params, invocation) {
|
||||
let returnValue = [false, ''];
|
||||
if (!Main.sessionMode.allowScreencast)
|
||||
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||
|
||||
let sender = invocation.get_sender();
|
||||
let recorder = this._ensureRecorderForSender(sender);
|
||||
if (!recorder.is_recording()) {
|
||||
let [fileTemplate, options] = params;
|
||||
|
||||
recorder.set_file_template(fileTemplate);
|
||||
this._applyOptionalParameters(recorder, options);
|
||||
let [success, fileName] = recorder.record();
|
||||
returnValue = [success, fileName ? fileName : ''];
|
||||
}
|
||||
|
||||
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||
},
|
||||
|
||||
ScreencastAreaAsync: function(params, invocation) {
|
||||
let returnValue = [false, ''];
|
||||
if (!Main.sessionMode.allowScreencast)
|
||||
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||
|
||||
let sender = invocation.get_sender();
|
||||
let recorder = this._ensureRecorderForSender(sender);
|
||||
|
||||
if (!recorder.is_recording()) {
|
||||
let [x, y, width, height, fileTemplate, options] = params;
|
||||
|
||||
recorder.set_file_template(fileTemplate);
|
||||
recorder.set_area(x, y, width, height);
|
||||
this._applyOptionalParameters(recorder, options);
|
||||
let [success, fileName] = recorder.record();
|
||||
returnValue = [success, fileName ? fileName : ''];
|
||||
}
|
||||
|
||||
invocation.return_value(GLib.Variant.new('(bs)', returnValue));
|
||||
},
|
||||
|
||||
StopScreencastAsync: function(params, invocation) {
|
||||
let success = this._stopRecordingForSender(invocation.get_sender());
|
||||
invocation.return_value(GLib.Variant.new('(b)', [success]));
|
||||
}
|
||||
});
|
@@ -16,6 +16,7 @@ const _modes = {
|
||||
'restrictive': {
|
||||
parentMode: null,
|
||||
stylesheetName: 'gnome-shell.css',
|
||||
overridesSchema: 'org.gnome.shell.overrides',
|
||||
hasOverview: false,
|
||||
showCalendarEvents: false,
|
||||
allowSettings: false,
|
||||
@@ -45,7 +46,7 @@ const _modes = {
|
||||
unlockDialog: imports.gdm.loginDialog.LoginDialog,
|
||||
components: ['polkitAgent'],
|
||||
panel: {
|
||||
left: ['logo'],
|
||||
left: [],
|
||||
center: ['dateMenu'],
|
||||
right: ['a11yGreeter', 'display', 'keyboard',
|
||||
'volume', 'battery', 'powerMenu']
|
||||
@@ -84,7 +85,7 @@ const _modes = {
|
||||
components: ['networkAgent', 'keyring'],
|
||||
panel: {
|
||||
left: [],
|
||||
center: [],
|
||||
center: ['dateMenu'],
|
||||
right: ['a11yGreeter', 'keyboard', 'volume', 'battery']
|
||||
}
|
||||
},
|
||||
@@ -195,6 +196,10 @@ const SessionMode = new Lang.Class({
|
||||
return this._modeStack[this._modeStack.length - 1];
|
||||
},
|
||||
|
||||
get allowScreencast() {
|
||||
return this.components.indexOf('recorder') != -1;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let params = this._modes[this.currentMode];
|
||||
let defaults;
|
||||
|
@@ -12,6 +12,7 @@ const ExtensionDownloader = imports.ui.extensionDownloader;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
const Screencast = imports.ui.screencast;
|
||||
const Screenshot = imports.ui.screenshot;
|
||||
|
||||
const GnomeShellIface = <interface name="org.gnome.Shell">
|
||||
@@ -20,6 +21,7 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
|
||||
<arg type="b" direction="out" name="success" />
|
||||
<arg type="s" direction="out" name="result" />
|
||||
</method>
|
||||
<method name="FocusSearch"/>
|
||||
<method name="ShowOSD">
|
||||
<arg type="a{sv}" direction="in" name="params"/>
|
||||
</method>
|
||||
@@ -70,6 +72,7 @@ const GnomeShell = new Lang.Class({
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
|
||||
|
||||
this._extensionsService = new GnomeShellExtensions();
|
||||
this._screencastService = new Screencast.ScreencastService();
|
||||
this._screenshotService = new Screenshot.ScreenshotService();
|
||||
|
||||
this._grabbedAccelerators = new Hash.Map();
|
||||
@@ -114,6 +117,10 @@ const GnomeShell = new Lang.Class({
|
||||
return [success, returnValue];
|
||||
},
|
||||
|
||||
FocusSearch: function() {
|
||||
Main.overview.focusSearch();
|
||||
},
|
||||
|
||||
ShowOSD: function(params) {
|
||||
for (let param in params)
|
||||
params[param] = params[param].deep_unpack();
|
||||
|
@@ -14,9 +14,7 @@ const EntryMenu = new Lang.Class({
|
||||
Name: 'ShellEntryMenu',
|
||||
Extends: PopupMenu.PopupMenu,
|
||||
|
||||
_init: function(entry, params) {
|
||||
params = Params.parse (params, { isPassword: false });
|
||||
|
||||
_init: function(entry) {
|
||||
this.parent(entry, 0, St.Side.TOP);
|
||||
|
||||
this.actor.add_style_class_name('entry-context-menu');
|
||||
@@ -37,8 +35,6 @@ const EntryMenu = new Lang.Class({
|
||||
this._pasteItem = item;
|
||||
|
||||
this._passwordItem = null;
|
||||
if (params.isPassword)
|
||||
this._makePasswordItem();
|
||||
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
this.actor.hide();
|
||||
@@ -53,19 +49,21 @@ const EntryMenu = new Lang.Class({
|
||||
},
|
||||
|
||||
get isPassword() {
|
||||
return this._passwordItem != null;
|
||||
return this._passwordItem != null;
|
||||
},
|
||||
|
||||
set isPassword(v) {
|
||||
if (v == this.isPassword)
|
||||
return;
|
||||
if (v == this.isPassword)
|
||||
return;
|
||||
|
||||
if (v)
|
||||
this._makePasswordItem();
|
||||
else {
|
||||
this._passwordItem.destroy();
|
||||
this._passwordItem = null;
|
||||
}
|
||||
if (v) {
|
||||
this._makePasswordItem();
|
||||
this._entry.input_purpose = Gtk.InputPurpose.PASSWORD;
|
||||
} else {
|
||||
this._passwordItem.destroy();
|
||||
this._passwordItem = null;
|
||||
this._entry.input_purpose = Gtk.InputPurpose.FREE_FORM;
|
||||
}
|
||||
},
|
||||
|
||||
open: function(animate) {
|
||||
@@ -155,7 +153,10 @@ function addContextMenu(entry, params) {
|
||||
if (entry.menu)
|
||||
return;
|
||||
|
||||
entry.menu = new EntryMenu(entry, params);
|
||||
params = Params.parse (params, { isPassword: false });
|
||||
|
||||
entry.menu = new EntryMenu(entry);
|
||||
entry.menu.isPassword = params.isPassword;
|
||||
entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry });
|
||||
entry._menuManager.addMenu(entry.menu);
|
||||
|
||||
|
@@ -33,6 +33,33 @@ const KEY_INPUT_SOURCES = 'sources';
|
||||
const INPUT_SOURCE_TYPE_XKB = 'xkb';
|
||||
const INPUT_SOURCE_TYPE_IBUS = 'ibus';
|
||||
|
||||
// This is the longest we'll keep the keyboard frozen until an input
|
||||
// source is active.
|
||||
const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
|
||||
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard';
|
||||
|
||||
const KeyboardManagerInterface =
|
||||
<interface name="org.gnome.SettingsDaemon.Keyboard">
|
||||
<method name="SetInputSource">
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface);
|
||||
|
||||
function releaseKeyboard() {
|
||||
if (Main.modalCount > 0)
|
||||
global.display.unfreeze_keyboard(global.get_current_time());
|
||||
else
|
||||
global.display.ungrab_keyboard(global.get_current_time());
|
||||
}
|
||||
|
||||
function holdKeyboard() {
|
||||
global.freeze_keyboard(global.get_current_time());
|
||||
}
|
||||
|
||||
const IBusManager = new Lang.Class({
|
||||
Name: 'IBusManager',
|
||||
|
||||
@@ -45,26 +72,24 @@ const IBusManager = new Lang.Class({
|
||||
this._readyCallback = readyCallback;
|
||||
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
|
||||
|
||||
this._ibus = null;
|
||||
this._panelService = null;
|
||||
this._engines = {};
|
||||
this._ready = false;
|
||||
this._registerPropertiesId = 0;
|
||||
this._currentEngineName = null;
|
||||
|
||||
this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
Lang.bind(this, this._onNameAppeared),
|
||||
Lang.bind(this, this._clear));
|
||||
this._ibus = IBus.Bus.new_async();
|
||||
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
|
||||
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
|
||||
// Need to set this to get 'global-engine-changed' emitions
|
||||
this._ibus.set_watch_ibus_signal(true);
|
||||
this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged));
|
||||
},
|
||||
|
||||
_clear: function() {
|
||||
if (this._panelService)
|
||||
this._panelService.destroy();
|
||||
if (this._ibus)
|
||||
this._ibus.destroy();
|
||||
|
||||
this._ibus = null;
|
||||
this._panelService = null;
|
||||
this._candidatePopup.setPanelService(null);
|
||||
this._engines = {};
|
||||
@@ -76,18 +101,12 @@ const IBusManager = new Lang.Class({
|
||||
this._readyCallback(false);
|
||||
},
|
||||
|
||||
_onNameAppeared: function() {
|
||||
this._ibus = IBus.Bus.new_async();
|
||||
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
|
||||
},
|
||||
|
||||
_onConnected: function() {
|
||||
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
|
||||
this._ibus.request_name_async(IBus.SERVICE_PANEL,
|
||||
IBus.BusNameFlag.REPLACE_EXISTING,
|
||||
-1, null,
|
||||
Lang.bind(this, this._initPanelService));
|
||||
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
|
||||
},
|
||||
|
||||
_initEngines: function(ibus, result) {
|
||||
@@ -109,9 +128,6 @@ const IBusManager = new Lang.Class({
|
||||
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
|
||||
object_path: IBus.PATH_PANEL });
|
||||
this._candidatePopup.setPanelService(this._panelService);
|
||||
// Need to set this to get 'global-engine-changed' emitions
|
||||
this._ibus.set_watch_ibus_signal(true);
|
||||
this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged));
|
||||
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
|
||||
// If an engine is already active we need to get its properties
|
||||
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
|
||||
@@ -140,6 +156,9 @@ const IBusManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_engineChanged: function(bus, engineName) {
|
||||
if (!this._ready)
|
||||
return;
|
||||
|
||||
this._currentEngineName = engineName;
|
||||
|
||||
if (this._registerPropertiesId != 0)
|
||||
@@ -337,14 +356,14 @@ const InputSourceIndicator = new Lang.Class({
|
||||
Main.wm.addKeybinding('switch-input-source',
|
||||
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
|
||||
Meta.KeyBindingFlags.REVERSES,
|
||||
Shell.KeyBindingMode.ALL & ~Shell.KeyBindingMode.MESSAGE_TRAY,
|
||||
Shell.KeyBindingMode.ALL,
|
||||
Lang.bind(this, this._switchInputSource));
|
||||
this._keybindingActionBackward =
|
||||
Main.wm.addKeybinding('switch-input-source-backward',
|
||||
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
|
||||
Meta.KeyBindingFlags.REVERSES |
|
||||
Meta.KeyBindingFlags.REVERSED,
|
||||
Shell.KeyBindingMode.ALL & ~Shell.KeyBindingMode.MESSAGE_TRAY,
|
||||
Shell.KeyBindingMode.ALL,
|
||||
Lang.bind(this, this._switchInputSource));
|
||||
this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
|
||||
this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
|
||||
@@ -364,6 +383,15 @@ const InputSourceIndicator = new Lang.Class({
|
||||
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
|
||||
this._inputSourcesChanged();
|
||||
|
||||
this._keyboardManager = new KeyboardManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
|
||||
function(proxy, error) {
|
||||
if (error)
|
||||
log(error.message);
|
||||
});
|
||||
this._keyboardManager.g_default_timeout = MAX_INPUT_SOURCE_ACTIVATION_TIME;
|
||||
|
||||
global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher));
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, this._showLayout));
|
||||
|
||||
@@ -397,10 +425,43 @@ const InputSourceIndicator = new Lang.Class({
|
||||
this._inputSourcesChanged();
|
||||
},
|
||||
|
||||
_modifiersSwitcher: function() {
|
||||
let sourceIndexes = Object.keys(this._inputSources);
|
||||
if (sourceIndexes.length == 0) {
|
||||
releaseKeyboard();
|
||||
return true;
|
||||
}
|
||||
|
||||
let is = this._currentSource;
|
||||
if (!is)
|
||||
is = this._inputSources[sourceIndexes[0]];
|
||||
|
||||
let nextIndex = is.index + 1;
|
||||
if (nextIndex > sourceIndexes[sourceIndexes.length - 1])
|
||||
nextIndex = 0;
|
||||
|
||||
while (!(is = this._inputSources[nextIndex]))
|
||||
nextIndex += 1;
|
||||
|
||||
is.activate();
|
||||
return true;
|
||||
},
|
||||
|
||||
_switchInputSource: function(display, screen, window, binding) {
|
||||
if (this._mruSources.length < 2)
|
||||
return;
|
||||
|
||||
// HACK: Fall back on simple input source switching since we
|
||||
// can't show a popup switcher while a GrabHelper grab is in
|
||||
// effect without considerable work to consolidate the usage
|
||||
// of pushModal/popModal and grabHelper. See
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=695143 .
|
||||
if (Main.keybindingMode == Shell.KeyBindingMode.MESSAGE_TRAY ||
|
||||
Main.keybindingMode == Shell.KeyBindingMode.TOPBAR_POPUP) {
|
||||
this._modifiersSwitcher();
|
||||
return;
|
||||
}
|
||||
|
||||
let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward);
|
||||
let modifiers = binding.get_modifiers();
|
||||
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
||||
@@ -417,7 +478,7 @@ const InputSourceIndicator = new Lang.Class({
|
||||
[oldSource, this._currentSource] = [this._currentSource, newSource];
|
||||
|
||||
if (oldSource) {
|
||||
oldSource.menuItem.setOrnament(PopupMenu.Ornament.NONE);
|
||||
oldSource.menuItem.setShowDot(false);
|
||||
oldSource.indicatorLabel.hide();
|
||||
}
|
||||
|
||||
@@ -435,7 +496,7 @@ const InputSourceIndicator = new Lang.Class({
|
||||
|
||||
this.actor.show();
|
||||
|
||||
newSource.menuItem.setOrnament(PopupMenu.Ornament.DOT);
|
||||
newSource.menuItem.setShowDot(true);
|
||||
newSource.indicatorLabel.show();
|
||||
|
||||
this._buildPropSection(newSource.properties);
|
||||
@@ -488,10 +549,8 @@ const InputSourceIndicator = new Lang.Class({
|
||||
let is = new InputSource(type, id, displayName, shortName, i);
|
||||
|
||||
is.connect('activate', Lang.bind(this, function() {
|
||||
if (this._currentSource && this._currentSource.index == is.index)
|
||||
return;
|
||||
this._settings.set_value(KEY_CURRENT_INPUT_SOURCE,
|
||||
GLib.Variant.new_uint32(is.index));
|
||||
holdKeyboard();
|
||||
this._keyboardManager.SetInputSourceRemote(is.index, releaseKeyboard);
|
||||
}));
|
||||
|
||||
if (!(is.shortName in inputSourcesByShortName))
|
||||
@@ -661,8 +720,7 @@ const InputSourceIndicator = new Lang.Class({
|
||||
item.prop = prop;
|
||||
radioGroup.push(item);
|
||||
item.radioGroup = radioGroup;
|
||||
item.setOrnament(prop.get_state() == IBus.PropState.CHECKED ?
|
||||
PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE);
|
||||
item.setShowDot(prop.get_state() == IBus.PropState.CHECKED);
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
if (item.prop.get_state() == IBus.PropState.CHECKED)
|
||||
return;
|
||||
@@ -670,12 +728,12 @@ const InputSourceIndicator = new Lang.Class({
|
||||
let group = item.radioGroup;
|
||||
for (let i = 0; i < group.length; ++i) {
|
||||
if (group[i] == item) {
|
||||
item.setOrnament(PopupMenu.Ornament.DOT);
|
||||
item.setShowDot(true);
|
||||
item.prop.set_state(IBus.PropState.CHECKED);
|
||||
this._ibusManager.activateProperty(item.prop.get_key(),
|
||||
IBus.PropState.CHECKED);
|
||||
} else {
|
||||
group[i].setOrnament(PopupMenu.Ornament.NONE);
|
||||
group[i].setShowDot(false);
|
||||
group[i].prop.set_state(IBus.PropState.UNCHECKED);
|
||||
this._ibusManager.activateProperty(group[i].prop.get_key(),
|
||||
IBus.PropState.UNCHECKED);
|
||||
|
@@ -5,10 +5,17 @@ const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const NetworkManager = imports.gi.NetworkManager;
|
||||
const NMClient = imports.gi.NMClient;
|
||||
const NMGtk = imports.gi.NMGtk;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
// Some of the new code depends on as-yet-unreleased NM
|
||||
var NMGtk;
|
||||
try {
|
||||
NMGtk = imports.gi.NMGtk;
|
||||
} catch(e) {
|
||||
NMGtk = null;
|
||||
}
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
@@ -27,6 +34,7 @@ const NMConnectionCategory = {
|
||||
};
|
||||
|
||||
const NMAccessPointSecurity = {
|
||||
UNKNOWN: 0,
|
||||
NONE: 1,
|
||||
WEP: 2,
|
||||
WPA_PSK: 3,
|
||||
@@ -44,6 +52,20 @@ const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags'];
|
||||
// (the remaining are placed into More…)
|
||||
const NUM_VISIBLE_NETWORKS = 5;
|
||||
|
||||
function macToArray(string) {
|
||||
return string.split(':').map(function(el) {
|
||||
return parseInt(el, 16);
|
||||
});
|
||||
}
|
||||
|
||||
function macCompare(one, two) {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
if (one[i] != two[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function ssidCompare(one, two) {
|
||||
if (!one || !two)
|
||||
return false;
|
||||
@@ -108,7 +130,8 @@ const NMNetworkMenuItem = new Lang.Class({
|
||||
this._icons.add_actor(this._signalIcon);
|
||||
|
||||
this._secureIcon = new St.Icon({ style_class: 'popup-menu-icon' });
|
||||
if (this.bestAP._secType != NMAccessPointSecurity.NONE)
|
||||
if (this.bestAP._secType != NMAccessPointSecurity.UNKNOWN &&
|
||||
this.bestAP._secType != NMAccessPointSecurity.NONE)
|
||||
this._secureIcon.icon_name = 'network-wireless-encrypted-symbolic';
|
||||
this._icons.add_actor(this._secureIcon);
|
||||
},
|
||||
@@ -130,12 +153,18 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
|
||||
Name: 'NMWirelessSectionTitleMenuItem',
|
||||
Extends: PopupMenu.PopupSwitchMenuItem,
|
||||
|
||||
_init: function(client) {
|
||||
this.parent(_("Wi-Fi"), false, { style_class: 'popup-subtitle-menu-item' });
|
||||
_init: function(client, property, title, params) {
|
||||
params = params || { };
|
||||
params.style_class = 'popup-subtitle-menu-item';
|
||||
this.parent(title, false, params);
|
||||
|
||||
this._client = client;
|
||||
this._client.connect('notify::wireless-enabled', Lang.bind(this, this._propertyChanged));
|
||||
this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._propertyChanged));
|
||||
this._property = property + '_enabled';
|
||||
this._propertyHardware = property + '_hardware_enabled';
|
||||
this._setEnabledFunc = property + '_set_enabled';
|
||||
|
||||
this._client.connect('notify::' + property + '-enabled', Lang.bind(this, this._propertyChanged));
|
||||
this._client.connect('notify::' + property + '-hardware-enabled', Lang.bind(this, this._propertyChanged));
|
||||
|
||||
this._propertyChanged();
|
||||
},
|
||||
@@ -157,12 +186,12 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
|
||||
activate: function(event) {
|
||||
this.parent(event);
|
||||
|
||||
this._client.wireless_set_enabled(this._switch.state);
|
||||
this._client[this._setEnabledFunc](this._switch.state);
|
||||
},
|
||||
|
||||
_propertyChanged: function() {
|
||||
this._softwareEnabled = this._client.wireless_enabled;
|
||||
this._hardwareEnabled = this._client.wireless_hardware_enabled;
|
||||
this._softwareEnabled = this._client[this._property];
|
||||
this._hardwareEnabled = this._client[this._propertyHardware];
|
||||
|
||||
let enabled = this._softwareEnabled && this._hardwareEnabled;
|
||||
this.setToggleState(enabled);
|
||||
@@ -286,6 +315,7 @@ const NMDevice = new Lang.Class({
|
||||
|
||||
this._activeConnection = null;
|
||||
this._activeConnectionItem = null;
|
||||
this._autoConnectionItem = null;
|
||||
this._overflowItem = null;
|
||||
|
||||
this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected, { style_class: 'popup-subtitle-menu-item' });
|
||||
@@ -372,9 +402,13 @@ const NMDevice = new Lang.Class({
|
||||
},
|
||||
|
||||
_activateAutomaticConnection: function() {
|
||||
let connection = new NetworkManager.Connection();
|
||||
this._client.add_and_activate_connection(connection, this.device, null, null);
|
||||
return true;
|
||||
let connection = this._createAutomaticConnection();
|
||||
if (connection) {
|
||||
this._client.add_and_activate_connection(connection, this.device, null, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
get connected() {
|
||||
@@ -468,6 +502,11 @@ const NMDevice = new Lang.Class({
|
||||
this.statusItem.label.text = this.device._description;
|
||||
},
|
||||
|
||||
// protected
|
||||
_createAutomaticConnection: function() {
|
||||
throw new TypeError('Invoking pure virtual function NMDevice.createAutomaticConnection');
|
||||
},
|
||||
|
||||
_queueCreateSection: function() {
|
||||
if (this._deferredWorkId) {
|
||||
this._clearSection();
|
||||
@@ -478,6 +517,7 @@ const NMDevice = new Lang.Class({
|
||||
_clearSection: function() {
|
||||
// Clear everything
|
||||
this.section.removeAll();
|
||||
this._autoConnectionItem = null;
|
||||
this._activeConnectionItem = null;
|
||||
this._overflowItem = null;
|
||||
for (let i = 0; i < this._connections.length; i++) {
|
||||
@@ -516,6 +556,14 @@ const NMDevice = new Lang.Class({
|
||||
} else
|
||||
this.section.addMenuItem(obj.item);
|
||||
}
|
||||
} else if (this._autoConnectionName) {
|
||||
this._autoConnectionItem = new PopupMenu.PopupMenuItem(this._autoConnectionName);
|
||||
this._autoConnectionItem.connect('activate', Lang.bind(this, function() {
|
||||
let connection = this._createAutomaticConnection();
|
||||
if (connection)
|
||||
this._client.add_and_activate_connection(connection, this.device, null, null);
|
||||
}));
|
||||
this.section.addMenuItem(this._autoConnectionItem);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -540,7 +588,7 @@ const NMDevice = new Lang.Class({
|
||||
title = _("Connected (private)");
|
||||
}
|
||||
this._activeConnectionItem = new PopupMenu.PopupMenuItem(title, { reactive: false });
|
||||
this._activeConnectionItem.setOrnament(PopupMenu.Ornament.DOT);
|
||||
this._activeConnectionItem.setShowDot(true);
|
||||
},
|
||||
|
||||
_deviceStateChanged: function(device, newstate, oldstate, reason) {
|
||||
@@ -617,10 +665,24 @@ const NMDeviceWired = new Lang.Class({
|
||||
|
||||
_init: function(client, device, connections) {
|
||||
device._description = _("Wired");
|
||||
this._autoConnectionName = _("Auto Ethernet");
|
||||
this.category = NMConnectionCategory.WIRED;
|
||||
|
||||
this.parent(client, device, connections);
|
||||
},
|
||||
|
||||
_createAutomaticConnection: function() {
|
||||
let connection = new NetworkManager.Connection();
|
||||
let uuid = NetworkManager.utils_uuid_generate();
|
||||
connection.add_setting(new NetworkManager.SettingWired());
|
||||
connection.add_setting(new NetworkManager.SettingConnection({
|
||||
uuid: uuid,
|
||||
id: this._autoConnectionName,
|
||||
type: NetworkManager.SETTING_WIRED_SETTING_NAME,
|
||||
autoconnect: true
|
||||
}));
|
||||
return connection;
|
||||
}
|
||||
});
|
||||
|
||||
const NMDeviceModem = new Lang.Class({
|
||||
@@ -661,10 +723,13 @@ const NMDeviceModem = new Lang.Class({
|
||||
this._connectionType = NetworkManager.SETTING_GSM_SETTING_NAME;
|
||||
}
|
||||
|
||||
if (is_wwan)
|
||||
if (is_wwan) {
|
||||
this.category = NMConnectionCategory.WWAN;
|
||||
else
|
||||
this._autoConnectionName = _("Auto broadband");
|
||||
} else {
|
||||
this.category = NMConnectionCategory.WIRED;
|
||||
this._autoConnectionName = _("Auto dial-up");
|
||||
}
|
||||
|
||||
if (this.mobileDevice) {
|
||||
this._operatorNameId = this.mobileDevice.connect('notify::operator-name', Lang.bind(this, function() {
|
||||
@@ -759,20 +824,50 @@ const NMDeviceBluetooth = new Lang.Class({
|
||||
|
||||
_init: function(client, device, connections) {
|
||||
device._description = _("Bluetooth");
|
||||
this._autoConnectionName = this._makeConnectionName(device);
|
||||
device.connect('notify::name', Lang.bind(this, this._updateAutoConnectionName));
|
||||
|
||||
this.category = NMConnectionCategory.WWAN;
|
||||
|
||||
this.parent(client, device, connections);
|
||||
},
|
||||
|
||||
_createAutomaticConnection: function() {
|
||||
let connection = new NetworkManager.Connection;
|
||||
let uuid = NetworkManager.utils_uuid_generate();
|
||||
connection.add_setting(new NetworkManager.SettingBluetooth);
|
||||
connection.add_setting(new NetworkManager.SettingConnection({
|
||||
uuid: uuid,
|
||||
id: this._autoConnectionName,
|
||||
type: NetworkManager.SETTING_BLUETOOTH_SETTING_NAME,
|
||||
autoconnect: false
|
||||
}));
|
||||
return connection;
|
||||
},
|
||||
|
||||
_activateAutomaticConnection: function() {
|
||||
// FIXME: DUN devices are configured like modems, so
|
||||
// We need to spawn the mobile wizard
|
||||
// we need to spawn the mobile wizard
|
||||
// but the network panel doesn't support bluetooth at the moment
|
||||
// so we just create an empty connection and hope
|
||||
// that this phone supports PAN
|
||||
|
||||
return this.parent();
|
||||
},
|
||||
|
||||
_makeConnectionName: function(device) {
|
||||
let name = device.name;
|
||||
if (name)
|
||||
return _("Auto %s").format(name);
|
||||
else
|
||||
return _("Auto bluetooth");
|
||||
},
|
||||
|
||||
_updateAutoConnectionName: function() {
|
||||
this._autoConnectionName = this._makeConnectionName(this.device);
|
||||
|
||||
this._queueCreateSection();
|
||||
this._updateStatusItem();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -808,20 +903,20 @@ const NMDeviceWireless = new Lang.Class({
|
||||
}
|
||||
|
||||
let pos = this._findNetwork(ap);
|
||||
let network;
|
||||
let obj;
|
||||
if (pos != -1) {
|
||||
network = this._networks[pos];
|
||||
network.accessPoints.push(ap);
|
||||
obj = this._networks[pos];
|
||||
obj.accessPoints.push(ap);
|
||||
} else {
|
||||
network = { ssid: ap.get_ssid(),
|
||||
mode: ap.mode,
|
||||
security: this._getApSecurityType(ap),
|
||||
connections: [ ],
|
||||
item: null,
|
||||
accessPoints: [ ap ]
|
||||
obj = { ssid: ap.get_ssid(),
|
||||
mode: ap.mode,
|
||||
security: this._getApSecurityType(ap),
|
||||
connections: [ ],
|
||||
item: null,
|
||||
accessPoints: [ ap ]
|
||||
};
|
||||
network.ssidText = ssidToLabel(network.ssid);
|
||||
this._networks.push(network);
|
||||
obj.ssidText = ssidToLabel(obj.ssid);
|
||||
this._networks.push(obj);
|
||||
}
|
||||
ap._updateId = ap.connect('notify::strength', Lang.bind(this, this._onApStrengthChanged));
|
||||
|
||||
@@ -829,8 +924,8 @@ const NMDeviceWireless = new Lang.Class({
|
||||
for (let j = 0; j < validConnections.length; j++) {
|
||||
let connection = validConnections[j];
|
||||
if (ap.connection_valid(connection) &&
|
||||
network.connections.indexOf(connection) == -1) {
|
||||
network.connections.push(connection);
|
||||
obj.connections.indexOf(connection) == -1) {
|
||||
obj.connections.push(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -839,7 +934,16 @@ const NMDeviceWireless = new Lang.Class({
|
||||
for (let i = 0; i < this._networks.length; i++)
|
||||
sortAccessPoints(this._networks[i].accessPoints);
|
||||
|
||||
this._activeApChanged();
|
||||
if (this.device.active_access_point) {
|
||||
let networkPos = this._findNetwork(this.device.active_access_point);
|
||||
|
||||
if (networkPos == -1) // the connected access point is invisible
|
||||
this._activeNetwork = null;
|
||||
else
|
||||
this._activeNetwork = this._networks[networkPos];
|
||||
} else {
|
||||
this._activeNetwork = null;
|
||||
}
|
||||
this._networks.sort(this._networkSortFunction);
|
||||
|
||||
this._apChangedId = device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged));
|
||||
@@ -986,9 +1090,9 @@ const NMDeviceWireless = new Lang.Class({
|
||||
|
||||
_findExistingNetwork: function(accessPoint) {
|
||||
for (let i = 0; i < this._networks.length; i++) {
|
||||
let network = this._networks[i];
|
||||
for (let j = 0; j < network.accessPoints.length; j++) {
|
||||
if (network.accessPoints[j] == accessPoint)
|
||||
let apObj = this._networks[i];
|
||||
for (let j = 0; j < apObj.accessPoints.length; j++) {
|
||||
if (apObj.accessPoints[j] == accessPoint)
|
||||
return { network: i, ap: j };
|
||||
}
|
||||
}
|
||||
@@ -1036,30 +1140,30 @@ const NMDeviceWireless = new Lang.Class({
|
||||
}
|
||||
|
||||
let pos = this._findNetwork(accessPoint);
|
||||
let network;
|
||||
let apObj;
|
||||
let needsupdate = false;
|
||||
|
||||
if (pos != -1) {
|
||||
network = this._networks[pos];
|
||||
if (network.accessPoints.indexOf(accessPoint) != -1) {
|
||||
apObj = this._networks[pos];
|
||||
if (apObj.accessPoints.indexOf(accessPoint) != -1) {
|
||||
log('Access point was already seen, not adding again');
|
||||
return;
|
||||
}
|
||||
|
||||
Util.insertSorted(network.accessPoints, accessPoint, function(one, two) {
|
||||
Util.insertSorted(apObj.accessPoints, accessPoint, function(one, two) {
|
||||
return two.strength - one.strength;
|
||||
});
|
||||
if (network.item)
|
||||
network.item.updateBestAP(network.accessPoints[0]);
|
||||
if (apObj.item)
|
||||
apObj.item.updateBestAP(apObj.accessPoints[0]);
|
||||
} else {
|
||||
network = { ssid: accessPoint.get_ssid(),
|
||||
mode: accessPoint.mode,
|
||||
security: this._getApSecurityType(accessPoint),
|
||||
connections: [ ],
|
||||
item: null,
|
||||
accessPoints: [ accessPoint ]
|
||||
};
|
||||
network.ssidText = ssidToLabel(network.ssid);
|
||||
apObj = { ssid: accessPoint.get_ssid(),
|
||||
mode: accessPoint.mode,
|
||||
security: this._getApSecurityType(accessPoint),
|
||||
connections: [ ],
|
||||
item: null,
|
||||
accessPoints: [ accessPoint ]
|
||||
};
|
||||
apObj.ssidText = ssidToLabel(apObj.ssid);
|
||||
}
|
||||
accessPoint._updateId = accessPoint.connect('notify::strength', Lang.bind(this, this._onApStrengthChanged));
|
||||
|
||||
@@ -1067,14 +1171,14 @@ const NMDeviceWireless = new Lang.Class({
|
||||
for (let i = 0; i < this._connections.length; i++) {
|
||||
let connection = this._connections[i].connection;
|
||||
if (accessPoint.connection_valid(connection) &&
|
||||
network.connections.indexOf(connection) == -1) {
|
||||
network.connections.push(connection);
|
||||
apObj.connections.indexOf(connection) == -1) {
|
||||
apObj.connections.push(connection);
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != -1)
|
||||
this._networks.splice(pos, 1);
|
||||
let newPos = Util.insertSorted(this._networks, network, this._networkSortFunction);
|
||||
let newPos = Util.insertSorted(this._networks, apObj, this._networkSortFunction);
|
||||
|
||||
// Queue an update of the UI if we changed the order
|
||||
if (newPos != pos)
|
||||
@@ -1094,28 +1198,28 @@ const NMDeviceWireless = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
let network = this._networks[res.network];
|
||||
network.accessPoints.splice(res.ap, 1);
|
||||
let apObj = this._networks[res.network];
|
||||
apObj.accessPoints.splice(res.ap, 1);
|
||||
|
||||
if (network.accessPoints.length == 0) {
|
||||
if (this._activeNetwork == network)
|
||||
if (apObj.accessPoints.length == 0) {
|
||||
if (this._activeNetwork == apObj)
|
||||
this._activeNetwork = null;
|
||||
|
||||
if (network.item)
|
||||
network.item.destroy();
|
||||
if (apObj.item)
|
||||
apObj.item.destroy();
|
||||
|
||||
if (this._overflowItem) {
|
||||
if (!network.isMore) {
|
||||
if (!apObj.isMore) {
|
||||
// we removed an item in the main menu, and we have a more submenu
|
||||
// we need to extract the first item in more and move it to the submenu
|
||||
|
||||
let item = this._overflowItem.menu.firstMenuItem;
|
||||
if (item && item._network) {
|
||||
if (item && item._apObj) {
|
||||
item.destroy();
|
||||
// clear the cycle, and allow the construction of the new item
|
||||
item._network.item = null;
|
||||
item._apObj.item = null;
|
||||
|
||||
this._createNetworkItem(item._network, NUM_VISIBLE_NETWORKS-1);
|
||||
this._createNetworkItem(item._apObj, NUM_VISIBLE_NETWORKS-1);
|
||||
} else {
|
||||
log('The more... menu was existing and empty! This should not happen');
|
||||
}
|
||||
@@ -1134,14 +1238,14 @@ const NMDeviceWireless = new Lang.Class({
|
||||
let okPrev = true, okNext = true;
|
||||
|
||||
if (res.network > 0)
|
||||
okPrev = this._networkSortFunction(this._networks[res.network - 1], network) >= 0;
|
||||
okPrev = this._networkSortFunction(this._networks[res.network - 1], apObj) >= 0;
|
||||
if (res.network < this._networks.length-1)
|
||||
okNext = this._networkSortFunction(this._networks[res.network + 1], network) <= 0;
|
||||
okNext = this._networkSortFunction(this._networks[res.network + 1], apObj) <= 0;
|
||||
|
||||
if (!okPrev || !okNext)
|
||||
this._queueCreateSection();
|
||||
else if (network.item)
|
||||
network.item.updateBestAP(network.accessPoints[0]);
|
||||
else if (apObj.item)
|
||||
apObj.item.updateBestAP(apObj.accessPoints[0]);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1180,20 +1284,20 @@ const NMDeviceWireless = new Lang.Class({
|
||||
|
||||
let forceupdate = false;
|
||||
for (let i = 0; i < this._networks.length; i++) {
|
||||
let network = this._networks[i];
|
||||
let connections = network.connections;
|
||||
let apObj = this._networks[i];
|
||||
let connections = apObj.connections;
|
||||
for (let k = 0; k < connections.length; k++) {
|
||||
if (connections[k].get_uuid() == connection.get_uuid()) {
|
||||
// remove the connection from the access point group
|
||||
connections.splice(k, 1);
|
||||
connections.splice(k);
|
||||
forceupdate = forceupdate || connections.length == 0;
|
||||
|
||||
if (forceupdate)
|
||||
break;
|
||||
|
||||
if (network.item) {
|
||||
if (network.item instanceof PopupMenu.PopupSubMenuMenuItem) {
|
||||
let items = network.item.menu._getMenuItems();
|
||||
if (apObj.item) {
|
||||
if (apObj.item instanceof PopupMenu.PopupSubMenuMenuItem) {
|
||||
let items = apObj.item.menu._getMenuItems();
|
||||
if (items.length == 2) {
|
||||
// we need to update the connection list to convert this to a normal item
|
||||
forceupdate = true;
|
||||
@@ -1206,8 +1310,8 @@ const NMDeviceWireless = new Lang.Class({
|
||||
}
|
||||
}
|
||||
} else {
|
||||
network.item.destroy();
|
||||
network.item = null;
|
||||
apObj.item.destroy();
|
||||
apObj.item = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1233,13 +1337,13 @@ const NMDeviceWireless = new Lang.Class({
|
||||
// find an appropriate access point
|
||||
let forceupdate = false;
|
||||
for (let i = 0; i < this._networks.length; i++) {
|
||||
let network = this._networks[i];
|
||||
let apObj = this._networks[i];
|
||||
|
||||
// Check if connection is valid for any of these access points
|
||||
for (let k = 0; k < network.accessPoints.length; k++) {
|
||||
let ap = network.accessPoints[k];
|
||||
for (let k = 0; k < apObj.accessPoints.length; k++) {
|
||||
let ap = apObj.accessPoints[k];
|
||||
if (ap.connection_valid(connection)) {
|
||||
network.connections.push(connection);
|
||||
apObj.connections.push(connection);
|
||||
// this potentially changes the sorting order
|
||||
forceupdate = true;
|
||||
break;
|
||||
@@ -1260,30 +1364,55 @@ const NMDeviceWireless = new Lang.Class({
|
||||
else
|
||||
title = _("Connected (private)");
|
||||
|
||||
this._activeConnectionItem = new NMNetworkMenuItem(this.device.active_access_point, undefined,
|
||||
{ reactive: false });
|
||||
this._activeConnectionItem.setOrnament(PopupMenu.Ornament.DOT);
|
||||
if (this._activeNetwork)
|
||||
this._activeConnectionItem = new NMNetworkMenuItem(this.device.active_access_point, undefined,
|
||||
{ reactive: false });
|
||||
else
|
||||
this._activeConnectionItem = new PopupMenu.PopupImageMenuItem(title,
|
||||
'network-wireless-connected-symbolic',
|
||||
{ reactive: false });
|
||||
this._activeConnectionItem.setShowDot(true);
|
||||
},
|
||||
|
||||
_createNetworkItem: function(network, position) {
|
||||
if(!network.accessPoints || network.accessPoints.length == 0) {
|
||||
_createAutomaticConnection: function(apObj) {
|
||||
let name;
|
||||
let ssid = NetworkManager.utils_ssid_to_utf8(apObj.ssid);
|
||||
if (ssid) {
|
||||
/* TRANSLATORS: this the automatic wireless connection name (including the network name) */
|
||||
name = _("Auto %s").format(ssid);
|
||||
} else
|
||||
name = _("Auto wireless");
|
||||
|
||||
let connection = new NetworkManager.Connection();
|
||||
connection.add_setting(new NetworkManager.SettingWireless());
|
||||
connection.add_setting(new NetworkManager.SettingConnection({
|
||||
id: name,
|
||||
autoconnect: true, // NetworkManager will know to ignore this if appropriate
|
||||
uuid: NetworkManager.utils_uuid_generate(),
|
||||
type: NetworkManager.SETTING_WIRELESS_SETTING_NAME
|
||||
}));
|
||||
return connection;
|
||||
},
|
||||
|
||||
_createNetworkItem: function(apObj, position) {
|
||||
if(!apObj.accessPoints || apObj.accessPoints.length == 0) {
|
||||
// this should not happen, but I have no idea why it happens
|
||||
return;
|
||||
}
|
||||
|
||||
if(network.connections.length > 0) {
|
||||
if (network.connections.length == 1) {
|
||||
network.item = this._createAPItem(network.connections[0], network, false);
|
||||
if(apObj.connections.length > 0) {
|
||||
if (apObj.connections.length == 1) {
|
||||
apObj.item = this._createAPItem(apObj.connections[0], apObj, false);
|
||||
} else {
|
||||
let title = network.ssidText;
|
||||
network.item = new PopupMenu.PopupSubMenuMenuItem(title);
|
||||
for (let i = 0; i < network.connections.length; i++)
|
||||
network.item.menu.addMenuItem(this._createAPItem(network.connections[i], network, true));
|
||||
let title = apObj.ssidText;
|
||||
apObj.item = new PopupMenu.PopupSubMenuMenuItem(title);
|
||||
for (let i = 0; i < apObj.connections.length; i++)
|
||||
apObj.item.menu.addMenuItem(this._createAPItem(apObj.connections[i], apObj, true));
|
||||
}
|
||||
} else {
|
||||
network.item = new NMNetworkMenuItem(network.accessPoints[0]);
|
||||
network.item.connect('activate', Lang.bind(this, function() {
|
||||
let accessPoints = network.accessPoints;
|
||||
apObj.item = new NMNetworkMenuItem(apObj.accessPoints[0]);
|
||||
apObj.item.connect('activate', Lang.bind(this, function() {
|
||||
let accessPoints = apObj.accessPoints;
|
||||
if ( (accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
|
||||
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
|
||||
// 802.1x-enabled APs require further configuration, so they're
|
||||
@@ -1291,23 +1420,23 @@ const NMDeviceWireless = new Lang.Class({
|
||||
Util.spawn(['gnome-control-center', 'network', 'connect-8021x-wifi',
|
||||
this.device.get_path(), accessPoints[0].dbus_path]);
|
||||
} else {
|
||||
let connection = new NetworkManager.Connection();
|
||||
let connection = this._createAutomaticConnection(apObj);
|
||||
this._client.add_and_activate_connection(connection, this.device, accessPoints[0].dbus_path, null)
|
||||
}
|
||||
}));
|
||||
}
|
||||
network.item._network = network;
|
||||
apObj.item._apObj = apObj;
|
||||
|
||||
if (position < NUM_VISIBLE_NETWORKS) {
|
||||
network.isMore = false;
|
||||
this.section.addMenuItem(network.item, position);
|
||||
apObj.isMore = false;
|
||||
this.section.addMenuItem(apObj.item, position);
|
||||
} else {
|
||||
if (!this._overflowItem) {
|
||||
this._overflowItem = new PopupMenu.PopupSubMenuMenuItem(_("More…"));
|
||||
this.section.addMenuItem(this._overflowItem);
|
||||
}
|
||||
this._overflowItem.menu.addMenuItem(network.item, position - NUM_VISIBLE_NETWORKS);
|
||||
network.isMore = true;
|
||||
this._overflowItem.menu.addMenuItem(apObj.item, position - NUM_VISIBLE_NETWORKS);
|
||||
apObj.isMore = true;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1323,13 +1452,13 @@ const NMDeviceWireless = new Lang.Class({
|
||||
let activeOffset = this._activeConnectionItem ? 1 : 0;
|
||||
|
||||
for(let j = 0; j < this._networks.length; j++) {
|
||||
let network = this._networks[j];
|
||||
if (network == this._activeNetwork) {
|
||||
let apObj = this._networks[j];
|
||||
if (apObj == this._activeNetwork) {
|
||||
activeOffset--;
|
||||
continue;
|
||||
}
|
||||
|
||||
this._createNetworkItem(network, j + activeOffset);
|
||||
this._createNetworkItem(apObj, j + activeOffset);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1551,9 +1680,11 @@ const NMApplet = new Lang.Class({
|
||||
|
||||
// Virtual device types
|
||||
this._vtypes = { };
|
||||
this._vtypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMDeviceVirtual;
|
||||
this._vtypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMDeviceVirtual;
|
||||
this._vtypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMDeviceVirtual;
|
||||
if (NMGtk) {
|
||||
this._vtypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMDeviceVirtual;
|
||||
this._vtypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMDeviceVirtual;
|
||||
this._vtypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMDeviceVirtual;
|
||||
}
|
||||
|
||||
// Connection types
|
||||
this._ctypes = { };
|
||||
@@ -1565,9 +1696,11 @@ const NMApplet = new Lang.Class({
|
||||
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
|
||||
this._ctypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
|
||||
this._ctypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
|
||||
if (NMGtk) {
|
||||
this._ctypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
|
||||
this._ctypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
|
||||
this._ctypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
|
||||
}
|
||||
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
|
||||
|
||||
NMClient.Client.new_async(null, Lang.bind(this, this._clientGot));
|
||||
@@ -1635,7 +1768,7 @@ const NMApplet = new Lang.Class({
|
||||
this._devices.wireless = {
|
||||
section: new PopupMenu.PopupMenuSection(),
|
||||
devices: [ ],
|
||||
item: this._makeWirelessToggle()
|
||||
item: this._makeToggleItem('wireless', _("Wi-Fi"))
|
||||
};
|
||||
this._devices.wireless.section.addMenuItem(this._devices.wireless.item);
|
||||
this._devices.wireless.section.actor.hide();
|
||||
@@ -1682,14 +1815,14 @@ const NMApplet = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_makeWirelessToggle: function() {
|
||||
let item = new NMWirelessSectionTitleMenuItem(this._client);
|
||||
_makeToggleItem: function(type, title) {
|
||||
let item = new NMWirelessSectionTitleMenuItem(this._client, type, title);
|
||||
item.connect('enabled-changed', Lang.bind(this, function(item, enabled) {
|
||||
let devices = this._devices.wireless.devices;
|
||||
let devices = this._devices[type].devices;
|
||||
devices.forEach(function(dev) {
|
||||
dev.setEnabled(enabled);
|
||||
});
|
||||
this._syncSectionTitle('wireless');
|
||||
this._syncSectionTitle(type);
|
||||
}));
|
||||
return item;
|
||||
},
|
||||
@@ -1767,12 +1900,19 @@ const NMApplet = new Lang.Class({
|
||||
},
|
||||
|
||||
_syncDeviceNames: function() {
|
||||
let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
|
||||
for (let i = 0; i < this._nmDevices.length; i++) {
|
||||
let device = this._nmDevices[i];
|
||||
device._description = names[i];
|
||||
if (device._delegate)
|
||||
if (NMGtk) {
|
||||
let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
|
||||
for (let i = 0; i < this._nmDevices.length; i++) {
|
||||
let device = this._nmDevices[i];
|
||||
device._description = names[i];
|
||||
if (device._delegate)
|
||||
device._delegate.syncDescription();
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < this._nmDevices.length; i++) {
|
||||
let device = this._nmDevices[i];
|
||||
device._delegate.syncDescription();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1808,6 +1948,11 @@ const NMApplet = new Lang.Class({
|
||||
wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
|
||||
this._syncSectionTitle(dev.category);
|
||||
}));
|
||||
wrapper._destroyId = wrapper.connect('destroy', function(wrapper) {
|
||||
wrapper.disconnect(wrapper._activationFailedId);
|
||||
wrapper.disconnect(wrapper._deviceStateChangedId);
|
||||
wrapper.disconnect(wrapper._destroyId);
|
||||
});
|
||||
|
||||
let section = this._devices[wrapper.category].section;
|
||||
section.addMenuItem(wrapper.statusItem);
|
||||
@@ -1839,8 +1984,6 @@ const NMApplet = new Lang.Class({
|
||||
},
|
||||
|
||||
_removeDeviceWrapper: function(wrapper) {
|
||||
wrapper.disconnect(wrapper._activationFailedId);
|
||||
wrapper.disconnect(wrapper._deviceStateChangedId);
|
||||
wrapper.destroy();
|
||||
|
||||
let devices = this._devices[wrapper.category].devices;
|
||||
@@ -1904,6 +2047,7 @@ const NMApplet = new Lang.Class({
|
||||
let default_ip4 = null;
|
||||
let default_ip6 = null;
|
||||
let active_vpn = null;
|
||||
let active_any = null;
|
||||
for (let i = 0; i < this._activeConnections.length; i++) {
|
||||
let a = this._activeConnections[i];
|
||||
|
||||
@@ -1934,10 +2078,15 @@ const NMApplet = new Lang.Class({
|
||||
if (a.default6)
|
||||
default_ip6 = a;
|
||||
|
||||
if (a._type == 'vpn')
|
||||
active_vpn = a;
|
||||
else if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING)
|
||||
if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING)
|
||||
activating = a;
|
||||
else if (a.state == NetworkManager.ActiveConnectionState.ACTIVATED)
|
||||
active_any = a;
|
||||
|
||||
if (a._type == 'vpn' &&
|
||||
(a.state == NetworkManager.ActiveConnectionState.ACTIVATING ||
|
||||
a.state == NetworkManager.ActiveConnectionState.ACTIVATED))
|
||||
active_vpn = a;
|
||||
|
||||
if (!a._primaryDevice) {
|
||||
if (a._type != NetworkManager.SETTING_VPN_SETTING_NAME) {
|
||||
@@ -1965,7 +2114,7 @@ const NMApplet = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
this._mainConnection = activating || default_ip4 || default_ip6 || this._activeConnections[0] || null;
|
||||
this._mainConnection = activating || default_ip4 || default_ip6 || active_any || null;
|
||||
this._vpnConnection = active_vpn;
|
||||
},
|
||||
|
||||
@@ -1991,7 +2140,25 @@ const NMApplet = new Lang.Class({
|
||||
return false;
|
||||
},
|
||||
|
||||
_addConnection: function(connection) {
|
||||
_readConnections: function() {
|
||||
let connections = this._settings.list_connections();
|
||||
for (let i = 0; i < connections.length; i++) {
|
||||
let connection = connections[i];
|
||||
if (this._ignoreConnection(connection))
|
||||
continue;
|
||||
if (connection._updatedId) {
|
||||
// connection was already seen (for example because NetworkManager was restarted)
|
||||
continue;
|
||||
}
|
||||
connection._removedId = connection.connect('removed', Lang.bind(this, this._connectionRemoved));
|
||||
connection._updatedId = connection.connect('updated', Lang.bind(this, this._updateConnection));
|
||||
|
||||
this._updateConnection(connection);
|
||||
this._connections.push(connection);
|
||||
}
|
||||
},
|
||||
|
||||
_newConnection: function(settings, connection) {
|
||||
if (this._ignoreConnection(connection))
|
||||
return;
|
||||
if (connection._updatedId) {
|
||||
@@ -2004,22 +2171,14 @@ const NMApplet = new Lang.Class({
|
||||
|
||||
this._updateConnection(connection);
|
||||
this._connections.push(connection);
|
||||
},
|
||||
|
||||
_readConnections: function() {
|
||||
let connections = this._settings.list_connections();
|
||||
connections.forEach(Lang.bind(this, this._addConnection));
|
||||
},
|
||||
|
||||
_newConnection: function(settings, connection) {
|
||||
this._addConnection(connection);
|
||||
this._updateIcon();
|
||||
},
|
||||
|
||||
_connectionRemoved: function(connection) {
|
||||
let pos = this._connections.indexOf(connection);
|
||||
if (pos != -1)
|
||||
this._connections.splice(connection, 1);
|
||||
this._connections.splice(connection);
|
||||
|
||||
let section = connection._section;
|
||||
|
||||
|
@@ -307,7 +307,7 @@ const Indicator = new Lang.Class({
|
||||
this._headphoneIcon.visible = value;
|
||||
}));
|
||||
|
||||
this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' }));
|
||||
this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'audio-headphones-symbolic' }));
|
||||
this._headphoneIcon.visible = false;
|
||||
|
||||
this.menu.addMenuItem(this._volumeMenu);
|
||||
|
@@ -91,10 +91,6 @@ const UnlockDialog = new Lang.Class({
|
||||
this._promptLoginHint.hide();
|
||||
this.contentLayout.add_actor(this._promptLoginHint);
|
||||
|
||||
let spinnerIcon = global.datadir + '/theme/process-working.svg';
|
||||
this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, LoginDialog.WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
|
||||
this.allowCancel = false;
|
||||
this.buttonLayout.visible = true;
|
||||
this.addButton({ label: _("Cancel"),
|
||||
@@ -105,12 +101,11 @@ const UnlockDialog = new Lang.Class({
|
||||
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.placeSpinner({ 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 },
|
||||
@@ -164,28 +159,6 @@ const UnlockDialog = new Lang.Class({
|
||||
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) {
|
||||
if (message) {
|
||||
this._promptMessage.text = message;
|
||||
@@ -216,7 +189,7 @@ const UnlockDialog = new Lang.Class({
|
||||
|
||||
this._currentQuery = serviceName;
|
||||
this._updateSensitivity(true);
|
||||
this._setWorking(false);
|
||||
this.setWorking(false);
|
||||
},
|
||||
|
||||
_showLoginHint: function(verifier, message) {
|
||||
@@ -235,7 +208,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);
|
||||
this.setWorking(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -246,7 +219,7 @@ const UnlockDialog = new Lang.Class({
|
||||
this._currentQuery = null;
|
||||
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(true);
|
||||
this.setWorking(true);
|
||||
|
||||
this._userVerifier.answerQuery(query, this._promptEntry.text);
|
||||
},
|
||||
@@ -286,7 +259,7 @@ const UnlockDialog = new Lang.Class({
|
||||
this._promptEntry.menu.isPassword = true;
|
||||
|
||||
this._updateSensitivity(false);
|
||||
this._setWorking(false);
|
||||
this.setWorking(false);
|
||||
},
|
||||
|
||||
_escape: function() {
|
||||
|
@@ -16,6 +16,7 @@ const UserWidget = new Lang.Class({
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'user-widget',
|
||||
vertical: false });
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._avatar = new UserMenu.UserAvatarWidget(user);
|
||||
this.actor.add(this._avatar.actor,
|
||||
@@ -36,7 +37,7 @@ const UserWidget = new Lang.Class({
|
||||
this._updateUser();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
_onDestroy: function() {
|
||||
if (this._userLoadedId != 0) {
|
||||
this._user.disconnect(this._userLoadedId);
|
||||
this._userLoadedId = 0;
|
||||
@@ -46,8 +47,6 @@ const UserWidget = new Lang.Class({
|
||||
this._user.disconnect(this._userChangedId);
|
||||
this._userChangedId = 0;
|
||||
}
|
||||
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
_updateUser: function() {
|
||||
|
@@ -150,14 +150,6 @@ const ViewSelector = new Lang.Class({
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Lang.bind(this, this._toggleAppsPage));
|
||||
|
||||
Main.wm.addKeybinding('toggle-overview',
|
||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Lang.bind(Main.overview, Main.overview.toggle));
|
||||
|
||||
},
|
||||
|
||||
_toggleAppsPage: function() {
|
||||
@@ -186,10 +178,6 @@ const ViewSelector = new Lang.Class({
|
||||
Main.overview.fadeInDesktop();
|
||||
},
|
||||
|
||||
setWorkspacesFullGeometry: function(geom) {
|
||||
this._workspacesDisplay.setWorkspacesFullGeometry(geom);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._workspacesDisplay.hide();
|
||||
},
|
||||
|
@@ -136,6 +136,42 @@ const WindowManager = new Lang.Class({
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.allowKeybinding('switch-to-workspace-1',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-2',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-3',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-4',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-5',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-6',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-7',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-8',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-9',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-10',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-11',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.allowKeybinding('switch-to-workspace-12',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this.setCustomKeybindingHandler('switch-applications',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
|
@@ -753,6 +753,13 @@ const LayoutStrategy = new Lang.Class({
|
||||
layout.space = space;
|
||||
},
|
||||
|
||||
_getDistance: function (row, actor) {
|
||||
let dist_x = actor.x - row.x;
|
||||
let dist_y = actor.y - row.y;
|
||||
|
||||
return Math.sqrt(Math.pow(dist_x, 2) + Math.pow(dist_y, 2));
|
||||
},
|
||||
|
||||
computeWindowSlots: function(layout, area) {
|
||||
this._computeRowSizes(layout);
|
||||
|
||||
@@ -760,36 +767,28 @@ const LayoutStrategy = new Lang.Class({
|
||||
|
||||
let slots = [];
|
||||
|
||||
// Do this in three parts.
|
||||
let height = 0;
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
height += row.height + this._rowSpacing;
|
||||
}
|
||||
|
||||
height -= this._rowSpacing;
|
||||
|
||||
let y = 0;
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
|
||||
// If this window layout row doesn't fit in the actual
|
||||
// geometry, then apply an additional scale to it.
|
||||
row.additionalScale = Math.min(1, area.width / row.width, area.height / height);
|
||||
|
||||
row.x = area.x + (Math.max(area.width - row.width, 0) / 2) * row.additionalScale;
|
||||
row.y = area.y + (y + Math.max(area.height - height, 0) / 2) * row.additionalScale;
|
||||
row.x = area.x + (area.width - row.width) / 2;
|
||||
row.y = area.y + y;
|
||||
y += row.height + this._rowSpacing;
|
||||
row.windows.sort(Lang.bind(this, function(a, b) {
|
||||
return this._getDistance(row, a.realWindow) - this._getDistance(row, b.realWindow);
|
||||
}));
|
||||
}
|
||||
|
||||
let height = y - this._rowSpacing;
|
||||
let baseY = (area.height - height) / 2;
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
row.y += baseY;
|
||||
let x = row.x;
|
||||
for (let j = 0; j < row.windows.length; j++) {
|
||||
let window = row.windows[j];
|
||||
|
||||
let s = scale * this._computeWindowScale(window) * row.additionalScale;
|
||||
let s = scale * this._computeWindowScale(window);
|
||||
let cellWidth = window.actor.width * s;
|
||||
let cellHeight = window.actor.height * s;
|
||||
|
||||
@@ -833,13 +832,6 @@ const UnalignedLayoutStrategy = new Lang.Class({
|
||||
return false;
|
||||
},
|
||||
|
||||
_sortRow: function(row) {
|
||||
// Sort windows horizontally to minimize travel distance
|
||||
row.windows.sort(function(a, b) {
|
||||
return a.realWindow.x - b.realWindow.x;
|
||||
});
|
||||
},
|
||||
|
||||
computeLayout: function(windows, layout) {
|
||||
let numRows = layout.numRows;
|
||||
|
||||
@@ -870,7 +862,6 @@ const UnalignedLayoutStrategy = new Lang.Class({
|
||||
row.windows.push(window);
|
||||
row.fullWidth += width;
|
||||
} else {
|
||||
this._sortRow(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -892,14 +883,6 @@ const UnalignedLayoutStrategy = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
function padArea(area, padding) {
|
||||
return {
|
||||
x: area.x + padding.left,
|
||||
y: area.y + padding.top,
|
||||
width: area.width - padding.left - padding.right,
|
||||
height: area.height - padding.top - padding.bottom,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @metaWorkspace: a #Meta.Workspace, or null
|
||||
@@ -911,19 +894,10 @@ const Workspace = new Lang.Class({
|
||||
// When dragging a window, we use this slot for reserve space.
|
||||
this._reservedSlot = null;
|
||||
this.metaWorkspace = metaWorkspace;
|
||||
|
||||
// The full geometry is the geometry we should try and position
|
||||
// windows for. The actual geometry we allocate may be less than
|
||||
// this, like if the workspace switcher is slid out.
|
||||
this._fullGeometry = null;
|
||||
|
||||
// The actual geometry is the geometry we need to arrange windows
|
||||
// in. If this is a smaller area than the full geometry, we'll
|
||||
// do some simple aspect ratio like math to fit the layout calculated
|
||||
// for the full geometry into this area.
|
||||
this._actualGeometry = null;
|
||||
|
||||
this._currentLayout = null;
|
||||
this._x = 0;
|
||||
this._y = 0;
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
|
||||
this.monitorIndex = monitorIndex;
|
||||
this._monitor = Main.layoutManager.monitors[this.monitorIndex];
|
||||
@@ -973,22 +947,23 @@ const Workspace = new Lang.Class({
|
||||
|
||||
this._positionWindowsFlags = 0;
|
||||
this._positionWindowsId = 0;
|
||||
|
||||
this._currentLayout = null;
|
||||
},
|
||||
|
||||
setFullGeometry: function(geom) {
|
||||
this._fullGeometry = geom;
|
||||
this._recalculateWindowPositions(WindowPositionFlags.NONE);
|
||||
},
|
||||
|
||||
setActualGeometry: function(geom) {
|
||||
this._actualGeometry = geom;
|
||||
setGeometry: function(x, y, width, height) {
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
||||
this._dropRect.set_position(geom.x, geom.y);
|
||||
this._dropRect.set_size(geom.width, geom.height);
|
||||
this._updateWindowPositions(WindowPositionFlags.NONE);
|
||||
this._dropRect.set_position(x, y);
|
||||
this._dropRect.set_size(width, height);
|
||||
return false;
|
||||
}));
|
||||
|
||||
this.positionWindows(WindowPositionFlags.NONE);
|
||||
},
|
||||
|
||||
_lookupIndex: function (metaWindow) {
|
||||
@@ -1016,32 +991,37 @@ const Workspace = new Lang.Class({
|
||||
clone = null;
|
||||
|
||||
this._reservedSlot = clone;
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
|
||||
this._currentLayout = null;
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||
},
|
||||
|
||||
_recalculateWindowPositions: function(flags) {
|
||||
/**
|
||||
* positionWindows:
|
||||
* @flags:
|
||||
* INITIAL - this is the initial positioning of the windows.
|
||||
* ANIMATE - Indicates that we need animate changing position.
|
||||
*/
|
||||
positionWindows: function(flags) {
|
||||
this._positionWindowsFlags |= flags;
|
||||
|
||||
if (this._positionWindowsId > 0)
|
||||
return;
|
||||
|
||||
this._positionWindowsId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
||||
this._realRecalculateWindowPositions(this._positionWindowsFlags);
|
||||
this._realPositionWindows(this._positionWindowsFlags);
|
||||
this._positionWindowsFlags = 0;
|
||||
this._positionWindowsId = 0;
|
||||
return false;
|
||||
}));
|
||||
},
|
||||
|
||||
_realRecalculateWindowPositions: function(flags) {
|
||||
_realPositionWindows : function(flags) {
|
||||
if (this._repositionWindowsId > 0) {
|
||||
Mainloop.source_remove(this._repositionWindowsId);
|
||||
this._repositionWindowsId = 0;
|
||||
}
|
||||
|
||||
let clones = this._windows.slice();
|
||||
if (clones.length == 0)
|
||||
return;
|
||||
|
||||
clones.sort(function(a, b) {
|
||||
return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence();
|
||||
@@ -1050,25 +1030,11 @@ const Workspace = new Lang.Class({
|
||||
if (this._reservedSlot)
|
||||
clones.push(this._reservedSlot);
|
||||
|
||||
this._currentLayout = this._computeLayout(clones);
|
||||
this._updateWindowPositions(flags);
|
||||
},
|
||||
|
||||
_updateWindowPositions: function(flags) {
|
||||
if (this._currentLayout == null) {
|
||||
this._recalculateWindowPositions(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
||||
let animate = flags & WindowPositionFlags.ANIMATE;
|
||||
|
||||
let layout = this._currentLayout;
|
||||
let strategy = layout.strategy;
|
||||
|
||||
let [, , padding] = this._getSpacingAndPadding();
|
||||
let area = padArea(this._actualGeometry, padding);
|
||||
let slots = strategy.computeWindowSlots(layout, area);
|
||||
// Start the animations
|
||||
let slots = this._computeAllWindowSlots(clones);
|
||||
|
||||
let currentWorkspace = global.screen.get_active_workspace();
|
||||
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
|
||||
@@ -1128,6 +1094,7 @@ const Workspace = new Lang.Class({
|
||||
Tweener.removeTweens(clone.actor);
|
||||
clone.actor.set_position(x, y);
|
||||
clone.actor.set_scale(scale, scale);
|
||||
clone.actor.set_opacity(255);
|
||||
clone.overlay.relayout(false);
|
||||
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
|
||||
}
|
||||
@@ -1182,8 +1149,8 @@ const Workspace = new Lang.Class({
|
||||
let [x, y, mask] = global.get_pointer();
|
||||
|
||||
let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
|
||||
let inWorkspace = (this._fullGeometry.x < x && x < this._fullGeometry.x + this._fullGeometry.width &&
|
||||
this._fullGeometry.y < y && y < this._fullGeometry.y + this._fullGeometry.height);
|
||||
let inWorkspace = (this._x < x && x < this._x + this._width &&
|
||||
this._y < y && y < this._y + this._height);
|
||||
|
||||
if (pointerHasMoved && inWorkspace) {
|
||||
// store current cursor position
|
||||
@@ -1198,7 +1165,7 @@ const Workspace = new Lang.Class({
|
||||
return true;
|
||||
}
|
||||
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||
return false;
|
||||
},
|
||||
|
||||
@@ -1303,7 +1270,7 @@ const Workspace = new Lang.Class({
|
||||
}
|
||||
|
||||
this._currentLayout = null;
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
@@ -1340,8 +1307,13 @@ const Workspace = new Lang.Class({
|
||||
|
||||
// Animate the full-screen to Overview transition.
|
||||
zoomToOverview : function() {
|
||||
this._currentLayout = null;
|
||||
|
||||
// Position and scale the windows.
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
||||
if (Main.overview.animationInProgress)
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
||||
else
|
||||
this.positionWindows(WindowPositionFlags.INITIAL);
|
||||
},
|
||||
|
||||
// Animates the return from Overview mode
|
||||
@@ -1465,7 +1437,7 @@ const Workspace = new Lang.Class({
|
||||
}));
|
||||
clone.connect('size-changed',
|
||||
Lang.bind(this, function() {
|
||||
this._recalculateWindowPositions(WindowPositionFlags.NONE);
|
||||
this.positionWindows(0);
|
||||
}));
|
||||
|
||||
this.actor.add_actor(clone.actor);
|
||||
@@ -1514,14 +1486,12 @@ const Workspace = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_getBestLayout: function(windows, area, rowSpacing, columnSpacing) {
|
||||
_computeLayout: function(windows, area, rowSpacing, columnSpacing) {
|
||||
// We look for the largest scale that allows us to fit the
|
||||
// largest row/tallest column on the workspace.
|
||||
|
||||
let lastLayout = {};
|
||||
|
||||
let strategy = new UnalignedLayoutStrategy(this._monitor, rowSpacing, columnSpacing);
|
||||
|
||||
for (let numRows = 1; ; numRows++) {
|
||||
let numColumns = Math.ceil(windows.length / numRows);
|
||||
|
||||
@@ -1531,6 +1501,8 @@ const Workspace = new Lang.Class({
|
||||
if (numColumns == lastLayout.numColumns)
|
||||
break;
|
||||
|
||||
let strategy = new UnalignedLayoutStrategy(this._monitor, rowSpacing, columnSpacing);
|
||||
|
||||
let layout = { area: area, strategy: strategy, numRows: numRows, numColumns: numColumns };
|
||||
strategy.computeLayout(windows, layout);
|
||||
strategy.computeScaleAndSpace(layout);
|
||||
@@ -1544,7 +1516,18 @@ const Workspace = new Lang.Class({
|
||||
return lastLayout;
|
||||
},
|
||||
|
||||
_getSpacingAndPadding: function() {
|
||||
_rectEqual: function(one, two) {
|
||||
if (one == two)
|
||||
return true;
|
||||
|
||||
return (one.x == two.x &&
|
||||
one.y == two.y &&
|
||||
one.width == two.width &&
|
||||
one.height == two.height);
|
||||
},
|
||||
|
||||
_computeAllWindowSlots: function(windows) {
|
||||
let totalWindows = windows.length;
|
||||
let node = this.actor.get_theme_node();
|
||||
|
||||
// Window grid spacing
|
||||
@@ -1557,14 +1540,21 @@ const Workspace = new Lang.Class({
|
||||
right: node.get_padding(St.Side.RIGHT),
|
||||
};
|
||||
|
||||
if (!totalWindows)
|
||||
return [];
|
||||
|
||||
let closeButtonHeight, captionHeight;
|
||||
let leftBorder, rightBorder;
|
||||
|
||||
// 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();
|
||||
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];
|
||||
[leftBorder, rightBorder] = [0, 0];
|
||||
}
|
||||
|
||||
rowSpacing += captionHeight;
|
||||
columnSpacing += (rightBorder + leftBorder) / 2;
|
||||
@@ -1573,13 +1563,25 @@ const Workspace = new Lang.Class({
|
||||
padding.left += leftBorder;
|
||||
padding.right += rightBorder;
|
||||
|
||||
return [rowSpacing, columnSpacing, padding];
|
||||
},
|
||||
let area = {
|
||||
x: this._x + padding.left,
|
||||
y: this._y + padding.top,
|
||||
width: this._width - padding.left - padding.right,
|
||||
height: this._height - padding.top - padding.bottom,
|
||||
};
|
||||
|
||||
_computeLayout: function(windows) {
|
||||
let [rowSpacing, columnSpacing, padding] = this._getSpacingAndPadding();
|
||||
let area = padArea(this._fullGeometry, padding);
|
||||
return this._getBestLayout(windows, area, rowSpacing, columnSpacing);
|
||||
if (!this._currentLayout)
|
||||
this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing);
|
||||
|
||||
let layout = this._currentLayout;
|
||||
let strategy = layout.strategy;
|
||||
|
||||
if (!this._rectEqual(area, layout.area)) {
|
||||
layout.area = area;
|
||||
strategy.computeScaleAndSpace(layout);
|
||||
}
|
||||
|
||||
return strategy.computeWindowSlots(layout, area);
|
||||
},
|
||||
|
||||
_onCloneSelected : function (clone, time) {
|
||||
|
@@ -23,18 +23,6 @@ const MAX_WORKSPACES = 16;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
function rectEqual(one, two) {
|
||||
if (one == two)
|
||||
return true;
|
||||
|
||||
if (!one || !two)
|
||||
return false;
|
||||
|
||||
return (one.x == two.x &&
|
||||
one.y == two.y &&
|
||||
one.width == two.width &&
|
||||
one.height == two.height);
|
||||
}
|
||||
|
||||
const WorkspacesView = new Lang.Class({
|
||||
Name: 'WorkspacesView',
|
||||
@@ -55,9 +43,10 @@ const WorkspacesView = new Lang.Class({
|
||||
this._updateWorkspaceActors(false);
|
||||
}));
|
||||
|
||||
this._fullGeometry = null;
|
||||
this._actualGeometry = null;
|
||||
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
this._x = 0;
|
||||
this._y = 0;
|
||||
this._spacing = 0;
|
||||
this._animating = false; // tweening
|
||||
this._scrolling = false; // swipe-scrolling
|
||||
@@ -96,8 +85,8 @@ const WorkspacesView = new Lang.Class({
|
||||
this._overviewShownId =
|
||||
Main.overview.connect('shown',
|
||||
Lang.bind(this, function() {
|
||||
this.actor.set_clip(this._fullGeometry.x, this._fullGeometry.y,
|
||||
this._fullGeometry.width, this._fullGeometry.height);
|
||||
this.actor.set_clip(this._x, this._y,
|
||||
this._width, this._height);
|
||||
}));
|
||||
|
||||
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
|
||||
@@ -135,8 +124,10 @@ const WorkspacesView = new Lang.Class({
|
||||
continue;
|
||||
|
||||
let ws = new Workspace.Workspace(null, i);
|
||||
ws.setFullGeometry(monitors[i]);
|
||||
ws.setActualGeometry(monitors[i]);
|
||||
ws.setGeometry(monitors[i].x,
|
||||
monitors[i].y,
|
||||
monitors[i].width,
|
||||
monitors[i].height);
|
||||
global.overlay_group.add_actor(ws.actor);
|
||||
this._extraWorkspaces.push(ws);
|
||||
}
|
||||
@@ -148,24 +139,18 @@ const WorkspacesView = new Lang.Class({
|
||||
this._extraWorkspaces = [];
|
||||
},
|
||||
|
||||
setFullGeometry: function(geom) {
|
||||
if (rectEqual(this._fullGeometry, geom))
|
||||
return;
|
||||
setGeometry: function(x, y, width, height) {
|
||||
if (this._x == x && this._y == y &&
|
||||
this._width == width && this._height == height)
|
||||
return;
|
||||
|
||||
this._fullGeometry = geom;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setFullGeometry(geom);
|
||||
},
|
||||
|
||||
setActualGeometry: function(geom) {
|
||||
if (rectEqual(this._actualGeometry, geom))
|
||||
return;
|
||||
|
||||
this._actualGeometry = geom;
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setActualGeometry(geom);
|
||||
this._workspaces[i].setGeometry(x, y, width, height);
|
||||
},
|
||||
|
||||
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||
@@ -225,7 +210,7 @@ const WorkspacesView = new Lang.Class({
|
||||
|
||||
Tweener.removeTweens(workspace.actor);
|
||||
|
||||
let y = (w - active) * (this._fullGeometry.height + this._spacing);
|
||||
let y = (w - active) * (this._height + this._spacing);
|
||||
|
||||
if (showAnimation) {
|
||||
let params = { y: y,
|
||||
@@ -296,9 +281,8 @@ const WorkspacesView = new Lang.Class({
|
||||
|
||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
this._workspaces[w].setFullGeometry(this._fullGeometry);
|
||||
if (this._actualGeometry)
|
||||
this._workspaces[w].setActualGeometry(this._actualGeometry);
|
||||
this._workspaces[w].setGeometry(this._x, this._y,
|
||||
this._width, this._height);
|
||||
this.actor.add_actor(this._workspaces[w].actor);
|
||||
}
|
||||
|
||||
@@ -446,7 +430,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.Widget({ clip_to_allocation: true });
|
||||
this.actor.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesActualGeometry));
|
||||
this.actor.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesGeometry));
|
||||
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
||||
|
||||
let clickAction = new Clutter.ClickAction()
|
||||
@@ -500,8 +484,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
|
||||
this._notifyOpacityId = 0;
|
||||
this._scrollEventId = 0;
|
||||
|
||||
this._fullGeometry = null;
|
||||
},
|
||||
|
||||
_onPan: function(action) {
|
||||
@@ -590,8 +572,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._workspacesViews.push(view);
|
||||
}
|
||||
|
||||
this._updateWorkspacesFullGeometry();
|
||||
this._updateWorkspacesActualGeometry();
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
global.overlay_group.add_actor(this._workspacesViews[i].actor);
|
||||
@@ -651,48 +632,31 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
}));
|
||||
},
|
||||
|
||||
// This geometry should always be the fullest geometry
|
||||
// the workspaces switcher can ever be allocated, as if
|
||||
// the sliding controls were never slid in at all.
|
||||
setWorkspacesFullGeometry: function(geom) {
|
||||
this._fullGeometry = geom;
|
||||
this._updateWorkspacesFullGeometry();
|
||||
},
|
||||
|
||||
_updateWorkspacesFullGeometry: function() {
|
||||
_updateWorkspacesGeometry: function() {
|
||||
if (!this._workspacesViews.length)
|
||||
return;
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == this._primaryIndex) {
|
||||
this._workspacesViews[m].setFullGeometry(this._fullGeometry);
|
||||
m++;
|
||||
} else if (!this._workspacesOnlyOnPrimary) {
|
||||
this._workspacesViews[m].setFullGeometry(monitors[i]);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
},
|
||||
let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
|
||||
let fullHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
|
||||
|
||||
_updateWorkspacesActualGeometry: function() {
|
||||
if (!this._workspacesViews.length)
|
||||
return;
|
||||
let width = fullWidth;
|
||||
let height = fullHeight;
|
||||
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
let width = this.actor.allocation.x2 - this.actor.allocation.x1;
|
||||
let height = this.actor.allocation.y2 - this.actor.allocation.y1;
|
||||
let geometry = { x: x, y: y, width: width, height: height };
|
||||
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == this._primaryIndex) {
|
||||
this._workspacesViews[m].setActualGeometry(geometry);
|
||||
this._workspacesViews[m].setGeometry(x, y, width, height);
|
||||
m++;
|
||||
} else if (!this._workspacesOnlyOnPrimary) {
|
||||
this._workspacesViews[m].setActualGeometry(monitors[i]);
|
||||
this._workspacesViews[m].setGeometry(monitors[i].x,
|
||||
monitors[i].y,
|
||||
monitors[i].width,
|
||||
monitors[i].height);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
@@ -125,6 +125,12 @@
|
||||
<listitem><para>List possible modes and exit</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--clutter-display=<replaceable>DISPLAY</replaceable></option></term>
|
||||
|
||||
<listitem><para>Clutter the option display (otherwise ignored)</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
|
@@ -46,6 +46,7 @@ ms
|
||||
nb
|
||||
nl
|
||||
nn
|
||||
oc
|
||||
or
|
||||
pa
|
||||
pl
|
||||
|
2
po/eu.po
2
po/eu.po
@@ -1244,7 +1244,7 @@ msgstr "Ezezaguna"
|
||||
#, c-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] "Mezu berri &d"
|
||||
msgstr[0] "Mezu berri %d"
|
||||
msgstr[1] "%d mezu berri"
|
||||
|
||||
#: ../js/ui/overview.js:84
|
||||
|
98
po/ia.po
98
po/ia.po
@@ -5,10 +5,10 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Project-Id-Version: gnome-shell 3.8\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-04-23 19:57+0000\n"
|
||||
"POT-Creation-Date: 2013-04-19 21:48+0000\n"
|
||||
"PO-Revision-Date: 2013-04-23 08:00+0400\n"
|
||||
"Last-Translator: Nik Kalach <nikka@fedoraproject.org>\n"
|
||||
"Language-Team: Interlingua <trans-ia@lists.fedoraproject.org>\n"
|
||||
@@ -39,14 +39,10 @@ msgid "Focus the active notification"
|
||||
msgstr "Mitter foco al notificationes active"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:4
|
||||
msgid "Show the overview"
|
||||
msgstr "Monstrar le panorama"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:5
|
||||
msgid "Show all applications"
|
||||
msgstr "Monstrar tote le applicationes"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:6
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:5
|
||||
msgid "Open the application menu"
|
||||
msgstr "Aperir le menu de applicationes"
|
||||
|
||||
@@ -226,52 +222,44 @@ msgstr ""
|
||||
"panorama de activitates."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
|
||||
msgid "Keybinding to open the overview"
|
||||
msgstr "Association de claves pro aperir le panorama"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
|
||||
msgid "Keybinding to open the Activities Overview."
|
||||
msgstr "Association de claves pro aperir le panorama de activitates"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
msgid "Keybinding to toggle the visibility of the message tray"
|
||||
msgstr ""
|
||||
"Association de claves pro commutar le visibilitate del tiratorio de messages"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
|
||||
msgid "Keybinding to toggle the visibility of the message tray."
|
||||
msgstr ""
|
||||
"Association de claves pro commutar le visibilitate del tiratorio de messages."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
msgid "Keybinding to focus the active notification"
|
||||
msgstr "Association de claves pro mitter foco al notificationes active"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
|
||||
msgid "Keybinding to focus the active notification."
|
||||
msgstr "Association de claves pro mitter foco al notificationes active."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
msgid "Keybinding to toggle the screen recorder"
|
||||
msgstr "Association de claves pro commutar le registrator de schermo"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
|
||||
msgid "Keybinding to start/stop the builtin screen recorder."
|
||||
msgstr "Association de claves pro initiar/arrestar le registration de schermo."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
msgid "Which keyboard to use"
|
||||
msgstr "Que claviero usar"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
|
||||
msgid "The type of keyboard to use."
|
||||
msgstr "Le typo de claviero a usar."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
|
||||
msgid "Framerate used for recording screencasts."
|
||||
msgstr "Rata de quadros usate pro registrar le video de schermo."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
@@ -279,11 +267,11 @@ msgstr ""
|
||||
"Le numero de imagines per secunda in le video de schermo registrate per le "
|
||||
"registrator incorporate in GNOME Shell."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "Le catena usante per gstreamer pro codificar video de schermo"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
@@ -309,11 +297,11 @@ msgstr ""
|
||||
"queue ! webmmux' e registra in WEBM usante le codec VP8. %T designa le "
|
||||
"numero de filos optimal pro le systema."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
|
||||
msgid "File extension used for storing the screencast"
|
||||
msgstr "Extension de file a usar pro slaveguardar le video de schermo"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39
|
||||
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 "
|
||||
@@ -323,11 +311,11 @@ msgstr ""
|
||||
"currente e iste extension. Illo deberea esser modificate si le formato de "
|
||||
"container usate pro registar le video es differente."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
|
||||
msgid "The application icon mode."
|
||||
msgstr "Le modo de icone in le selector de applicationes."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
|
||||
msgid ""
|
||||
"Configures how the windows are shown in the switcher. Valid possibilities "
|
||||
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
|
||||
@@ -338,22 +326,22 @@ msgstr ""
|
||||
"fenestra), 'app-icon-only' (monstrar solmente un icone del application) o "
|
||||
"'both' (monstrar tote le duo)."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:44
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
|
||||
msgid "Attach modal dialog to the parent window"
|
||||
msgstr "Attaccar le dialogo modal al fenestra parental"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:45
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43
|
||||
msgid ""
|
||||
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
|
||||
msgstr ""
|
||||
"Iste clave supplanta le clave in org.gnome.mutter quando GNOME Shell es "
|
||||
"lanceate."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:46
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:44
|
||||
msgid "Arrangement of buttons on the titlebar"
|
||||
msgstr "Arrangiamento de buttones sur le barra de titulo"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:47
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:45
|
||||
msgid ""
|
||||
"This key overrides the key in org.gnome.desktop.wm.preferences when running "
|
||||
"GNOME Shell."
|
||||
@@ -361,15 +349,15 @@ msgstr ""
|
||||
"Iste clave supplanta le clave in org.gnome.desktop.wm.preferences quando "
|
||||
"GNOME Shell es lanceate."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:48
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:46
|
||||
msgid "Enable edge tiling when dropping windows on screen edges"
|
||||
msgstr "Activar le tegulage de fenestras depositate sur le bordos del schermo"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:49
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:47
|
||||
msgid "Workspaces are managed dynamically"
|
||||
msgstr "Le spatios de travalio se gere dynamicamente"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:50
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:48
|
||||
msgid "Workspaces only on primary monitor"
|
||||
msgstr "Le spatios de travalio es solmente sur le schermo principal"
|
||||
|
||||
@@ -475,23 +463,23 @@ msgstr "Impossibile de analysar le commando:"
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Falta al execution de '%s':"
|
||||
|
||||
#: ../js/ui/appDisplay.js:351
|
||||
#: ../js/ui/appDisplay.js:349
|
||||
msgid "Frequent"
|
||||
msgstr "Frequente"
|
||||
|
||||
#: ../js/ui/appDisplay.js:358
|
||||
#: ../js/ui/appDisplay.js:356
|
||||
msgid "All"
|
||||
msgstr "Tote"
|
||||
|
||||
#: ../js/ui/appDisplay.js:916
|
||||
#: ../js/ui/appDisplay.js:914
|
||||
msgid "New Window"
|
||||
msgstr "Nove fenestra"
|
||||
|
||||
#: ../js/ui/appDisplay.js:919 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Remover del favoritos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:920
|
||||
#: ../js/ui/appDisplay.js:918
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Adder al favoritos"
|
||||
|
||||
@@ -1238,35 +1226,35 @@ msgstr "Expunger messages"
|
||||
msgid "Notification Settings"
|
||||
msgstr "Parametros de notificationes"
|
||||
|
||||
#: ../js/ui/messageTray.js:1710
|
||||
#: ../js/ui/messageTray.js:1709
|
||||
msgid "No Messages"
|
||||
msgstr "Necun message"
|
||||
|
||||
#: ../js/ui/messageTray.js:1783
|
||||
#: ../js/ui/messageTray.js:1785
|
||||
msgid "Message Tray"
|
||||
msgstr "Tiratorio de messages"
|
||||
|
||||
#: ../js/ui/messageTray.js:2801
|
||||
#: ../js/ui/messageTray.js:2813
|
||||
msgid "System Information"
|
||||
msgstr "Information de systema"
|
||||
|
||||
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:378
|
||||
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374
|
||||
msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "Incognite"
|
||||
|
||||
#: ../js/ui/overviewControls.js:472 ../js/ui/screenShield.js:149
|
||||
#: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
|
||||
#, c-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] "%d nove message"
|
||||
msgstr[1] "%d nove messages"
|
||||
|
||||
#: ../js/ui/overview.js:82
|
||||
#: ../js/ui/overview.js:84
|
||||
msgid "Undo"
|
||||
msgstr "Disfacer"
|
||||
|
||||
#: ../js/ui/overview.js:127
|
||||
#: ../js/ui/overview.js:129
|
||||
msgid "Overview"
|
||||
msgstr "Panorama"
|
||||
|
||||
@@ -1274,21 +1262,21 @@ msgstr "Panorama"
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: ../js/ui/overview.js:260
|
||||
#: ../js/ui/overview.js:271
|
||||
msgid "Type to search…"
|
||||
msgstr "Scribe pro cercar…"
|
||||
|
||||
#: ../js/ui/panel.js:641
|
||||
#: ../js/ui/panel.js:633
|
||||
msgid "Quit"
|
||||
msgstr "Quitar"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:692
|
||||
#: ../js/ui/panel.js:657
|
||||
msgid "Activities"
|
||||
msgstr "Activitates"
|
||||
|
||||
#: ../js/ui/panel.js:989
|
||||
#: ../js/ui/panel.js:954
|
||||
msgid "Top Bar"
|
||||
msgstr "Barra superior"
|
||||
|
||||
@@ -1297,7 +1285,7 @@ msgstr "Barra superior"
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:718
|
||||
#: ../js/ui/popupMenu.js:727
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
@@ -1932,7 +1920,7 @@ msgstr "Usar un modo specific, per ex. \"gdm\" pro le schermo de accesso"
|
||||
msgid "List possible modes"
|
||||
msgstr "Monstrar le lista del modos possibile"
|
||||
|
||||
#: ../src/shell-app.c:626
|
||||
#: ../src/shell-app.c:622
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "Impossibile de lancear '%s'"
|
||||
|
273
po/lt.po
273
po/lt.po
@@ -11,9 +11,9 @@ 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: 2013-03-23 11:49+0000\n"
|
||||
"PO-Revision-Date: 2013-03-26 22:43+0200\n"
|
||||
"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n"
|
||||
"POT-Creation-Date: 2013-12-20 16:10+0000\n"
|
||||
"PO-Revision-Date: 2013-12-21 16:31+0200\n"
|
||||
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
|
||||
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
|
||||
"Language: lt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -360,7 +360,7 @@ msgstr "Darbalaukiai tik pagrindiniame monitoriuje"
|
||||
#: ../js/extensionPrefs/main.js:125
|
||||
#, c-format
|
||||
msgid "There was an error loading the preferences dialog for %s:"
|
||||
msgstr "Įvyko klaida įkeliant %s nustatymų dialogą:"
|
||||
msgstr "Kilo klaida įkeliant %s nustatymų dialogą:"
|
||||
|
||||
#: ../js/extensionPrefs/main.js:165
|
||||
msgid "Extension"
|
||||
@@ -370,43 +370,50 @@ msgstr "Plėtinys"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "Išskleidžiamajame sąraše pasirinkite konfigūruotiną plėtinį."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:405
|
||||
#: ../js/gdm/loginDialog.js:371
|
||||
msgid "Session…"
|
||||
msgstr "Seansas…"
|
||||
|
||||
#. 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:630
|
||||
#: ../js/gdm/loginDialog.js:601
|
||||
msgid "Not listed?"
|
||||
msgstr "Nėra sąraše?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375
|
||||
#: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
|
||||
#: ../js/ui/userMenu.js:938
|
||||
msgid "Cancel"
|
||||
msgstr "Atsisakyti"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:802
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "Prisijungti"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:802
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgid "Next"
|
||||
msgstr "Kitas"
|
||||
|
||||
#. Translators: this message is shown below the username entry field
|
||||
#. to clue the user in on how to login to the local network realm
|
||||
#: ../js/gdm/loginDialog.js:888
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(pvz., naudotojas arba %s)"
|
||||
|
||||
#. 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:917 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "Naudotojo vardas: "
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1173
|
||||
#: ../js/gdm/loginDialog.js:1158
|
||||
msgid "Login Window"
|
||||
msgstr "Prisijungimo langas"
|
||||
|
||||
@@ -429,21 +436,16 @@ msgstr "Paleisti iš naujo"
|
||||
msgid "Power Off"
|
||||
msgstr "Išjungti"
|
||||
|
||||
#: ../js/gdm/util.js:249
|
||||
#: ../js/gdm/util.js:248
|
||||
msgid "Authentication error"
|
||||
msgstr "Tapatybės patvirtinimo klaida"
|
||||
|
||||
#. Translators: this message is shown below the password entry field
|
||||
#. to indicate the user can swipe their finger instead
|
||||
#: ../js/gdm/util.js:366
|
||||
#: ../js/gdm/util.js:365
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(arba perbraukite pirštu)"
|
||||
|
||||
#: ../js/gdm/util.js:391
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(pvz., naudotojas arba %s)"
|
||||
|
||||
#: ../js/misc/util.js:97
|
||||
msgid "Command not found"
|
||||
msgstr "Komanda nerasta"
|
||||
@@ -459,23 +461,23 @@ msgstr "Nepavyko perskaityti komandos:"
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Nepavyko įvykdyti „%s“:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:349
|
||||
#: ../js/ui/appDisplay.js:392
|
||||
msgid "Frequent"
|
||||
msgstr "Dažnai naudojamos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:356
|
||||
#: ../js/ui/appDisplay.js:399
|
||||
msgid "All"
|
||||
msgstr "Visos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:914
|
||||
#: ../js/ui/appDisplay.js:977
|
||||
msgid "New Window"
|
||||
msgstr "Naujas langas"
|
||||
|
||||
#: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:980 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Pašalinti iš mėgstamų"
|
||||
|
||||
#: ../js/ui/appDisplay.js:918
|
||||
#: ../js/ui/appDisplay.js:981
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Pridėti prie mėgstamų"
|
||||
|
||||
@@ -512,7 +514,7 @@ msgctxt "event list time"
|
||||
msgid "%H\\u2236%M"
|
||||
msgstr "%H\\u2236%M"
|
||||
|
||||
#. Transators: Shown in calendar event list, if 12h format,
|
||||
#. Translators: Shown in calendar event list, if 12h format,
|
||||
#. \u2236 is a ratio character, similar to : and \u2009 is
|
||||
#. a thin space
|
||||
#: ../js/ui/calendar.js:77
|
||||
@@ -667,11 +669,11 @@ msgstr "Atverti su %s"
|
||||
msgid "Eject"
|
||||
msgstr "Išimti"
|
||||
|
||||
#: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280
|
||||
msgid "Password:"
|
||||
msgstr "Slaptažodis:"
|
||||
|
||||
#: ../js/ui/components/keyring.js:101
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
msgid "Type again:"
|
||||
msgstr "Įveskite dar kartą:"
|
||||
|
||||
@@ -751,15 +753,15 @@ msgstr "Mobiliojo plačiajuosčio tinklo slaptažodis"
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "Būtinas slaptažodis norint prisijungti prie „%s“"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:55
|
||||
#: ../js/ui/components/polkitAgent.js:54
|
||||
msgid "Authentication Required"
|
||||
msgstr "Reikia patvirtinti tapatybę"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:93
|
||||
#: ../js/ui/components/polkitAgent.js:92
|
||||
msgid "Administrator"
|
||||
msgstr "Administratorius"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:165
|
||||
#: ../js/ui/components/polkitAgent.js:170
|
||||
msgid "Authenticate"
|
||||
msgstr "Patvirtinti tapatybę"
|
||||
|
||||
@@ -767,12 +769,12 @@ msgstr "Patvirtinti tapatybę"
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
#: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383
|
||||
#: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "Atsiprašome, tai nesuveikė. Bandykite dar kartą."
|
||||
|
||||
#. Translators: this is a filename used for screencast recording
|
||||
#: ../js/ui/components/recorder.js:48
|
||||
#: ../js/ui/components/recorder.js:47
|
||||
#, no-c-format
|
||||
msgid "Screencast from %d %t"
|
||||
msgstr "Ekrano vaizdo įrašas iš %d %t"
|
||||
@@ -831,14 +833,14 @@ msgstr "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "
|
||||
|
||||
#. Translators: this is the other person changing their old IM name to their new
|
||||
#. IM name.
|
||||
#: ../js/ui/components/telepathyClient.js:985
|
||||
#: ../js/ui/components/telepathyClient.js:986
|
||||
#, c-format
|
||||
msgid "%s is now known as %s"
|
||||
msgstr "%s nuo šiol vadinasi %s"
|
||||
|
||||
#. translators: argument is a room name like
|
||||
#. * room@jabber.org for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1088
|
||||
#: ../js/ui/components/telepathyClient.js:1089
|
||||
#, c-format
|
||||
msgid "Invitation to %s"
|
||||
msgstr "Kvietimas į %s"
|
||||
@@ -846,38 +848,38 @@ msgstr "Kvietimas į %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:1097
|
||||
#, c-format
|
||||
msgid "%s is inviting you to join %s"
|
||||
msgstr "%s jus kviečia prisijungti prie %s"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1098
|
||||
#: ../js/ui/components/telepathyClient.js:1137
|
||||
#: ../js/ui/components/telepathyClient.js:1177
|
||||
#: ../js/ui/components/telepathyClient.js:1240
|
||||
#: ../js/ui/components/telepathyClient.js:1099
|
||||
#: ../js/ui/components/telepathyClient.js:1138
|
||||
#: ../js/ui/components/telepathyClient.js:1178
|
||||
#: ../js/ui/components/telepathyClient.js:1241
|
||||
msgid "Decline"
|
||||
msgstr "Atmesti"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1099
|
||||
#: ../js/ui/components/telepathyClient.js:1178
|
||||
#: ../js/ui/components/telepathyClient.js:1241
|
||||
#: ../js/ui/components/telepathyClient.js:1100
|
||||
#: ../js/ui/components/telepathyClient.js:1179
|
||||
#: ../js/ui/components/telepathyClient.js:1242
|
||||
msgid "Accept"
|
||||
msgstr "Priimti"
|
||||
|
||||
#. translators: argument is a contact name like Alice for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1129
|
||||
#: ../js/ui/components/telepathyClient.js:1130
|
||||
#, c-format
|
||||
msgid "Video call from %s"
|
||||
msgstr "Vaizdo skambutis nuo %s"
|
||||
|
||||
#. translators: argument is a contact name like Alice for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1132
|
||||
#: ../js/ui/components/telepathyClient.js:1133
|
||||
#, c-format
|
||||
msgid "Call from %s"
|
||||
msgstr "Skambutis nuo %s"
|
||||
|
||||
#. translators: this is a button label (verb), not a noun
|
||||
#: ../js/ui/components/telepathyClient.js:1139
|
||||
#: ../js/ui/components/telepathyClient.js:1140
|
||||
msgid "Answer"
|
||||
msgstr "Atsiliepti"
|
||||
|
||||
@@ -886,110 +888,110 @@ msgstr "Atsiliepti"
|
||||
#. * 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:1172
|
||||
#, c-format
|
||||
msgid "%s is sending you %s"
|
||||
msgstr "%s jums siunčia %s"
|
||||
|
||||
#. To translators: The parameter is the contact's alias
|
||||
#: ../js/ui/components/telepathyClient.js:1206
|
||||
#: ../js/ui/components/telepathyClient.js:1207
|
||||
#, c-format
|
||||
msgid "%s would like permission to see when you are online"
|
||||
msgstr "%s pageidauja matyti, kai esate prisijungę prie interneto"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1298
|
||||
#: ../js/ui/components/telepathyClient.js:1299
|
||||
msgid "Network error"
|
||||
msgstr "Tinklo klaida"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1300
|
||||
#: ../js/ui/components/telepathyClient.js:1301
|
||||
msgid "Authentication failed"
|
||||
msgstr "Nepavyko patvirtinti tapatybės"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1302
|
||||
#: ../js/ui/components/telepathyClient.js:1303
|
||||
msgid "Encryption error"
|
||||
msgstr "Šifravimo klaida"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1304
|
||||
#: ../js/ui/components/telepathyClient.js:1305
|
||||
msgid "Certificate not provided"
|
||||
msgstr "Liudijimas nepateiktas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1306
|
||||
#: ../js/ui/components/telepathyClient.js:1307
|
||||
msgid "Certificate untrusted"
|
||||
msgstr "Liudijimas nepatikimas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1308
|
||||
#: ../js/ui/components/telepathyClient.js:1309
|
||||
msgid "Certificate expired"
|
||||
msgstr "Liudijimo galiojimas pasibaigęs"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1310
|
||||
#: ../js/ui/components/telepathyClient.js:1311
|
||||
msgid "Certificate not activated"
|
||||
msgstr "Liudijimas neaktyvuotas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1312
|
||||
#: ../js/ui/components/telepathyClient.js:1313
|
||||
msgid "Certificate hostname mismatch"
|
||||
msgstr "Liudijimo serverio vardo nesutapimas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1314
|
||||
#: ../js/ui/components/telepathyClient.js:1315
|
||||
msgid "Certificate fingerprint mismatch"
|
||||
msgstr "Liudijimo piršto atspaudo nesutapimas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1316
|
||||
#: ../js/ui/components/telepathyClient.js:1317
|
||||
msgid "Certificate self-signed"
|
||||
msgstr "Liudijimas pačių pasirašytas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1318
|
||||
#: ../js/ui/components/telepathyClient.js:1319
|
||||
msgid "Status is set to offline"
|
||||
msgstr "Nustatyta atsijungimo būsena"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1320
|
||||
#: ../js/ui/components/telepathyClient.js:1321
|
||||
msgid "Encryption is not available"
|
||||
msgstr "Šifravimas negalimas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1322
|
||||
#: ../js/ui/components/telepathyClient.js:1323
|
||||
msgid "Certificate is invalid"
|
||||
msgstr "Liudijimas netinkamas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1324
|
||||
#: ../js/ui/components/telepathyClient.js:1325
|
||||
msgid "Connection has been refused"
|
||||
msgstr "Ryšys atmestas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1326
|
||||
#: ../js/ui/components/telepathyClient.js:1327
|
||||
msgid "Connection can't be established"
|
||||
msgstr "Nepavyko užmegzti ryšio"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1328
|
||||
#: ../js/ui/components/telepathyClient.js:1329
|
||||
msgid "Connection has been lost"
|
||||
msgstr "Ryšys nutrūko"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1330
|
||||
#: ../js/ui/components/telepathyClient.js:1331
|
||||
msgid "This account is already connected to the server"
|
||||
msgstr "Ši paskyra jau prijungta prie serverio"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1332
|
||||
#: ../js/ui/components/telepathyClient.js:1333
|
||||
msgid ""
|
||||
"Connection has been replaced by a new connection using the same resource"
|
||||
msgstr "Ryšys pakeistas nauju ryšiu naudojant tą patį išteklių"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1334
|
||||
#: ../js/ui/components/telepathyClient.js:1335
|
||||
msgid "The account already exists on the server"
|
||||
msgstr "Tokia paskyra serveryje jau yra"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1336
|
||||
#: ../js/ui/components/telepathyClient.js:1337
|
||||
msgid "Server is currently too busy to handle the connection"
|
||||
msgstr "Šiuo metu serveris per daug užimtas šiai užklausai apdoroti"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1338
|
||||
#: ../js/ui/components/telepathyClient.js:1339
|
||||
msgid "Certificate has been revoked"
|
||||
msgstr "Liudijimas atšauktas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
#: ../js/ui/components/telepathyClient.js:1341
|
||||
msgid ""
|
||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr ""
|
||||
"Liudijimui naudojamas nesaugus šifravimo algoritmas arba jis kriptografiškai "
|
||||
"silpnas"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1342
|
||||
#: ../js/ui/components/telepathyClient.js:1343
|
||||
msgid ""
|
||||
"The length of the server certificate, or the depth of the server certificate "
|
||||
"chain, exceed the limits imposed by the cryptography library"
|
||||
@@ -997,22 +999,22 @@ msgstr ""
|
||||
"Serverio liudijimo ilgis arba liudijimų eilės dydis viršija kriptografijos "
|
||||
"bibliotekos apribojimus"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1344
|
||||
#: ../js/ui/components/telepathyClient.js:1345
|
||||
msgid "Internal error"
|
||||
msgstr "Vidinė klaida"
|
||||
|
||||
#. translators: argument is the account name, like
|
||||
#. * name@jabber.org for example.
|
||||
#: ../js/ui/components/telepathyClient.js:1354
|
||||
#: ../js/ui/components/telepathyClient.js:1355
|
||||
#, c-format
|
||||
msgid "Unable to connect to %s"
|
||||
msgstr "Nepavyksta prisijungti prie %s"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1359
|
||||
#: ../js/ui/components/telepathyClient.js:1360
|
||||
msgid "View account"
|
||||
msgstr "Rodyti paskyrą"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1398
|
||||
#: ../js/ui/components/telepathyClient.js:1399
|
||||
msgid "Unknown reason"
|
||||
msgstr "Nežinoma priežastis"
|
||||
|
||||
@@ -1026,7 +1028,7 @@ msgstr "Paleisti programas"
|
||||
|
||||
#. Translators: this is the name of the dock/favorites area on
|
||||
#. the left of the overview
|
||||
#: ../js/ui/dash.js:435
|
||||
#: ../js/ui/dash.js:445
|
||||
msgid "Dash"
|
||||
msgstr "Paleidimo sritis"
|
||||
|
||||
@@ -1038,14 +1040,14 @@ msgstr "Atverti kalendorių"
|
||||
msgid "Open Clocks"
|
||||
msgstr "Atverti laikrodžius"
|
||||
|
||||
#: ../js/ui/dateMenu.js:105
|
||||
#: ../js/ui/dateMenu.js:104
|
||||
msgid "Date & Time Settings"
|
||||
msgstr "Datos ir laiko nustatymai"
|
||||
|
||||
#. 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:215
|
||||
#: ../js/ui/dateMenu.js:216
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%A, %Y m. %B %d d."
|
||||
|
||||
@@ -1156,7 +1158,7 @@ msgstr "Įdiegti"
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "Atsiųsti ir įdiegti „%s“ iš extensions.gnome.org?"
|
||||
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333
|
||||
#: ../js/ui/status/power.js:211
|
||||
msgid "Keyboard"
|
||||
msgstr "Klaviatūra"
|
||||
@@ -1183,7 +1185,9 @@ msgstr "Rodyti klaidas"
|
||||
msgid "Enabled"
|
||||
msgstr "Įjungta"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:769
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1830
|
||||
msgid "Disabled"
|
||||
msgstr "Išjungta"
|
||||
|
||||
@@ -1223,19 +1227,19 @@ msgstr "Išvalyti pranešimus"
|
||||
msgid "Notification Settings"
|
||||
msgstr "Pranešimų nustatymai"
|
||||
|
||||
#: ../js/ui/messageTray.js:1709
|
||||
#: ../js/ui/messageTray.js:1707
|
||||
msgid "No Messages"
|
||||
msgstr "Nėra pranešimų"
|
||||
|
||||
#: ../js/ui/messageTray.js:1782
|
||||
#: ../js/ui/messageTray.js:1783
|
||||
msgid "Message Tray"
|
||||
msgstr "Pranešimų juosta"
|
||||
|
||||
#: ../js/ui/messageTray.js:2810
|
||||
#: ../js/ui/messageTray.js:2822
|
||||
msgid "System Information"
|
||||
msgstr "Sistemos informacija"
|
||||
|
||||
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374
|
||||
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:392
|
||||
msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "Nežinoma"
|
||||
@@ -1264,17 +1268,17 @@ msgstr "Apžvalga"
|
||||
msgid "Type to search…"
|
||||
msgstr "Rašykite, ko ieškote…"
|
||||
|
||||
#: ../js/ui/panel.js:612
|
||||
#: ../js/ui/panel.js:636
|
||||
msgid "Quit"
|
||||
msgstr "Užverti"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:636
|
||||
#: ../js/ui/panel.js:687
|
||||
msgid "Activities"
|
||||
msgstr "Apžvalga"
|
||||
|
||||
#: ../js/ui/panel.js:933
|
||||
#: ../js/ui/panel.js:983
|
||||
msgid "Top Bar"
|
||||
msgstr "Viršutinė juosta"
|
||||
|
||||
@@ -1283,15 +1287,15 @@ msgstr "Viršutinė juosta"
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:727
|
||||
#: ../js/ui/popupMenu.js:740
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:73
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Enter a Command"
|
||||
msgstr "Įveskite komandą"
|
||||
|
||||
#: ../js/ui/runDialog.js:109
|
||||
#: ../js/ui/runDialog.js:110
|
||||
msgid "Close"
|
||||
msgstr "Užverti"
|
||||
|
||||
@@ -1313,7 +1317,7 @@ msgstr[2] "%d naujų pranešimų"
|
||||
msgid "Lock"
|
||||
msgstr "Užrakinti"
|
||||
|
||||
#: ../js/ui/screenShield.js:637
|
||||
#: ../js/ui/screenShield.js:642
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME aplinkai reikia užrakinti ekraną"
|
||||
|
||||
@@ -1324,11 +1328,11 @@ msgstr "GNOME aplinkai reikia užrakinti ekraną"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1194
|
||||
#: ../js/ui/screenShield.js:765 ../js/ui/screenShield.js:1201
|
||||
msgid "Unable to lock"
|
||||
msgstr "Nepavyksta užrakinti"
|
||||
|
||||
#: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1195
|
||||
#: ../js/ui/screenShield.js:766 ../js/ui/screenShield.js:1202
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "Programa užblokavo užrakinimą"
|
||||
|
||||
@@ -1340,19 +1344,19 @@ msgstr "Ieškoma…"
|
||||
msgid "No results."
|
||||
msgstr "Nerasta atitikmenų."
|
||||
|
||||
#: ../js/ui/shellEntry.js:29
|
||||
#: ../js/ui/shellEntry.js:27
|
||||
msgid "Copy"
|
||||
msgstr "Kopijuoti"
|
||||
|
||||
#: ../js/ui/shellEntry.js:34
|
||||
#: ../js/ui/shellEntry.js:32
|
||||
msgid "Paste"
|
||||
msgstr "Įdėti"
|
||||
|
||||
#: ../js/ui/shellEntry.js:106
|
||||
#: ../js/ui/shellEntry.js:99
|
||||
msgid "Show Text"
|
||||
msgstr "Rodyti tekstą"
|
||||
|
||||
#: ../js/ui/shellEntry.js:108
|
||||
#: ../js/ui/shellEntry.js:101
|
||||
msgid "Hide Text"
|
||||
msgstr "Slėpti tekstą"
|
||||
|
||||
@@ -1364,7 +1368,7 @@ msgstr "Slaptažodis"
|
||||
msgid "Remember Password"
|
||||
msgstr "Atsiminti slaptažodį"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
|
||||
msgid "Unlock"
|
||||
msgstr "Atrakinti"
|
||||
|
||||
@@ -1533,11 +1537,12 @@ msgstr "Įveskite PIN, nurodytą įrenginyje."
|
||||
msgid "OK"
|
||||
msgstr "Gerai"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:368
|
||||
#: ../js/ui/status/keyboard.js:396
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "Rodyti klaviatūros išdėstymą"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:373
|
||||
#: ../js/ui/status/keyboard.js:401
|
||||
#| msgid "Date & Time Settings"
|
||||
msgid "Region & Language Settings"
|
||||
msgstr "Regiono ir kalbos nustatymai"
|
||||
|
||||
@@ -1655,7 +1660,7 @@ msgstr "Nepavyko prisijungti"
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Tinklo ryšio nepavyko aktyvuoti"
|
||||
|
||||
#: ../js/ui/status/network.js:2276
|
||||
#: ../js/ui/status/network.js:2282
|
||||
msgid "Networking is disabled"
|
||||
msgstr "Tinklas išjungtas"
|
||||
|
||||
@@ -1773,11 +1778,11 @@ msgstr "Garsumas"
|
||||
msgid "Microphone"
|
||||
msgstr "Mikrofonas"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:124
|
||||
#: ../js/ui/unlockDialog.js:120
|
||||
msgid "Log in as another user"
|
||||
msgstr "Prisijungti kitu naudotoju"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:145
|
||||
#: ../js/ui/unlockDialog.js:141
|
||||
msgid "Unlock Window"
|
||||
msgstr "Atrakinimo langas"
|
||||
|
||||
@@ -1885,32 +1890,56 @@ msgstr "„%s“ yra pasirengusi"
|
||||
msgid "Evolution Calendar"
|
||||
msgstr "Evolution kalendorius"
|
||||
|
||||
#: ../src/main.c:347
|
||||
#. translators:
|
||||
#. * The number of sound outputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1837
|
||||
#, c-format
|
||||
msgid "%u Output"
|
||||
msgid_plural "%u Outputs"
|
||||
msgstr[0] "%u išvestis"
|
||||
msgstr[1] "%u išvestys"
|
||||
msgstr[2] "%u išvesčių"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound inputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1847
|
||||
#, c-format
|
||||
msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] "%u įvestis"
|
||||
msgstr[1] "%u įvestys"
|
||||
msgstr[2] "%u įvesčių"
|
||||
|
||||
#: ../src/gvc/gvc-mixer-control.c:2373
|
||||
msgid "System Sounds"
|
||||
msgstr "Sistemos garsai"
|
||||
|
||||
#: ../src/main.c:328
|
||||
msgid "Print version"
|
||||
msgstr "Išvesti versijos numerį"
|
||||
|
||||
#: ../src/main.c:353
|
||||
#: ../src/main.c:334
|
||||
msgid "Mode used by GDM for login screen"
|
||||
msgstr "Veiksena, naudojama GDM prisijungimo ekrane"
|
||||
|
||||
#: ../src/main.c:359
|
||||
#: ../src/main.c:340
|
||||
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
|
||||
msgstr "Naudoti konkrečią veikseną, pvz., „gdm“ prisijungimo ekranui"
|
||||
|
||||
#: ../src/main.c:365
|
||||
#: ../src/main.c:346
|
||||
msgid "List possible modes"
|
||||
msgstr "Išvardinti galimas veiksenas"
|
||||
|
||||
#: ../src/shell-app.c:622
|
||||
#: ../src/shell-app.c:640
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "Nepavyko paleisti „%s“"
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:708
|
||||
#: ../src/shell-keyring-prompt.c:714
|
||||
msgid "Passwords do not match."
|
||||
msgstr "Slaptažodžiai nesutampa."
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:716
|
||||
#: ../src/shell-keyring-prompt.c:722
|
||||
msgid "Password cannot be blank"
|
||||
msgstr "Slaptažodis negali būti tuščias"
|
||||
|
||||
@@ -1918,17 +1947,17 @@ msgstr "Slaptažodis negali būti tuščias"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Naudotojas užvėrė tapatybės patvirtinimo dialogą"
|
||||
|
||||
#~ msgid "%u Output"
|
||||
#~ msgid_plural "%u Outputs"
|
||||
#~ msgstr[0] "%u išvestis"
|
||||
#~ msgstr[1] "%u išvestys"
|
||||
#~ msgstr[2] "%u išvesčių"
|
||||
#~ msgctxt "event list time"
|
||||
#~ msgid "%H∶%M"
|
||||
#~ msgstr "%H∶%M"
|
||||
|
||||
#~ msgid "%u Input"
|
||||
#~ msgid_plural "%u Inputs"
|
||||
#~ msgstr[0] "%u įvestis"
|
||||
#~ msgstr[1] "%u įvestys"
|
||||
#~ msgstr[2] "%u įvesčių"
|
||||
#~ msgctxt "event list time"
|
||||
#~ msgid "%l∶%M %p"
|
||||
#~ msgstr "%l∶%M"
|
||||
|
||||
#~ msgid "System Sounds"
|
||||
#~ msgstr "Sistemos garsai"
|
||||
#~ msgid "calendar:MY"
|
||||
#~ msgstr "calendar:YM"
|
||||
|
||||
#~| msgid "Network error"
|
||||
#~ msgid "Network"
|
||||
#~ msgstr "Tinklas"
|
||||
|
320
po/ml.po
320
po/ml.po
@@ -10,9 +10,9 @@ 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: 2013-04-24 18:23+0000\n"
|
||||
"PO-Revision-Date: 2013-04-25 00:32+0530\n"
|
||||
"Last-Translator: Balasankar C <c.balasankar@gmail.com>\n"
|
||||
"POT-Creation-Date: 2013-03-23 11:49+0000\n"
|
||||
"PO-Revision-Date: 2013-03-25 14:57+0530\n"
|
||||
"Last-Translator: Ani Peter <peter.ani@gmail.com>\n"
|
||||
"Language-Team: American English <kde-i18n-doc@kde.org>\n"
|
||||
"Language: ml\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -44,14 +44,10 @@ msgid "Focus the active notification"
|
||||
msgstr "സജീവമായ അറിയിപ്പിനെ കേന്ദ്രീകരിക്കുക"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:4
|
||||
msgid "Show the overview"
|
||||
msgstr "പൊതുവായ അവലോകനം കാണിക്കുക"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:5
|
||||
msgid "Show all applications"
|
||||
msgstr "എല്ലാ പ്രയോഗങ്ങളും കാണിയ്ക്കുക"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:6
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:5
|
||||
msgid "Open the application menu"
|
||||
msgstr "പ്രയോഗത്തിന്റെ മെനു തുറക്കുക"
|
||||
|
||||
@@ -75,7 +71,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
|
||||
@@ -83,7 +80,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
|
||||
@@ -97,14 +95,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 ""
|
||||
@@ -113,9 +116,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
|
||||
@@ -126,7 +132,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 "List of categories that should be displayed as folders"
|
||||
@@ -137,8 +144,8 @@ msgid ""
|
||||
"Each category name in this list will be represented as folder in the "
|
||||
"application view, rather than being displayed inline in the main view."
|
||||
msgstr ""
|
||||
"ഈ പട്ടികയിലുള്ള ഓരോ വിഭാഗത്തിന്റെ പേരും, പ്രധാന കാഴ്ചയില് ഓരോ വരിയായി കാണിയ്ക്കുന്നതിനു് "
|
||||
"പകരം പ്രയോഗങ്ങളുടെ കാഴ്ചയില് ഫോള്ഡറായി കാണിയ്ക്കുന്നു. "
|
||||
"ഈ പട്ടികയിലുള്ള ഓരോ വിഭാഗത്തിന്റെ പേരും, പ്രധാന കാഴ്ചയില് ഓരോ വരിയായി "
|
||||
"കാണിയ്ക്കുന്നതിനു് പകരം പ്രയോഗങ്ങളുടെ കാഴ്ചയില് ഫോള്ഡറായി കാണിയ്ക്കുന്നു. "
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:11
|
||||
msgid "History for command (Alt-F2) dialog"
|
||||
@@ -153,7 +160,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:14
|
||||
@@ -161,7 +169,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:15
|
||||
@@ -173,13 +182,15 @@ 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:17
|
||||
msgid ""
|
||||
"Whether to remember password for mounting encrypted or remote filesystems"
|
||||
msgstr ""
|
||||
"എന്ക്രിപ്റ്റ് ചെയ്തതോ വിദൂരമോ ആയ ഫയല്സിസ്റ്റങ്ങള് മൌണ്ട് ചെയ്യുമ്പോഴുള്ള രഹസ്യവാക്ക് ഓര്മ്മിക്കണോ എന്ന്"
|
||||
"എന്ക്രിപ്റ്റ് ചെയ്തതോ വിദൂരമോ ആയ ഫയല്സിസ്റ്റങ്ങള് മൌണ്ട് ചെയ്യുമ്പോഴുള്ള "
|
||||
"രഹസ്യവാക്ക് ഓര്മ്മിക്കണോ എന്ന്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
|
||||
msgid ""
|
||||
@@ -188,9 +199,10 @@ msgid ""
|
||||
"'Remember Password' checkbox will be present. This key sets the default "
|
||||
"state of the checkbox."
|
||||
msgstr ""
|
||||
"ഒരു എന്ക്രിപ്റ്റ് ചെയ്ത ഡിവൈസ് അല്ലെങ്കില് വിദൂര ഫയല്സിസ്റ്റം മൌണ്ട് ചെയ്യുമ്പോള് ഷെല് ഒരു രഹസ്യവാക്ക് "
|
||||
"ആവശ്യപ്പെടുന്നു. രഹസ്യവാക്ക് സൂക്ഷിയ്ക്കുവാന് സാധ്യമെങ്കില്, 'രഹസ്യവാക്ക് ഓര്ത്തു്വയ്ക്കുക' ചെക്ക്ബോക്സ് "
|
||||
"കാണാം. ഈ കീ ചെക്ക്ബോക്സിന്റെ സ്വതവേയുള്ള അവസ്ഥ സജ്ജമാക്കുന്നു."
|
||||
"ഒരു എന്ക്രിപ്റ്റ് ചെയ്ത ഡിവൈസ് അല്ലെങ്കില് വിദൂര ഫയല്സിസ്റ്റം മൌണ്ട് "
|
||||
"ചെയ്യുമ്പോള് ഷെല് ഒരു രഹസ്യവാക്ക് ആവശ്യപ്പെടുന്നു. രഹസ്യവാക്ക് "
|
||||
"സൂക്ഷിയ്ക്കുവാന് സാധ്യമെങ്കില്, 'രഹസ്യവാക്ക് ഓര്ത്തു്വയ്ക്കുക' "
|
||||
"ചെക്ക്ബോക്സ് കാണാം. ഈ കീ ചെക്ക്ബോക്സിന്റെ സ്വതവേയുള്ള അവസ്ഥ സജ്ജമാക്കുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
|
||||
msgid "Show the week date in the calendar"
|
||||
@@ -216,65 +228,61 @@ msgstr "\"പ്രയോഗങ്ങള് കാണിയ്ക്കുക
|
||||
msgid ""
|
||||
"Keybinding to open the \"Show Applications\" view of the Activities Overview."
|
||||
msgstr ""
|
||||
"പ്രവര്ത്തികളുടെ അവലോകനത്തിന്റെ \"പ്രയോഗങ്ങള് കാണിയ്ക്കുക\" എന്ന കാഴ്ച തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്"
|
||||
"പ്രവര്ത്തികളുടെ അവലോകനത്തിന്റെ \"പ്രയോഗങ്ങള് കാണിയ്ക്കുക\" എന്ന കാഴ്ച "
|
||||
"തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
|
||||
msgid "Keybinding to open the overview"
|
||||
msgstr "പൊതുവായ അവലോകനം തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
|
||||
msgid "Keybinding to open the Activities Overview."
|
||||
msgstr "പ്രയോഗങ്ങളുടെ പൊതുവായ അവലോകനം എന്ന കാഴ്ച തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
msgid "Keybinding to toggle the visibility of the message tray"
|
||||
msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള് ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
|
||||
msgid "Keybinding to toggle the visibility of the message tray."
|
||||
msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള് ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
|
||||
msgid "Keybinding to focus the active notification"
|
||||
msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്ഡിങ്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
|
||||
msgid "Keybinding to focus the active notification."
|
||||
msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്ഡിങ്."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
|
||||
msgid "Keybinding to toggle the screen recorder"
|
||||
msgstr "സ്ക്രീന് റിക്കോര്ഡര് ടൊഗ്ഗിള് ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
|
||||
msgid "Keybinding to start/stop the builtin screen recorder."
|
||||
msgstr "ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള കീക്കൂട്ടം."
|
||||
msgstr ""
|
||||
"ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള "
|
||||
"കീക്കൂട്ടം."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
msgid "Which keyboard to use"
|
||||
msgstr "ഏതു് കീബോര്ഡ് ഉപയോഗിയ്ക്കണം"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
|
||||
msgid "The type of keyboard to use."
|
||||
msgstr "ഏതു് തരം കീബോര്ഡ് ഉപയോഗിയ്ക്കണം."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
|
||||
msgid "Framerate used for recording screencasts."
|
||||
msgstr "സ്ക്രീന്കാസ്റ്റുകള് റിക്കോര്ഡ് ചെയ്യുന്നതിനുള്ള ഫ്രെയിം റേറ്റ്."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
|
||||
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:37
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "സ്ക്രീന്കാസ്റ്റ് എന്കോഡ് ചെയ്യുന്നതിനുള്ള gstreamer പൈപ്പ്ലൈന്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
@@ -288,68 +296,78 @@ 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 "
|
||||
"റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് "
|
||||
"ഉപയോഗിയ്ക്കുന്നു. gst-launch-"
|
||||
"നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് "
|
||||
"കാലിയാകുന്നു.ഇതു് നിലവില് 'vp8enc "
|
||||
"min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! "
|
||||
"queue ! webmmux' ആകുന്നുസ WEBM VP8 കോഡ് ഉപയോഗിച്ചു് റിക്കോര്ഡ് ചെയ്യുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
|
||||
msgid "File extension used for storing the screencast"
|
||||
msgstr "സ്ക്രീന്കാസ്റ്റ് സൂക്ഷിയ്ക്കുന്നതിനുള്ള ഫയല് എക്സ്റ്റെന്ഷന്"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39
|
||||
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 ""
|
||||
"റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, എക്സ്റ്റെന്ഷന് എന്നിവ "
|
||||
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് മാറ്റണം."
|
||||
"റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, "
|
||||
"എക്സ്റ്റെന്ഷന് എന്നിവ "
|
||||
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് "
|
||||
"മാറ്റണം."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
|
||||
msgid "The application icon mode."
|
||||
msgstr "പ്രയോഗത്തിന്റെ ഐക്കണ് മോഡ്."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
|
||||
msgid ""
|
||||
"Configures how the windows are shown in the switcher. Valid possibilities "
|
||||
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
|
||||
"only' (shows only the application icon) or 'both'."
|
||||
msgstr ""
|
||||
"സ്വിച്ചറില് ജാലകങ്ങള് എങ്ങനെ കാണിയ്ക്കുന്നു എന്നു് ക്രമീകരിയ്ക്കുന്നു. ശരിയായ സാധ്യതകള്: "
|
||||
"'thumbnail-only' (ജാലകത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു), 'app-icon-"
|
||||
"സ്വിച്ചറില് ജാലകങ്ങള് എങ്ങനെ കാണിയ്ക്കുന്നു എന്നു് ക്രമീകരിയ്ക്കുന്നു. "
|
||||
"ശരിയായ "
|
||||
"സാധ്യതകള്: 'thumbnail-only' (ജാലകത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു), "
|
||||
"'app-icon-"
|
||||
"only' (പ്രയോഗത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു) അല്ലെങ്കില് 'both'."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:44
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
|
||||
msgid "Attach modal dialog to the parent window"
|
||||
msgstr "പേരന്റ് ജാലകത്തിലേക്കു് ഡയലോഗ് ചേര്ക്കുക"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:45
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43
|
||||
msgid ""
|
||||
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
|
||||
msgstr "ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.mutter-ലുള്ള കീ ഈ കീ തിരുത്തിയെഴുതുന്നു."
|
||||
msgstr ""
|
||||
"ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.mutter-ലുള്ള കീ ഈ കീ "
|
||||
"തിരുത്തിയെഴുതുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:46
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:44
|
||||
msgid "Arrangement of buttons on the titlebar"
|
||||
msgstr "തലക്കെട്ടിനുള്ള ബാറില് ബട്ടണുകളുടെ ക്രമീകരണം"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:47
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:45
|
||||
msgid ""
|
||||
"This key overrides the key in org.gnome.desktop.wm.preferences when running "
|
||||
"GNOME Shell."
|
||||
msgstr ""
|
||||
"ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.desktop.wm.preferences-ലുള്ള കീ ഈ കീ "
|
||||
"തിരുത്തിയെഴുതുന്നു."
|
||||
"ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.desktop.wm.preferences-ലുള്ള "
|
||||
"കീ ഈ കീ തിരുത്തിയെഴുതുന്നു."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:48
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:46
|
||||
msgid "Enable edge tiling when dropping windows on screen edges"
|
||||
msgstr "സ്ക്രീന് കോണുകളില് ജാലകങ്ങള് എത്തിയ്ക്കുമ്പോള് കോണ് ചരിയ്ക്കുന്നതിനായി പ്രവര്ത്തന സജ്ജമാക്കുക"
|
||||
msgstr ""
|
||||
"സ്ക്രീന് കോണുകളില് ജാലകങ്ങള് എത്തിയ്ക്കുമ്പോള് കോണ് ചരിയ്ക്കുന്നതിനായി "
|
||||
"പ്രവര്ത്തന സജ്ജമാക്കുക"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:49
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:47
|
||||
msgid "Workspaces are managed dynamically"
|
||||
msgstr "പണിയിടങ്ങള് ഡയനാമിക്കായി കൈകാര്യം ചെയ്തിരിക്കുന്നു"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:50
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:48
|
||||
msgid "Workspaces only on primary monitor"
|
||||
msgstr "പ്രധാന മോണിറ്ററില് മാത്രം പണിയിടങ്ങള്"
|
||||
|
||||
@@ -364,9 +382,12 @@ msgstr "എക്സ്റ്റെന്ഷന്"
|
||||
|
||||
#: ../js/extensionPrefs/main.js:189
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക."
|
||||
msgstr ""
|
||||
"മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു "
|
||||
"എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:405
|
||||
#| msgid "Session..."
|
||||
msgid "Session…"
|
||||
msgstr "പ്രവര്ത്തനവേള..."
|
||||
|
||||
@@ -377,32 +398,32 @@ msgstr "പ്രവര്ത്തനവേള..."
|
||||
msgid "Not listed?"
|
||||
msgstr "ലഭ്യമല്ലേ?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:787 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376
|
||||
#: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:100
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99
|
||||
#: ../js/ui/userMenu.js:938
|
||||
msgid "Cancel"
|
||||
msgstr "വേണ്ട"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:803
|
||||
#: ../js/gdm/loginDialog.js:802
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "അകത്തുകയറുക"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:803
|
||||
#: ../js/gdm/loginDialog.js:802
|
||||
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:918 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/gdm/loginDialog.js:917 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "ഉപയോക്തൃ നാമം: "
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1174
|
||||
#: ../js/gdm/loginDialog.js:1173
|
||||
msgid "Login Window"
|
||||
msgstr "പ്രവേശന ജാലകം"
|
||||
|
||||
@@ -455,23 +476,23 @@ msgstr "ആജ്ഞ പ്രാവര്ത്തികമാക്കാ
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s' നടപ്പിലാക്കുന്നതില് പരാജയപ്പെട്ടു:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:351
|
||||
#: ../js/ui/appDisplay.js:349
|
||||
msgid "Frequent"
|
||||
msgstr "ഇടയ്ക്കിടെ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:358
|
||||
#: ../js/ui/appDisplay.js:356
|
||||
msgid "All"
|
||||
msgstr "എല്ലാം"
|
||||
|
||||
#: ../js/ui/appDisplay.js:916
|
||||
#: ../js/ui/appDisplay.js:914
|
||||
msgid "New Window"
|
||||
msgstr "പുതിയ വിന്ഡോ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:919 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "ഇഷ്ടപ്പെട്ടവയില് നിന്നും നീക്കം ചെയ്യുക"
|
||||
|
||||
#: ../js/ui/appDisplay.js:920
|
||||
#: ../js/ui/appDisplay.js:918
|
||||
msgid "Add to Favorites"
|
||||
msgstr "ഇഷ്ടപ്പെട്ടവയിലേക്ക് ചേര്ക്കുക"
|
||||
|
||||
@@ -508,7 +529,7 @@ msgctxt "event list time"
|
||||
msgid "%H\\u2236%M"
|
||||
msgstr "%H\\u2236%M"
|
||||
|
||||
#. Translators: Shown in calendar event list, if 12h format,
|
||||
#. Transators: Shown in calendar event list, if 12h format,
|
||||
#. \u2236 is a ratio character, similar to : and \u2009 is
|
||||
#. a thin space
|
||||
#: ../js/ui/calendar.js:77
|
||||
@@ -711,7 +732,8 @@ msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
"'%s'."
|
||||
msgstr ""
|
||||
"വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് "
|
||||
"വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് "
|
||||
"അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് "
|
||||
"ആവശ്യമുണ്ടു്."
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:314
|
||||
@@ -768,7 +790,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:47
|
||||
#: ../js/ui/components/recorder.js:48
|
||||
#, no-c-format
|
||||
msgid "Screencast from %d %t"
|
||||
msgstr "%d-ല് നിന്നുള്ള സ്ക്രീന്കാസ്റ്റ്, %t-ല്"
|
||||
@@ -891,7 +913,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"
|
||||
@@ -964,7 +987,9 @@ msgstr "ഈ അക്കൌണ്ട് നിലവില് സര്വ
|
||||
#: ../js/ui/components/telepathyClient.js:1332
|
||||
msgid ""
|
||||
"Connection has been replaced by a new connection using the same resource"
|
||||
msgstr "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
|
||||
msgstr ""
|
||||
"അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് "
|
||||
"മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
|
||||
|
||||
#: ../js/ui/components/telepathyClient.js:1334
|
||||
msgid "The account already exists on the server"
|
||||
@@ -981,14 +1006,17 @@ msgstr "സമ്മതപത്രം വീണ്ടും ആവശ്യപ
|
||||
#: ../js/ui/components/telepathyClient.js:1340
|
||||
msgid ""
|
||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
|
||||
msgstr "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു അല്ലെങ്കില് ഉചിതമല്ല"
|
||||
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
|
||||
@@ -1057,7 +1085,8 @@ msgstr "പുറത്ത് കടക്കുക"
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് ചെയ്തു് സിസ്റ്റത്തില് നിന്നും "
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് "
|
||||
"ചെയ്തു് സിസ്റ്റത്തില് നിന്നും "
|
||||
"പുറത്തു് കടക്കുക."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:67
|
||||
@@ -1091,7 +1120,8 @@ msgstr "നിര്ത്തുക"
|
||||
#: ../js/ui/endSessionDialog.js:84
|
||||
msgid "Click Power Off to quit these applications and power off the system."
|
||||
msgstr ""
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് ചെയ്തു സിസ്റ്റിന്റെ പവര് "
|
||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് "
|
||||
"ചെയ്തു സിസ്റ്റിന്റെ പവര് "
|
||||
"ഓഫ് ചെയ്യുക."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
@@ -1122,7 +1152,8 @@ msgstr "പുനരാരംഭിക്കുക"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:101
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr "ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക"
|
||||
msgstr ""
|
||||
"ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:103
|
||||
#, c-format
|
||||
@@ -1142,7 +1173,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:619 ../js/ui/status/keyboard.js:314
|
||||
#: ../js/ui/status/power.js:211
|
||||
@@ -1171,9 +1204,7 @@ msgstr "പിശകുകള് കാണിക്കുക"
|
||||
msgid "Enabled"
|
||||
msgstr "പ്രവര്ത്തനക്ഷമമാക്കി"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1830
|
||||
#: ../js/ui/lookingGlass.js:769
|
||||
msgid "Disabled"
|
||||
msgstr "പ്രവര്ത്തനരഹിതമാക്കി"
|
||||
|
||||
@@ -1206,6 +1237,7 @@ msgid "Remove"
|
||||
msgstr "നീക്കം ചെയ്യുക"
|
||||
|
||||
#: ../js/ui/messageTray.js:1501
|
||||
#| msgid "No Messages"
|
||||
msgid "Clear Messages"
|
||||
msgstr "സന്ദേശങ്ങള് വെടിപ്പാക്കുക"
|
||||
|
||||
@@ -1213,35 +1245,35 @@ msgstr "സന്ദേശങ്ങള് വെടിപ്പാക്ക
|
||||
msgid "Notification Settings"
|
||||
msgstr "അറിയിപ്പു് ക്രമീകരണങ്ങള്"
|
||||
|
||||
#: ../js/ui/messageTray.js:1710
|
||||
#: ../js/ui/messageTray.js:1709
|
||||
msgid "No Messages"
|
||||
msgstr "സന്ദേശങ്ങളില്ല"
|
||||
|
||||
#: ../js/ui/messageTray.js:1783
|
||||
#: ../js/ui/messageTray.js:1782
|
||||
msgid "Message Tray"
|
||||
msgstr "സന്ദേശത്തിന്റെ ട്രേ"
|
||||
|
||||
#: ../js/ui/messageTray.js:2801
|
||||
#: ../js/ui/messageTray.js:2810
|
||||
msgid "System Information"
|
||||
msgstr "സിസ്റ്റത്തെക്കുറിച്ചുള്ള വിവരം"
|
||||
|
||||
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:378
|
||||
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374
|
||||
msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "അജ്ഞാതം"
|
||||
|
||||
#: ../js/ui/overviewControls.js:472 ../js/ui/screenShield.js:149
|
||||
#: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
|
||||
#, c-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] "%d പുതിയ സന്ദേശം"
|
||||
msgstr[1] "%d പുതിയ സന്ദേശങ്ങള്"
|
||||
|
||||
#: ../js/ui/overview.js:82
|
||||
#: ../js/ui/overview.js:84
|
||||
msgid "Undo"
|
||||
msgstr "വേണ്ട"
|
||||
|
||||
#: ../js/ui/overview.js:127
|
||||
#: ../js/ui/overview.js:129
|
||||
msgid "Overview"
|
||||
msgstr "അവലോകനം"
|
||||
|
||||
@@ -1249,21 +1281,22 @@ msgstr "അവലോകനം"
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: ../js/ui/overview.js:260
|
||||
#: ../js/ui/overview.js:271
|
||||
#| msgid "Type to search..."
|
||||
msgid "Type to search…"
|
||||
msgstr "തെരയുന്നതിനായി ടൈപ്പ് ചെയ്യുക..."
|
||||
|
||||
#: ../js/ui/panel.js:641
|
||||
#: ../js/ui/panel.js:612
|
||||
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:692
|
||||
#: ../js/ui/panel.js:636
|
||||
msgid "Activities"
|
||||
msgstr "പ്രവര്ത്തനങ്ങള്"
|
||||
|
||||
#: ../js/ui/panel.js:989
|
||||
#: ../js/ui/panel.js:933
|
||||
msgid "Top Bar"
|
||||
msgstr "മുകളിലുള്ള ബാര്"
|
||||
|
||||
@@ -1272,15 +1305,15 @@ msgstr "മുകളിലുള്ള ബാര്"
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:718
|
||||
#: ../js/ui/popupMenu.js:727
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-us"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
#: ../js/ui/runDialog.js:73
|
||||
msgid "Enter a Command"
|
||||
msgstr "ഒരു കമാന്ഡ് നല്കുക"
|
||||
|
||||
#: ../js/ui/runDialog.js:110
|
||||
#: ../js/ui/runDialog.js:109
|
||||
msgid "Close"
|
||||
msgstr "അടക്കുക"
|
||||
|
||||
@@ -1301,7 +1334,7 @@ msgstr[1] "%d പുതിയ അറിയിപ്പുകള്"
|
||||
msgid "Lock"
|
||||
msgstr "പൂട്ടുക"
|
||||
|
||||
#: ../js/ui/screenShield.js:641
|
||||
#: ../js/ui/screenShield.js:637
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "ഗ്നോമിന് സ്ക്രീന് പൂട്ടണം"
|
||||
|
||||
@@ -1312,15 +1345,17 @@ msgstr "ഗ്നോമിന് സ്ക്രീന് പൂട്ടണ
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
|
||||
#: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1194
|
||||
#| msgid "Unable to connect to %s"
|
||||
msgid "Unable to lock"
|
||||
msgstr "പൂട്ടുവാന് സാധ്യമല്ല"
|
||||
|
||||
#: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199
|
||||
#: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1195
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "പൂട്ടുന്ന സംവിധാനം ഒരു പ്രയോഗം തടസ്സപ്പെടുത്തിയിരിയ്ക്കുന്നു"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:453
|
||||
#| msgid "Searching..."
|
||||
msgid "Searching…"
|
||||
msgstr "തെരയുന്നു..."
|
||||
|
||||
@@ -1336,11 +1371,11 @@ msgstr "പകര്ത്തുക"
|
||||
msgid "Paste"
|
||||
msgstr "ഒട്ടിയ്ക്കുക"
|
||||
|
||||
#: ../js/ui/shellEntry.js:101
|
||||
#: ../js/ui/shellEntry.js:106
|
||||
msgid "Show Text"
|
||||
msgstr "പദാവലി കാണിക്കുക"
|
||||
|
||||
#: ../js/ui/shellEntry.js:103
|
||||
#: ../js/ui/shellEntry.js:108
|
||||
msgid "Hide Text"
|
||||
msgstr "പദാവലി മറക്കുക"
|
||||
|
||||
@@ -1352,7 +1387,7 @@ msgstr "രഹസ്യവാക്ക്"
|
||||
msgid "Remember Password"
|
||||
msgstr "രഹസ്യവാക്ക് ഓര്ത്തു് വയ്ക്കുക"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:114
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113
|
||||
msgid "Unlock"
|
||||
msgstr "പൂട്ട് തുറക്കുക"
|
||||
|
||||
@@ -1416,10 +1451,12 @@ msgid "Visibility"
|
||||
msgstr "കാഴ്ച"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:59
|
||||
#| msgid "Send Files to Device..."
|
||||
msgid "Send Files to Device…"
|
||||
msgstr "ഡിവൈസിലേക്കു് ഫയലുകള് അയയ്ക്കുക..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:60
|
||||
#| msgid "Set Up a New Device..."
|
||||
msgid "Set Up a New Device…"
|
||||
msgstr "പുതിയൊരു ഡിവൈസ് സജ്ജമാക്കുക..."
|
||||
|
||||
@@ -1446,6 +1483,7 @@ msgid "connecting..."
|
||||
msgstr "ബന്ധിപ്പിയ്ക്കുന്നു...."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:239
|
||||
#| msgid "Send Files..."
|
||||
msgid "Send Files…"
|
||||
msgstr "ഫയലുകള് അയയ്ക്കുക..."
|
||||
|
||||
@@ -1658,6 +1696,7 @@ msgstr "ഊര്ജ്ജ ക്രമീകരണങ്ങള്"
|
||||
#. 0 is reported when UPower does not have enough data
|
||||
#. to estimate battery life
|
||||
#: ../js/ui/status/power.js:99
|
||||
#| msgid "Estimating..."
|
||||
msgid "Estimating…"
|
||||
msgstr "കണക്കുകൂട്ടുന്നു..."
|
||||
|
||||
@@ -1757,11 +1796,11 @@ msgstr "ഒച്ച"
|
||||
msgid "Microphone"
|
||||
msgstr "മൈക്രോഫോണ്"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:125
|
||||
#: ../js/ui/unlockDialog.js:124
|
||||
msgid "Log in as another user"
|
||||
msgstr "മറ്റൊരു ഉപയോക്താവായി പ്രവേശിയ്ക്കുക"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:146
|
||||
#: ../js/ui/unlockDialog.js:145
|
||||
msgid "Unlock Window"
|
||||
msgstr "ജാലകത്തിന്റെ പൂട്ടു തുറക്കുക"
|
||||
|
||||
@@ -1814,8 +1853,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/userMenu.js:888
|
||||
msgid "Other users are logged in."
|
||||
@@ -1868,28 +1909,6 @@ msgstr "'%s' തയ്യാറാണ്"
|
||||
msgid "Evolution Calendar"
|
||||
msgstr "ഇവല്യൂഷന് കലണ്ടര്"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound outputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1837
|
||||
#, c-format
|
||||
msgid "%u Output"
|
||||
msgid_plural "%u Outputs"
|
||||
msgstr[0] "%u ഔട്ട്പുട്ട്"
|
||||
msgstr[1] "%u ഔട്ട്പുട്ടുകള്"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound inputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1847
|
||||
#, c-format
|
||||
msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] "%u ഇന്പുട്ട്"
|
||||
msgstr[1] "%u ഇന്പുട്ടുകള്"
|
||||
|
||||
#: ../src/gvc/gvc-mixer-control.c:2371
|
||||
msgid "System Sounds"
|
||||
msgstr "സിസ്റ്റം ശബ്ദങ്ങള്"
|
||||
|
||||
#: ../src/main.c:347
|
||||
msgid "Print version"
|
||||
msgstr "പ്രിന്റ് ചെയ്യുവാന് സാധിയ്ക്കുന്ന പതിപ്പു്"
|
||||
@@ -1906,7 +1925,7 @@ msgstr "ഒരു പ്രത്യേക മോഡ് ഉപയോഗിയ്
|
||||
msgid "List possible modes"
|
||||
msgstr "സാധ്യമായ മോഡുകള് ലഭ്യമാക്കുക"
|
||||
|
||||
#: ../src/shell-app.c:626
|
||||
#: ../src/shell-app.c:622
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "'%s' ലഭ്യമാക്കുന്നതില് പരാജയം"
|
||||
@@ -1936,6 +1955,19 @@ msgstr "ഉപയോക്താവു് ആധികാരികത ഉറപ
|
||||
#~ msgid "More..."
|
||||
#~ msgstr "കൂടുതല്..."
|
||||
|
||||
#~ msgid "%u Output"
|
||||
#~ msgid_plural "%u Outputs"
|
||||
#~ msgstr[0] "%u ഔട്ട്പുട്ട്"
|
||||
#~ msgstr[1] "%u ഔട്ട്പുട്ടുകള്"
|
||||
|
||||
#~ msgid "%u Input"
|
||||
#~ msgid_plural "%u Inputs"
|
||||
#~ msgstr[0] "%u ഇന്പുട്ട്"
|
||||
#~ msgstr[1] "%u ഇന്പുട്ടുകള്"
|
||||
|
||||
#~ msgid "System Sounds"
|
||||
#~ msgstr "സിസ്റ്റം ശബ്ദങ്ങള്"
|
||||
|
||||
#~ msgctxt "event list time"
|
||||
#~ msgid "%H:%M"
|
||||
#~ msgstr "%H:%M"
|
||||
|
86
po/nb.po
86
po/nb.po
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell 3.8.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-03 13:31+0200\n"
|
||||
"POT-Creation-Date: 2013-05-13 09:47+0200\n"
|
||||
"PO-Revision-Date: 2013-04-03 13:31+0200\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
|
||||
@@ -335,43 +335,50 @@ msgstr "Utvidelse"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "Velg en utvidelse som skal konfigureres med komboboksen over."
|
||||
|
||||
#: ../js/gdm/loginDialog.js:405
|
||||
#: ../js/gdm/loginDialog.js:371
|
||||
msgid "Session…"
|
||||
msgstr "Økt …"
|
||||
|
||||
#. 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:630
|
||||
#: ../js/gdm/loginDialog.js:601
|
||||
msgid "Not listed?"
|
||||
msgstr "Ikke listet?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375
|
||||
#: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
|
||||
#: ../js/ui/userMenu.js:938
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:802
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "Logg inn"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:802
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgid "Next"
|
||||
msgstr "Neste"
|
||||
|
||||
#. Translators: this message is shown below the username entry field
|
||||
#. to clue the user in on how to login to the local network realm
|
||||
#: ../js/gdm/loginDialog.js:888
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(f.eks. bruker eller %s)"
|
||||
|
||||
#. 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:917 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "Brukernavn: "
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1173
|
||||
#: ../js/gdm/loginDialog.js:1158
|
||||
msgid "Login Window"
|
||||
msgstr "Innloggingsvindu"
|
||||
|
||||
@@ -394,21 +401,16 @@ msgstr "Start på nytt"
|
||||
msgid "Power Off"
|
||||
msgstr "Slå av"
|
||||
|
||||
#: ../js/gdm/util.js:249
|
||||
#: ../js/gdm/util.js:247
|
||||
msgid "Authentication error"
|
||||
msgstr "Autentiseringsfeil"
|
||||
|
||||
#. Translators: this message is shown below the password entry field
|
||||
#. to indicate the user can swipe their finger instead
|
||||
#: ../js/gdm/util.js:366
|
||||
#: ../js/gdm/util.js:364
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(eller dra finger)"
|
||||
|
||||
#: ../js/gdm/util.js:391
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(f.eks. bruker eller %s)"
|
||||
|
||||
#: ../js/misc/util.js:97
|
||||
msgid "Command not found"
|
||||
msgstr "Kommando ikke funnet"
|
||||
@@ -632,11 +634,11 @@ msgstr "Åpne med %s"
|
||||
msgid "Eject"
|
||||
msgstr "Løs ut"
|
||||
|
||||
#: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:275
|
||||
msgid "Password:"
|
||||
msgstr "Passord:"
|
||||
|
||||
#: ../js/ui/components/keyring.js:101
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
msgid "Type again:"
|
||||
msgstr "Skriv på nytt:"
|
||||
|
||||
@@ -724,7 +726,7 @@ msgstr "Autentisering kreves"
|
||||
msgid "Administrator"
|
||||
msgstr "Administrator"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:165
|
||||
#: ../js/ui/components/polkitAgent.js:171
|
||||
msgid "Authenticate"
|
||||
msgstr "Autentiser"
|
||||
|
||||
@@ -732,12 +734,12 @@ msgstr "Autentiser"
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
#: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383
|
||||
#: ../js/ui/components/polkitAgent.js:263 ../js/ui/shellMountOperation.js:383
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "Beklager, det virket ikke. Vennligst prøv igjen."
|
||||
|
||||
#. Translators: this is a filename used for screencast recording
|
||||
#: ../js/ui/components/recorder.js:48
|
||||
#: ../js/ui/components/recorder.js:47
|
||||
#, no-c-format
|
||||
msgid "Screencast from %d %t"
|
||||
msgstr "Skjermvideo fra %d %t"
|
||||
@@ -1003,14 +1005,14 @@ msgstr "Åpne kalender"
|
||||
msgid "Open Clocks"
|
||||
msgstr "Åpne Klokker"
|
||||
|
||||
#: ../js/ui/dateMenu.js:105
|
||||
#: ../js/ui/dateMenu.js:104
|
||||
msgid "Date & Time Settings"
|
||||
msgstr "Innstillinger for dato og klokkeslett"
|
||||
|
||||
#. 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:215
|
||||
#: ../js/ui/dateMenu.js:216
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%a %e %B, %Y"
|
||||
|
||||
@@ -1188,11 +1190,11 @@ msgstr "Innstillinger for varsling"
|
||||
msgid "No Messages"
|
||||
msgstr "Ingen meldinger"
|
||||
|
||||
#: ../js/ui/messageTray.js:1782
|
||||
#: ../js/ui/messageTray.js:1785
|
||||
msgid "Message Tray"
|
||||
msgstr "Meldingstrau"
|
||||
|
||||
#: ../js/ui/messageTray.js:2810
|
||||
#: ../js/ui/messageTray.js:2813
|
||||
msgid "System Information"
|
||||
msgstr "Systeminformasjon"
|
||||
|
||||
@@ -1224,17 +1226,17 @@ msgstr "Oversikt"
|
||||
msgid "Type to search…"
|
||||
msgstr "Skriv for å søke …"
|
||||
|
||||
#: ../js/ui/panel.js:612
|
||||
#: ../js/ui/panel.js:635
|
||||
msgid "Quit"
|
||||
msgstr "Avslutt"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:636
|
||||
#: ../js/ui/panel.js:686
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#: ../js/ui/panel.js:933
|
||||
#: ../js/ui/panel.js:982
|
||||
msgid "Top Bar"
|
||||
msgstr "Topp-panel"
|
||||
|
||||
@@ -1247,11 +1249,11 @@ msgstr "Topp-panel"
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:73
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Enter a Command"
|
||||
msgstr "Oppgi en kommando"
|
||||
|
||||
#: ../js/ui/runDialog.js:109
|
||||
#: ../js/ui/runDialog.js:110
|
||||
msgid "Close"
|
||||
msgstr "Lukk"
|
||||
|
||||
@@ -1272,7 +1274,7 @@ msgstr[1] "%d nye varslinger"
|
||||
msgid "Lock"
|
||||
msgstr "Lås"
|
||||
|
||||
#: ../js/ui/screenShield.js:640
|
||||
#: ../js/ui/screenShield.js:641
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME må låse skjermen"
|
||||
|
||||
@@ -1283,11 +1285,11 @@ msgstr "GNOME må låse skjermen"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:761 ../js/ui/screenShield.js:1197
|
||||
#: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
|
||||
msgid "Unable to lock"
|
||||
msgstr "Kan ikke låse"
|
||||
|
||||
#: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
|
||||
#: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "Låsing ble stoppet av et program"
|
||||
|
||||
@@ -1307,11 +1309,11 @@ msgstr "Kopier"
|
||||
msgid "Paste"
|
||||
msgstr "Lim inn"
|
||||
|
||||
#: ../js/ui/shellEntry.js:106
|
||||
#: ../js/ui/shellEntry.js:101
|
||||
msgid "Show Text"
|
||||
msgstr "Vis tekst"
|
||||
|
||||
#: ../js/ui/shellEntry.js:108
|
||||
#: ../js/ui/shellEntry.js:103
|
||||
msgid "Hide Text"
|
||||
msgstr "Skjul tekst"
|
||||
|
||||
@@ -1323,7 +1325,7 @@ msgstr "Passord"
|
||||
msgid "Remember Password"
|
||||
msgstr "Husk passord"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
|
||||
msgid "Unlock"
|
||||
msgstr "Lås opp"
|
||||
|
||||
@@ -1614,7 +1616,7 @@ msgstr "Tilkobling feilet"
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Aktivering av nettverkstilkobling feilet"
|
||||
|
||||
#: ../js/ui/status/network.js:2276
|
||||
#: ../js/ui/status/network.js:2282
|
||||
msgid "Networking is disabled"
|
||||
msgstr "Nettverk er slått av"
|
||||
|
||||
@@ -1728,11 +1730,11 @@ msgstr "Volum"
|
||||
msgid "Microphone"
|
||||
msgstr "Mikrofon"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:124
|
||||
#: ../js/ui/unlockDialog.js:120
|
||||
msgid "Log in as another user"
|
||||
msgstr "Logg inn som en annen bruker"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:145
|
||||
#: ../js/ui/unlockDialog.js:141
|
||||
msgid "Unlock Window"
|
||||
msgstr "Lås opp vindu"
|
||||
|
||||
@@ -1885,11 +1887,11 @@ msgstr "Vis mulige modi"
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "Klarte ikke å starte «%s»"
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:708
|
||||
#: ../src/shell-keyring-prompt.c:714
|
||||
msgid "Passwords do not match."
|
||||
msgstr "Passordene er ikke like."
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:716
|
||||
#: ../src/shell-keyring-prompt.c:722
|
||||
msgid "Password cannot be blank"
|
||||
msgstr "Passordet kan ikke være tomt"
|
||||
|
||||
|
569
po/pt_BR.po
569
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
522
po/sr@latin.po
522
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
1027
po/zh_CN.po
1027
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
214
po/zh_HK.po
214
po/zh_HK.po
@@ -9,15 +9,16 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell 3.3.90\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-03-04 08:38+0000\n"
|
||||
"PO-Revision-Date: 2013-03-06 19:06+0800\n"
|
||||
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
|
||||
"POT-Creation-Date: 2013-05-31 18:55+0000\n"
|
||||
"PO-Revision-Date: 2013-06-04 21:50+0800\n"
|
||||
"Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n"
|
||||
"Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Poedit 1.5.3\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
|
||||
msgid "Screenshots"
|
||||
@@ -313,44 +314,50 @@ msgstr "擴充功能"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "使用上面的組合方塊選擇要設定的擴充功能。"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:405
|
||||
#| msgid "Session..."
|
||||
#: ../js/gdm/loginDialog.js:371
|
||||
msgid "Session…"
|
||||
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:629
|
||||
#: ../js/gdm/loginDialog.js:601
|
||||
msgid "Not listed?"
|
||||
msgstr "沒有列出來?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375
|
||||
#: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126
|
||||
#: ../js/ui/userMenu.js:934
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
|
||||
#: ../js/ui/userMenu.js:938
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:799
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "登入"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:799
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgid "Next"
|
||||
msgstr "下一個"
|
||||
|
||||
#. Translators: this message is shown below the username entry field
|
||||
#. to clue the user in on how to login to the local network realm
|
||||
#: ../js/gdm/loginDialog.js:888
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(例如: user 或 %s)"
|
||||
|
||||
#. 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:904 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "使用者名稱:"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1157
|
||||
#: ../js/gdm/loginDialog.js:1158
|
||||
msgid "Login Window"
|
||||
msgstr "登入視窗"
|
||||
|
||||
@@ -359,8 +366,8 @@ msgstr "登入視窗"
|
||||
msgid "Power"
|
||||
msgstr "電源"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699
|
||||
#: ../js/ui/userMenu.js:815
|
||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700
|
||||
#: ../js/ui/userMenu.js:816
|
||||
msgid "Suspend"
|
||||
msgstr "暫停"
|
||||
|
||||
@@ -368,58 +375,53 @@ msgstr "暫停"
|
||||
msgid "Restart"
|
||||
msgstr "重新啟動"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:697
|
||||
#: ../js/ui/userMenu.js:699 ../js/ui/userMenu.js:814 ../js/ui/userMenu.js:938
|
||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698
|
||||
#: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942
|
||||
msgid "Power Off"
|
||||
msgstr "關閉電源"
|
||||
|
||||
#: ../js/gdm/util.js:182
|
||||
#: ../js/gdm/util.js:247
|
||||
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:299
|
||||
#: ../js/gdm/util.js:364
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(或是滑過手指)"
|
||||
|
||||
#: ../js/gdm/util.js:324
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(例如: user 或 %s)"
|
||||
|
||||
#: ../js/misc/util.js:94
|
||||
#: ../js/misc/util.js:97
|
||||
msgid "Command not found"
|
||||
msgstr "找不到指令"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:127
|
||||
#: ../js/misc/util.js:130
|
||||
msgid "Could not parse command:"
|
||||
msgstr "無法分析指令:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
#: ../js/misc/util.js:138
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "執行「%s」失敗:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:348
|
||||
#: ../js/ui/appDisplay.js:356
|
||||
msgid "Frequent"
|
||||
msgstr "頻率"
|
||||
msgstr "常用"
|
||||
|
||||
#: ../js/ui/appDisplay.js:355
|
||||
#: ../js/ui/appDisplay.js:363
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
#: ../js/ui/appDisplay.js:913
|
||||
#: ../js/ui/appDisplay.js:941
|
||||
msgid "New Window"
|
||||
msgstr "新視窗"
|
||||
|
||||
#: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:944 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "自喜好中移除"
|
||||
|
||||
#: ../js/ui/appDisplay.js:917
|
||||
#: ../js/ui/appDisplay.js:945
|
||||
msgid "Add to Favorites"
|
||||
msgstr "加入喜好"
|
||||
|
||||
@@ -433,7 +435,7 @@ msgstr "%s 已加入你的喜好中。"
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s 已經從你的喜好中移除。"
|
||||
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789
|
||||
msgid "Settings"
|
||||
msgstr "設定值"
|
||||
|
||||
@@ -456,7 +458,7 @@ msgctxt "event list time"
|
||||
msgid "%H\\u2236%M"
|
||||
msgstr "%H\\u2236%M"
|
||||
|
||||
#. Transators: Shown in calendar event list, if 12h format,
|
||||
#. Translators: Shown in calendar event list, if 12h format,
|
||||
#. \u2236 is a ratio character, similar to : and \u2009 is
|
||||
#. a thin space
|
||||
#: ../js/ui/calendar.js:77
|
||||
@@ -558,35 +560,35 @@ msgid "S"
|
||||
msgstr "六"
|
||||
|
||||
#. Translators: Text to show if there are no events
|
||||
#: ../js/ui/calendar.js:692
|
||||
#: ../js/ui/calendar.js:720
|
||||
msgid "Nothing Scheduled"
|
||||
msgstr "沒有預訂行程"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on current year
|
||||
#: ../js/ui/calendar.js:708
|
||||
#: ../js/ui/calendar.js:736
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%m月%d日%A"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on different year
|
||||
#: ../js/ui/calendar.js:711
|
||||
#: ../js/ui/calendar.js:739
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %d, %Y"
|
||||
msgstr "%Y年%m月%d日%A"
|
||||
|
||||
#: ../js/ui/calendar.js:721
|
||||
#: ../js/ui/calendar.js:749
|
||||
msgid "Today"
|
||||
msgstr "今天"
|
||||
|
||||
#: ../js/ui/calendar.js:725
|
||||
#: ../js/ui/calendar.js:753
|
||||
msgid "Tomorrow"
|
||||
msgstr "明天"
|
||||
|
||||
#: ../js/ui/calendar.js:736
|
||||
#: ../js/ui/calendar.js:764
|
||||
msgid "This week"
|
||||
msgstr "本週"
|
||||
|
||||
#: ../js/ui/calendar.js:744
|
||||
#: ../js/ui/calendar.js:772
|
||||
msgid "Next week"
|
||||
msgstr "下週"
|
||||
|
||||
@@ -602,20 +604,20 @@ msgstr "外部裝置已拔除"
|
||||
msgid "Removable Devices"
|
||||
msgstr "可移除式裝置"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:593
|
||||
#: ../js/ui/components/autorunManager.js:594
|
||||
#, c-format
|
||||
msgid "Open with %s"
|
||||
msgstr "用 %s 開啟"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:619
|
||||
#: ../js/ui/components/autorunManager.js:620
|
||||
msgid "Eject"
|
||||
msgstr "退出"
|
||||
|
||||
#: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280
|
||||
msgid "Password:"
|
||||
msgstr "密碼: "
|
||||
|
||||
#: ../js/ui/components/keyring.js:101
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
msgid "Type again:"
|
||||
msgstr "再輸入一次:"
|
||||
|
||||
@@ -693,15 +695,15 @@ msgstr "流動寬頻網絡密碼"
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "連線至「%s」需要密碼。"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:55
|
||||
#: ../js/ui/components/polkitAgent.js:54
|
||||
msgid "Authentication Required"
|
||||
msgstr "要求驗證"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:93
|
||||
#: ../js/ui/components/polkitAgent.js:92
|
||||
msgid "Administrator"
|
||||
msgstr "系統管理員"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:165
|
||||
#: ../js/ui/components/polkitAgent.js:170
|
||||
msgid "Authenticate"
|
||||
msgstr "驗證"
|
||||
|
||||
@@ -709,12 +711,12 @@ msgstr "驗證"
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
#: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383
|
||||
#: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "抱歉,那樣無法運作。請再試一次。"
|
||||
|
||||
#. Translators: this is a filename used for screencast recording
|
||||
#: ../js/ui/components/recorder.js:48
|
||||
#: ../js/ui/components/recorder.js:47
|
||||
#, no-c-format
|
||||
msgid "Screencast from %d %t"
|
||||
msgstr "Screencast from %d %t"
|
||||
@@ -976,14 +978,14 @@ msgstr "開啟行事曆"
|
||||
msgid "Open Clocks"
|
||||
msgstr "開啟時鐘"
|
||||
|
||||
#: ../js/ui/dateMenu.js:105
|
||||
#: ../js/ui/dateMenu.js:104
|
||||
msgid "Date & Time Settings"
|
||||
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:205
|
||||
#: ../js/ui/dateMenu.js:216
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%Y年%m月%e日%A"
|
||||
|
||||
@@ -1080,7 +1082,7 @@ msgstr "安裝"
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "是否從 extensions.gnome.org 下載並安裝「%s」?"
|
||||
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333
|
||||
#: ../js/ui/status/power.js:211
|
||||
msgid "Keyboard"
|
||||
msgstr "鍵盤"
|
||||
@@ -1142,7 +1144,6 @@ msgid "Remove"
|
||||
msgstr "移除"
|
||||
|
||||
#: ../js/ui/messageTray.js:1501
|
||||
#| msgid "No Messages"
|
||||
msgid "Clear Messages"
|
||||
msgstr "清除訊息"
|
||||
|
||||
@@ -1150,15 +1151,15 @@ msgstr "清除訊息"
|
||||
msgid "Notification Settings"
|
||||
msgstr "通知設定值"
|
||||
|
||||
#: ../js/ui/messageTray.js:1707
|
||||
#: ../js/ui/messageTray.js:1709
|
||||
msgid "No Messages"
|
||||
msgstr "沒有訊息"
|
||||
|
||||
#: ../js/ui/messageTray.js:1787
|
||||
#: ../js/ui/messageTray.js:1785
|
||||
msgid "Message Tray"
|
||||
msgstr "訊息匣"
|
||||
|
||||
#: ../js/ui/messageTray.js:2864
|
||||
#: ../js/ui/messageTray.js:2818
|
||||
msgid "System Information"
|
||||
msgstr "系統資訊"
|
||||
|
||||
@@ -1167,13 +1168,13 @@ msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "不明"
|
||||
|
||||
#: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153
|
||||
#: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
|
||||
#, c-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] "%d 個新訊息"
|
||||
|
||||
#: ../js/ui/overview.js:82
|
||||
#: ../js/ui/overview.js:84
|
||||
msgid "Undo"
|
||||
msgstr "復原"
|
||||
|
||||
@@ -1185,22 +1186,21 @@ msgstr "概覽"
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: ../js/ui/overview.js:284
|
||||
#| msgid "Type to search..."
|
||||
#: ../js/ui/overview.js:271
|
||||
msgid "Type to search…"
|
||||
msgstr "輸入以搜尋…"
|
||||
|
||||
#: ../js/ui/panel.js:613
|
||||
#: ../js/ui/panel.js:635
|
||||
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:642
|
||||
#: ../js/ui/panel.js:686
|
||||
msgid "Activities"
|
||||
msgstr "概覽 "
|
||||
|
||||
#: ../js/ui/panel.js:983
|
||||
#: ../js/ui/panel.js:982
|
||||
msgid "Top Bar"
|
||||
msgstr "頂端列"
|
||||
|
||||
@@ -1209,35 +1209,35 @@ msgstr "頂端列"
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:727
|
||||
#: ../js/ui/popupMenu.js:740
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-us"
|
||||
|
||||
#: ../js/ui/runDialog.js:205
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Enter a Command"
|
||||
msgstr "請輸入指令"
|
||||
|
||||
#: ../js/ui/runDialog.js:241
|
||||
#: ../js/ui/runDialog.js:110
|
||||
msgid "Close"
|
||||
msgstr "關閉"
|
||||
|
||||
#. Translators: This is a time format for a date in
|
||||
#. long format
|
||||
#: ../js/ui/screenShield.js:90
|
||||
#: ../js/ui/screenShield.js:86
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%m月%d日%A"
|
||||
|
||||
#: ../js/ui/screenShield.js:155
|
||||
#: ../js/ui/screenShield.js:151
|
||||
#, c-format
|
||||
msgid "%d new notification"
|
||||
msgid_plural "%d new notifications"
|
||||
msgstr[0] "%d 個新通知"
|
||||
|
||||
#: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:806
|
||||
#: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807
|
||||
msgid "Lock"
|
||||
msgstr "鎖定"
|
||||
|
||||
#: ../js/ui/screenShield.js:639
|
||||
#: ../js/ui/screenShield.js:641
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME 需要鎖定螢幕"
|
||||
|
||||
@@ -1248,37 +1248,35 @@ msgstr "GNOME 需要鎖定螢幕"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169
|
||||
#| msgid "Unable to connect to %s"
|
||||
#: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
|
||||
msgid "Unable to lock"
|
||||
msgstr "無法鎖定"
|
||||
|
||||
#: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170
|
||||
#: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "鎖定被應用程式阻擋"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:431
|
||||
#| msgid "Searching..."
|
||||
#: ../js/ui/searchDisplay.js:453
|
||||
msgid "Searching…"
|
||||
msgstr "搜尋…"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:475
|
||||
#: ../js/ui/searchDisplay.js:497
|
||||
msgid "No results."
|
||||
msgstr "沒有結果。"
|
||||
|
||||
#: ../js/ui/shellEntry.js:29
|
||||
#: ../js/ui/shellEntry.js:27
|
||||
msgid "Copy"
|
||||
msgstr "複製"
|
||||
|
||||
#: ../js/ui/shellEntry.js:34
|
||||
#: ../js/ui/shellEntry.js:32
|
||||
msgid "Paste"
|
||||
msgstr "貼上"
|
||||
|
||||
#: ../js/ui/shellEntry.js:105
|
||||
#: ../js/ui/shellEntry.js:99
|
||||
msgid "Show Text"
|
||||
msgstr "顯示文字"
|
||||
|
||||
#: ../js/ui/shellEntry.js:107
|
||||
#: ../js/ui/shellEntry.js:101
|
||||
msgid "Hide Text"
|
||||
msgstr "隱藏文字"
|
||||
|
||||
@@ -1290,7 +1288,7 @@ msgstr "密碼"
|
||||
msgid "Remember Password"
|
||||
msgstr "記住密碼"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
|
||||
msgid "Unlock"
|
||||
msgstr "解鎖"
|
||||
|
||||
@@ -1354,12 +1352,10 @@ msgid "Visibility"
|
||||
msgstr "顯示狀態"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:59
|
||||
#| msgid "Send Files to Device..."
|
||||
msgid "Send Files to Device…"
|
||||
msgstr "傳送檔案到裝置…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:60
|
||||
#| msgid "Set Up a New Device..."
|
||||
msgid "Set Up a New Device…"
|
||||
msgstr "設定新的裝置…"
|
||||
|
||||
@@ -1386,7 +1382,6 @@ msgid "connecting..."
|
||||
msgstr "連線中…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:239
|
||||
#| msgid "Send Files..."
|
||||
msgid "Send Files…"
|
||||
msgstr "傳送檔案…"
|
||||
|
||||
@@ -1462,11 +1457,11 @@ msgstr "請輸入裝置所提及的 PIN。"
|
||||
msgid "OK"
|
||||
msgstr "確定"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:368
|
||||
#: ../js/ui/status/keyboard.js:396
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "顯示鍵盤配置"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:373
|
||||
#: ../js/ui/status/keyboard.js:401
|
||||
msgid "Region & Language Settings"
|
||||
msgstr "地區和語言設定值"
|
||||
|
||||
@@ -1584,7 +1579,7 @@ msgstr "連線失敗"
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "啟動網絡連線失敗"
|
||||
|
||||
#: ../js/ui/status/network.js:2276
|
||||
#: ../js/ui/status/network.js:2282
|
||||
msgid "Networking is disabled"
|
||||
msgstr "網絡已停用"
|
||||
|
||||
@@ -1599,7 +1594,6 @@ msgstr "電源設定值"
|
||||
#. 0 is reported when UPower does not have enough data
|
||||
#. to estimate battery life
|
||||
#: ../js/ui/status/power.js:99
|
||||
#| msgid "Estimating..."
|
||||
msgid "Estimating…"
|
||||
msgstr "評估中…"
|
||||
|
||||
@@ -1695,11 +1689,11 @@ msgstr "音量"
|
||||
msgid "Microphone"
|
||||
msgstr "麥克風"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:151
|
||||
#: ../js/ui/unlockDialog.js:120
|
||||
msgid "Log in as another user"
|
||||
msgstr "以另一個使用者身分登入"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:177
|
||||
#: ../js/ui/unlockDialog.js:141
|
||||
msgid "Unlock Window"
|
||||
msgstr "解鎖視窗"
|
||||
|
||||
@@ -1727,46 +1721,48 @@ msgstr "閒置"
|
||||
msgid "Offline"
|
||||
msgstr "離線"
|
||||
|
||||
#: ../js/ui/userMenu.js:780
|
||||
#: ../js/ui/userMenu.js:781
|
||||
msgid "Notifications"
|
||||
msgstr "通知"
|
||||
|
||||
#: ../js/ui/userMenu.js:796
|
||||
#: ../js/ui/userMenu.js:797
|
||||
msgid "Switch User"
|
||||
msgstr "切換使用者"
|
||||
|
||||
#: ../js/ui/userMenu.js:801
|
||||
#: ../js/ui/userMenu.js:802
|
||||
msgid "Log Out"
|
||||
msgstr "登出"
|
||||
|
||||
#: ../js/ui/userMenu.js:821
|
||||
#: ../js/ui/userMenu.js:822
|
||||
msgid "Install Updates & Restart"
|
||||
msgstr "安裝更新 & 重新啟動"
|
||||
|
||||
#: ../js/ui/userMenu.js:839
|
||||
#: ../js/ui/userMenu.js:840
|
||||
msgid "Your chat status will be set to busy"
|
||||
msgstr "你的聊天狀態會設為忙碌"
|
||||
|
||||
#: ../js/ui/userMenu.js:840
|
||||
#: ../js/ui/userMenu.js:841
|
||||
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/userMenu.js:886
|
||||
#: ../js/ui/userMenu.js:888
|
||||
msgid "Other users are logged in."
|
||||
msgstr "其他使用者已登入。"
|
||||
|
||||
#: ../js/ui/userMenu.js:891
|
||||
#: ../js/ui/userMenu.js:893
|
||||
msgid "Shutting down might cause them to lose unsaved work."
|
||||
msgstr "關機可能使它們失去未儲存的工作。"
|
||||
|
||||
#: ../js/ui/userMenu.js:918
|
||||
#. Translators: Remote here refers to a remote session, like a ssh login
|
||||
#: ../js/ui/userMenu.js:921
|
||||
#, c-format
|
||||
msgid "%s (remote)"
|
||||
msgstr "%s (遠端)"
|
||||
|
||||
#: ../js/ui/userMenu.js:920
|
||||
#. Translators: Console here refers to a tty like a VT console
|
||||
#: ../js/ui/userMenu.js:924
|
||||
#, c-format
|
||||
msgid "%s (console)"
|
||||
msgstr "%s (主控臺)"
|
||||
@@ -1779,7 +1775,7 @@ msgstr "應用程式"
|
||||
msgid "Search"
|
||||
msgstr "搜尋"
|
||||
|
||||
#: ../js/ui/wanda.js:92
|
||||
#: ../js/ui/wanda.js:77
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Sorry, no wisdom for you today:\n"
|
||||
@@ -1788,7 +1784,7 @@ msgstr ""
|
||||
"抱歉,今天可能有些問題:\n"
|
||||
"%s"
|
||||
|
||||
#: ../js/ui/wanda.js:96
|
||||
#: ../js/ui/wanda.js:81
|
||||
#, c-format
|
||||
msgid "%s the Oracle says"
|
||||
msgstr "%s Oracle 說:"
|
||||
@@ -1818,7 +1814,7 @@ msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] "%u 輸入"
|
||||
|
||||
#: ../src/gvc/gvc-mixer-control.c:2371
|
||||
#: ../src/gvc/gvc-mixer-control.c:2373
|
||||
msgid "System Sounds"
|
||||
msgstr "系統音效"
|
||||
|
||||
@@ -1843,11 +1839,11 @@ msgstr "列出可能的模式"
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "無法啟動「%s」"
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:708
|
||||
#: ../src/shell-keyring-prompt.c:714
|
||||
msgid "Passwords do not match."
|
||||
msgstr "密碼不相符。"
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:716
|
||||
#: ../src/shell-keyring-prompt.c:722
|
||||
msgid "Password cannot be blank"
|
||||
msgstr "密碼不能為空白"
|
||||
|
||||
|
214
po/zh_TW.po
214
po/zh_TW.po
@@ -9,15 +9,16 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell 3.3.90\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-03-04 08:38+0000\n"
|
||||
"PO-Revision-Date: 2013-03-05 19:49+0800\n"
|
||||
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
|
||||
"POT-Creation-Date: 2013-05-31 18:55+0000\n"
|
||||
"PO-Revision-Date: 2013-04-27 00:04+0800\n"
|
||||
"Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n"
|
||||
"Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Poedit 1.5.3\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
|
||||
msgid "Screenshots"
|
||||
@@ -343,44 +344,50 @@ msgstr "擴充功能"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "使用上面的組合方塊選擇要設定的擴充功能。"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:405
|
||||
#| msgid "Session..."
|
||||
#: ../js/gdm/loginDialog.js:371
|
||||
msgid "Session…"
|
||||
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:629
|
||||
#: ../js/gdm/loginDialog.js:601
|
||||
msgid "Not listed?"
|
||||
msgstr "沒有列出來?"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375
|
||||
#: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
|
||||
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126
|
||||
#: ../js/ui/userMenu.js:934
|
||||
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
|
||||
#: ../js/ui/userMenu.js:938
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:799
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgctxt "button"
|
||||
msgid "Sign In"
|
||||
msgstr "登入"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:799
|
||||
#: ../js/gdm/loginDialog.js:791
|
||||
msgid "Next"
|
||||
msgstr "下一個"
|
||||
|
||||
#. Translators: this message is shown below the username entry field
|
||||
#. to clue the user in on how to login to the local network realm
|
||||
#: ../js/gdm/loginDialog.js:888
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(例如: user 或 %s)"
|
||||
|
||||
#. 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:904 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260
|
||||
#: ../js/ui/components/networkAgent.js:278
|
||||
msgid "Username: "
|
||||
msgstr "使用者名稱:"
|
||||
|
||||
#: ../js/gdm/loginDialog.js:1157
|
||||
#: ../js/gdm/loginDialog.js:1158
|
||||
msgid "Login Window"
|
||||
msgstr "登入視窗"
|
||||
|
||||
@@ -389,8 +396,8 @@ msgstr "登入視窗"
|
||||
msgid "Power"
|
||||
msgstr "電源"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699
|
||||
#: ../js/ui/userMenu.js:815
|
||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700
|
||||
#: ../js/ui/userMenu.js:816
|
||||
msgid "Suspend"
|
||||
msgstr "暫停"
|
||||
|
||||
@@ -398,58 +405,53 @@ msgstr "暫停"
|
||||
msgid "Restart"
|
||||
msgstr "重新啟動"
|
||||
|
||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:697
|
||||
#: ../js/ui/userMenu.js:699 ../js/ui/userMenu.js:814 ../js/ui/userMenu.js:938
|
||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698
|
||||
#: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942
|
||||
msgid "Power Off"
|
||||
msgstr "關閉電源"
|
||||
|
||||
#: ../js/gdm/util.js:182
|
||||
#: ../js/gdm/util.js:247
|
||||
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:299
|
||||
#: ../js/gdm/util.js:364
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(或是滑過手指)"
|
||||
|
||||
#: ../js/gdm/util.js:324
|
||||
#, c-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(例如: user 或 %s)"
|
||||
|
||||
#: ../js/misc/util.js:94
|
||||
#: ../js/misc/util.js:97
|
||||
msgid "Command not found"
|
||||
msgstr "找不到指令"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:127
|
||||
#: ../js/misc/util.js:130
|
||||
msgid "Could not parse command:"
|
||||
msgstr "無法分析指令:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
#: ../js/misc/util.js:138
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "執行「%s」失敗:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:348
|
||||
#: ../js/ui/appDisplay.js:356
|
||||
msgid "Frequent"
|
||||
msgstr "頻率"
|
||||
msgstr "常用"
|
||||
|
||||
#: ../js/ui/appDisplay.js:355
|
||||
#: ../js/ui/appDisplay.js:363
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
#: ../js/ui/appDisplay.js:913
|
||||
#: ../js/ui/appDisplay.js:941
|
||||
msgid "New Window"
|
||||
msgstr "新視窗"
|
||||
|
||||
#: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:944 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "自喜好中移除"
|
||||
|
||||
#: ../js/ui/appDisplay.js:917
|
||||
#: ../js/ui/appDisplay.js:945
|
||||
msgid "Add to Favorites"
|
||||
msgstr "加入喜好"
|
||||
|
||||
@@ -463,7 +465,7 @@ msgstr "%s 已加入您的喜好中。"
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s 已經從您的喜好中移除。"
|
||||
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789
|
||||
msgid "Settings"
|
||||
msgstr "設定值"
|
||||
|
||||
@@ -486,7 +488,7 @@ msgctxt "event list time"
|
||||
msgid "%H\\u2236%M"
|
||||
msgstr "%H\\u2236%M"
|
||||
|
||||
#. Transators: Shown in calendar event list, if 12h format,
|
||||
#. Translators: Shown in calendar event list, if 12h format,
|
||||
#. \u2236 is a ratio character, similar to : and \u2009 is
|
||||
#. a thin space
|
||||
#: ../js/ui/calendar.js:77
|
||||
@@ -588,35 +590,35 @@ msgid "S"
|
||||
msgstr "六"
|
||||
|
||||
#. Translators: Text to show if there are no events
|
||||
#: ../js/ui/calendar.js:692
|
||||
#: ../js/ui/calendar.js:720
|
||||
msgid "Nothing Scheduled"
|
||||
msgstr "沒有預訂行程"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on current year
|
||||
#: ../js/ui/calendar.js:708
|
||||
#: ../js/ui/calendar.js:736
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%m月%d日%A"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on different year
|
||||
#: ../js/ui/calendar.js:711
|
||||
#: ../js/ui/calendar.js:739
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %d, %Y"
|
||||
msgstr "%Y年%m月%d日%A"
|
||||
|
||||
#: ../js/ui/calendar.js:721
|
||||
#: ../js/ui/calendar.js:749
|
||||
msgid "Today"
|
||||
msgstr "今天"
|
||||
|
||||
#: ../js/ui/calendar.js:725
|
||||
#: ../js/ui/calendar.js:753
|
||||
msgid "Tomorrow"
|
||||
msgstr "明天"
|
||||
|
||||
#: ../js/ui/calendar.js:736
|
||||
#: ../js/ui/calendar.js:764
|
||||
msgid "This week"
|
||||
msgstr "本週"
|
||||
|
||||
#: ../js/ui/calendar.js:744
|
||||
#: ../js/ui/calendar.js:772
|
||||
msgid "Next week"
|
||||
msgstr "下週"
|
||||
|
||||
@@ -632,20 +634,20 @@ msgstr "外部裝置已拔除"
|
||||
msgid "Removable Devices"
|
||||
msgstr "可移除式裝置"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:593
|
||||
#: ../js/ui/components/autorunManager.js:594
|
||||
#, c-format
|
||||
msgid "Open with %s"
|
||||
msgstr "用 %s 開啟"
|
||||
|
||||
#: ../js/ui/components/autorunManager.js:619
|
||||
#: ../js/ui/components/autorunManager.js:620
|
||||
msgid "Eject"
|
||||
msgstr "退出"
|
||||
|
||||
#: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280
|
||||
msgid "Password:"
|
||||
msgstr "密碼: "
|
||||
|
||||
#: ../js/ui/components/keyring.js:101
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
msgid "Type again:"
|
||||
msgstr "再輸入一次:"
|
||||
|
||||
@@ -723,15 +725,15 @@ msgstr "行動寬頻網路密碼"
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "連線至「%s」需要密碼。"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:55
|
||||
#: ../js/ui/components/polkitAgent.js:54
|
||||
msgid "Authentication Required"
|
||||
msgstr "要求驗證"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:93
|
||||
#: ../js/ui/components/polkitAgent.js:92
|
||||
msgid "Administrator"
|
||||
msgstr "系統管理員"
|
||||
|
||||
#: ../js/ui/components/polkitAgent.js:165
|
||||
#: ../js/ui/components/polkitAgent.js:170
|
||||
msgid "Authenticate"
|
||||
msgstr "驗證"
|
||||
|
||||
@@ -739,12 +741,12 @@ msgstr "驗證"
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
#: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383
|
||||
#: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "抱歉,那樣無法運作。請再試一次。"
|
||||
|
||||
#. Translators: this is a filename used for screencast recording
|
||||
#: ../js/ui/components/recorder.js:48
|
||||
#: ../js/ui/components/recorder.js:47
|
||||
#, no-c-format
|
||||
msgid "Screencast from %d %t"
|
||||
msgstr "Screencast from %d %t"
|
||||
@@ -1006,14 +1008,14 @@ msgstr "開啟行事曆"
|
||||
msgid "Open Clocks"
|
||||
msgstr "開啟時鐘"
|
||||
|
||||
#: ../js/ui/dateMenu.js:105
|
||||
#: ../js/ui/dateMenu.js:104
|
||||
msgid "Date & Time Settings"
|
||||
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:205
|
||||
#: ../js/ui/dateMenu.js:216
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%Y年%m月%e日%A"
|
||||
|
||||
@@ -1110,7 +1112,7 @@ msgstr "安裝"
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "是否從 extensions.gnome.org 下載並安裝「%s」?"
|
||||
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333
|
||||
#: ../js/ui/status/power.js:211
|
||||
msgid "Keyboard"
|
||||
msgstr "鍵盤"
|
||||
@@ -1172,7 +1174,6 @@ msgid "Remove"
|
||||
msgstr "移除"
|
||||
|
||||
#: ../js/ui/messageTray.js:1501
|
||||
#| msgid "No Messages"
|
||||
msgid "Clear Messages"
|
||||
msgstr "清除訊息"
|
||||
|
||||
@@ -1180,15 +1181,15 @@ msgstr "清除訊息"
|
||||
msgid "Notification Settings"
|
||||
msgstr "通知設定值"
|
||||
|
||||
#: ../js/ui/messageTray.js:1707
|
||||
#: ../js/ui/messageTray.js:1709
|
||||
msgid "No Messages"
|
||||
msgstr "沒有訊息"
|
||||
|
||||
#: ../js/ui/messageTray.js:1787
|
||||
#: ../js/ui/messageTray.js:1785
|
||||
msgid "Message Tray"
|
||||
msgstr "訊息匣"
|
||||
|
||||
#: ../js/ui/messageTray.js:2864
|
||||
#: ../js/ui/messageTray.js:2818
|
||||
msgid "System Information"
|
||||
msgstr "系統資訊"
|
||||
|
||||
@@ -1197,13 +1198,13 @@ msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "不明"
|
||||
|
||||
#: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153
|
||||
#: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
|
||||
#, c-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] "%d 個新訊息"
|
||||
|
||||
#: ../js/ui/overview.js:82
|
||||
#: ../js/ui/overview.js:84
|
||||
msgid "Undo"
|
||||
msgstr "復原"
|
||||
|
||||
@@ -1215,22 +1216,21 @@ msgstr "概覽"
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: ../js/ui/overview.js:284
|
||||
#| msgid "Type to search..."
|
||||
#: ../js/ui/overview.js:271
|
||||
msgid "Type to search…"
|
||||
msgstr "輸入以搜尋…"
|
||||
|
||||
#: ../js/ui/panel.js:613
|
||||
#: ../js/ui/panel.js:635
|
||||
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:642
|
||||
#: ../js/ui/panel.js:686
|
||||
msgid "Activities"
|
||||
msgstr "概覽 "
|
||||
|
||||
#: ../js/ui/panel.js:983
|
||||
#: ../js/ui/panel.js:982
|
||||
msgid "Top Bar"
|
||||
msgstr "頂端列"
|
||||
|
||||
@@ -1239,35 +1239,35 @@ msgstr "頂端列"
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:727
|
||||
#: ../js/ui/popupMenu.js:740
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-us"
|
||||
|
||||
#: ../js/ui/runDialog.js:205
|
||||
#: ../js/ui/runDialog.js:74
|
||||
msgid "Enter a Command"
|
||||
msgstr "請輸入指令"
|
||||
|
||||
#: ../js/ui/runDialog.js:241
|
||||
#: ../js/ui/runDialog.js:110
|
||||
msgid "Close"
|
||||
msgstr "關閉"
|
||||
|
||||
#. Translators: This is a time format for a date in
|
||||
#. long format
|
||||
#: ../js/ui/screenShield.js:90
|
||||
#: ../js/ui/screenShield.js:86
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%m月%d日%A"
|
||||
|
||||
#: ../js/ui/screenShield.js:155
|
||||
#: ../js/ui/screenShield.js:151
|
||||
#, c-format
|
||||
msgid "%d new notification"
|
||||
msgid_plural "%d new notifications"
|
||||
msgstr[0] "%d 個新通知"
|
||||
|
||||
#: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:806
|
||||
#: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807
|
||||
msgid "Lock"
|
||||
msgstr "鎖定"
|
||||
|
||||
#: ../js/ui/screenShield.js:639
|
||||
#: ../js/ui/screenShield.js:641
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME 需要鎖定螢幕"
|
||||
|
||||
@@ -1278,37 +1278,35 @@ msgstr "GNOME 需要鎖定螢幕"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169
|
||||
#| msgid "Unable to connect to %s"
|
||||
#: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
|
||||
msgid "Unable to lock"
|
||||
msgstr "無法鎖定"
|
||||
|
||||
#: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170
|
||||
#: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "鎖定被應用程式阻擋"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:431
|
||||
#| msgid "Searching..."
|
||||
#: ../js/ui/searchDisplay.js:453
|
||||
msgid "Searching…"
|
||||
msgstr "搜尋…"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:475
|
||||
#: ../js/ui/searchDisplay.js:497
|
||||
msgid "No results."
|
||||
msgstr "沒有結果。"
|
||||
|
||||
#: ../js/ui/shellEntry.js:29
|
||||
#: ../js/ui/shellEntry.js:27
|
||||
msgid "Copy"
|
||||
msgstr "複製"
|
||||
|
||||
#: ../js/ui/shellEntry.js:34
|
||||
#: ../js/ui/shellEntry.js:32
|
||||
msgid "Paste"
|
||||
msgstr "貼上"
|
||||
|
||||
#: ../js/ui/shellEntry.js:105
|
||||
#: ../js/ui/shellEntry.js:99
|
||||
msgid "Show Text"
|
||||
msgstr "顯示文字"
|
||||
|
||||
#: ../js/ui/shellEntry.js:107
|
||||
#: ../js/ui/shellEntry.js:101
|
||||
msgid "Hide Text"
|
||||
msgstr "隱藏文字"
|
||||
|
||||
@@ -1320,7 +1318,7 @@ msgstr "密碼"
|
||||
msgid "Remember Password"
|
||||
msgstr "記住密碼"
|
||||
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140
|
||||
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
|
||||
msgid "Unlock"
|
||||
msgstr "解鎖"
|
||||
|
||||
@@ -1384,12 +1382,10 @@ msgid "Visibility"
|
||||
msgstr "顯示狀態"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:59
|
||||
#| msgid "Send Files to Device..."
|
||||
msgid "Send Files to Device…"
|
||||
msgstr "傳送檔案到裝置…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:60
|
||||
#| msgid "Set Up a New Device..."
|
||||
msgid "Set Up a New Device…"
|
||||
msgstr "設定新的裝置…"
|
||||
|
||||
@@ -1416,7 +1412,6 @@ msgid "connecting..."
|
||||
msgstr "連線中…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:239
|
||||
#| msgid "Send Files..."
|
||||
msgid "Send Files…"
|
||||
msgstr "傳送檔案…"
|
||||
|
||||
@@ -1492,11 +1487,11 @@ msgstr "請輸入裝置所提及的 PIN。"
|
||||
msgid "OK"
|
||||
msgstr "確定"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:368
|
||||
#: ../js/ui/status/keyboard.js:396
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "顯示鍵盤配置"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:373
|
||||
#: ../js/ui/status/keyboard.js:401
|
||||
msgid "Region & Language Settings"
|
||||
msgstr "地區和語言設定值"
|
||||
|
||||
@@ -1614,7 +1609,7 @@ msgstr "連線失敗"
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "啟動網路連線失敗"
|
||||
|
||||
#: ../js/ui/status/network.js:2276
|
||||
#: ../js/ui/status/network.js:2282
|
||||
msgid "Networking is disabled"
|
||||
msgstr "網路已停用"
|
||||
|
||||
@@ -1629,7 +1624,6 @@ msgstr "電源設定值"
|
||||
#. 0 is reported when UPower does not have enough data
|
||||
#. to estimate battery life
|
||||
#: ../js/ui/status/power.js:99
|
||||
#| msgid "Estimating..."
|
||||
msgid "Estimating…"
|
||||
msgstr "評估中…"
|
||||
|
||||
@@ -1725,11 +1719,11 @@ msgstr "音量"
|
||||
msgid "Microphone"
|
||||
msgstr "麥克風"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:151
|
||||
#: ../js/ui/unlockDialog.js:120
|
||||
msgid "Log in as another user"
|
||||
msgstr "以另一個使用者身分登入"
|
||||
|
||||
#: ../js/ui/unlockDialog.js:177
|
||||
#: ../js/ui/unlockDialog.js:141
|
||||
msgid "Unlock Window"
|
||||
msgstr "解鎖視窗"
|
||||
|
||||
@@ -1757,27 +1751,27 @@ msgstr "閒置"
|
||||
msgid "Offline"
|
||||
msgstr "離線"
|
||||
|
||||
#: ../js/ui/userMenu.js:780
|
||||
#: ../js/ui/userMenu.js:781
|
||||
msgid "Notifications"
|
||||
msgstr "通知"
|
||||
|
||||
#: ../js/ui/userMenu.js:796
|
||||
#: ../js/ui/userMenu.js:797
|
||||
msgid "Switch User"
|
||||
msgstr "切換使用者"
|
||||
|
||||
#: ../js/ui/userMenu.js:801
|
||||
#: ../js/ui/userMenu.js:802
|
||||
msgid "Log Out"
|
||||
msgstr "登出"
|
||||
|
||||
#: ../js/ui/userMenu.js:821
|
||||
#: ../js/ui/userMenu.js:822
|
||||
msgid "Install Updates & Restart"
|
||||
msgstr "安裝更新 & 重新啟動"
|
||||
|
||||
#: ../js/ui/userMenu.js:839
|
||||
#: ../js/ui/userMenu.js:840
|
||||
msgid "Your chat status will be set to busy"
|
||||
msgstr "您的聊天狀態會設為忙碌"
|
||||
|
||||
#: ../js/ui/userMenu.js:840
|
||||
#: ../js/ui/userMenu.js:841
|
||||
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."
|
||||
@@ -1785,20 +1779,22 @@ msgstr ""
|
||||
"通知現在已被停用,包含聊天訊息。您的上線狀態也調整為讓其他人知道您沒時間看他"
|
||||
"們的訊息。"
|
||||
|
||||
#: ../js/ui/userMenu.js:886
|
||||
#: ../js/ui/userMenu.js:888
|
||||
msgid "Other users are logged in."
|
||||
msgstr "其他使用者已登入。"
|
||||
|
||||
#: ../js/ui/userMenu.js:891
|
||||
#: ../js/ui/userMenu.js:893
|
||||
msgid "Shutting down might cause them to lose unsaved work."
|
||||
msgstr "關機可能使它們失去未儲存的工作。"
|
||||
|
||||
#: ../js/ui/userMenu.js:918
|
||||
#. Translators: Remote here refers to a remote session, like a ssh login
|
||||
#: ../js/ui/userMenu.js:921
|
||||
#, c-format
|
||||
msgid "%s (remote)"
|
||||
msgstr "%s (遠端)"
|
||||
|
||||
#: ../js/ui/userMenu.js:920
|
||||
#. Translators: Console here refers to a tty like a VT console
|
||||
#: ../js/ui/userMenu.js:924
|
||||
#, c-format
|
||||
msgid "%s (console)"
|
||||
msgstr "%s (主控臺)"
|
||||
@@ -1811,7 +1807,7 @@ msgstr "應用程式"
|
||||
msgid "Search"
|
||||
msgstr "搜尋"
|
||||
|
||||
#: ../js/ui/wanda.js:92
|
||||
#: ../js/ui/wanda.js:77
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Sorry, no wisdom for you today:\n"
|
||||
@@ -1820,7 +1816,7 @@ msgstr ""
|
||||
"抱歉,今天可能有些問題:\n"
|
||||
"%s"
|
||||
|
||||
#: ../js/ui/wanda.js:96
|
||||
#: ../js/ui/wanda.js:81
|
||||
#, c-format
|
||||
msgid "%s the Oracle says"
|
||||
msgstr "%s Oracle 說:"
|
||||
@@ -1850,7 +1846,7 @@ msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] "%u 輸入"
|
||||
|
||||
#: ../src/gvc/gvc-mixer-control.c:2371
|
||||
#: ../src/gvc/gvc-mixer-control.c:2373
|
||||
msgid "System Sounds"
|
||||
msgstr "系統音效"
|
||||
|
||||
@@ -1875,11 +1871,11 @@ msgstr "列出可能的模式"
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "無法啟動「%s」"
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:708
|
||||
#: ../src/shell-keyring-prompt.c:714
|
||||
msgid "Passwords do not match."
|
||||
msgstr "密碼不相符。"
|
||||
|
||||
#: ../src/shell-keyring-prompt.c:716
|
||||
#: ../src/shell-keyring-prompt.c:722
|
||||
msgid "Password cannot be blank"
|
||||
msgstr "密碼不能為空白"
|
||||
|
||||
|
@@ -135,10 +135,7 @@ shell_private_sources = \
|
||||
gactionobservable.h \
|
||||
gactionobservable.c \
|
||||
gactionobserver.h \
|
||||
gactionobserver.c \
|
||||
gtkmenutracker.c \
|
||||
gtkmenutracker.h \
|
||||
$(NULL)
|
||||
gactionobserver.c
|
||||
|
||||
libgnome_shell_la_SOURCES = \
|
||||
$(shell_built_sources) \
|
||||
@@ -161,8 +158,6 @@ libgnome_shell_la_SOURCES = \
|
||||
shell-invert-lightness-effect.c \
|
||||
shell-keyring-prompt.h \
|
||||
shell-keyring-prompt.c \
|
||||
shell-menu-tracker.c \
|
||||
shell-menu-tracker.h \
|
||||
shell-mount-operation.c \
|
||||
shell-network-agent.c \
|
||||
shell-perf-log.c \
|
||||
|
@@ -1,434 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2013 Canonical Limited
|
||||
*
|
||||
* 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: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkmenutracker.h"
|
||||
|
||||
typedef struct _GtkMenuTrackerSection GtkMenuTrackerSection;
|
||||
|
||||
struct _GtkMenuTracker
|
||||
{
|
||||
GtkMenuTrackerInsertFunc insert_func;
|
||||
GtkMenuTrackerRemoveFunc remove_func;
|
||||
gpointer user_data;
|
||||
|
||||
GtkMenuTrackerSection *toplevel;
|
||||
};
|
||||
|
||||
struct _GtkMenuTrackerSection
|
||||
{
|
||||
GMenuModel *model;
|
||||
GSList *items;
|
||||
gchar *action_namespace;
|
||||
|
||||
guint with_separators : 1;
|
||||
guint has_separator : 1;
|
||||
|
||||
gulong handler;
|
||||
};
|
||||
|
||||
static GtkMenuTrackerSection * gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
gint offset,
|
||||
const gchar *action_namespace);
|
||||
static void gtk_menu_tracker_section_free (GtkMenuTrackerSection *section);
|
||||
|
||||
static GtkMenuTrackerSection *
|
||||
gtk_menu_tracker_section_find_model (GtkMenuTrackerSection *section,
|
||||
GMenuModel *model,
|
||||
gint *offset)
|
||||
{
|
||||
GSList *item;
|
||||
|
||||
if (section->has_separator)
|
||||
(*offset)++;
|
||||
|
||||
if (section->model == model)
|
||||
return section;
|
||||
|
||||
for (item = section->items; item; item = item->next)
|
||||
{
|
||||
GtkMenuTrackerSection *subsection = item->data;
|
||||
|
||||
if (subsection)
|
||||
{
|
||||
GtkMenuTrackerSection *found_section;
|
||||
|
||||
found_section = gtk_menu_tracker_section_find_model (subsection, model, offset);
|
||||
|
||||
if (found_section)
|
||||
return found_section;
|
||||
}
|
||||
else
|
||||
(*offset)++;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* this is responsible for syncing the showing of a separator for a
|
||||
* single subsection (and its children).
|
||||
*
|
||||
* we only ever show separators if we have _actual_ children (ie: we do
|
||||
* not show a separator if the section contains only empty child
|
||||
* sections). it's difficult to determine this on-the-fly, so we have
|
||||
* this separate function to come back later and figure it out.
|
||||
*
|
||||
* 'section' is that section.
|
||||
*
|
||||
* 'tracker' is passed in so that we can emit callbacks when we decide
|
||||
* to add/remove separators.
|
||||
*
|
||||
* 'offset' is passed in so we know which position to emit in our
|
||||
* callbacks. ie: if we add a separator right at the top of this
|
||||
* section then we would emit it with this offset. deeper inside, we
|
||||
* adjust accordingly.
|
||||
*
|
||||
* could_have_separator is true in two situations:
|
||||
*
|
||||
* - our parent section had with_separators defined and we are not the
|
||||
* first section (ie: we should add a separator if we have content in
|
||||
* order to divide us from the items above)
|
||||
*
|
||||
* - if we had a 'label' attribute set for this section
|
||||
*
|
||||
* parent_model and parent_index are passed in so that we can give them
|
||||
* to the insertion callback so that it can see the label (and anything
|
||||
* else that happens to be defined on the section).
|
||||
*
|
||||
* we iterate each item in ourselves. for subsections, we recursively
|
||||
* run ourselves to sync separators. after we are done, we notice if we
|
||||
* have any items in us or if we are completely empty and sync if our
|
||||
* separator is shown or not.
|
||||
*/
|
||||
static gint
|
||||
gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section,
|
||||
GtkMenuTracker *tracker,
|
||||
gint offset,
|
||||
gboolean could_have_separator,
|
||||
GMenuModel *parent_model,
|
||||
gint parent_index)
|
||||
{
|
||||
gboolean should_have_separator;
|
||||
gint n_items = 0;
|
||||
GSList *item;
|
||||
gint i = 0;
|
||||
|
||||
for (item = section->items; item; item = item->next)
|
||||
{
|
||||
GtkMenuTrackerSection *subsection = item->data;
|
||||
|
||||
if (subsection)
|
||||
{
|
||||
gboolean could_have_separator;
|
||||
|
||||
could_have_separator = (section->with_separators && i > 0) ||
|
||||
g_menu_model_get_item_attribute (section->model, i, "label", "s", NULL);
|
||||
|
||||
n_items += gtk_menu_tracker_section_sync_separators (subsection, tracker, offset + n_items,
|
||||
could_have_separator, section->model, i);
|
||||
}
|
||||
else
|
||||
n_items++;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
should_have_separator = could_have_separator && n_items != 0;
|
||||
|
||||
if (should_have_separator > section->has_separator)
|
||||
{
|
||||
/* Add a separator */
|
||||
(* tracker->insert_func) (offset, parent_model, parent_index, NULL, TRUE, tracker->user_data);
|
||||
section->has_separator = TRUE;
|
||||
}
|
||||
else if (should_have_separator < section->has_separator)
|
||||
{
|
||||
/* Remove a separator */
|
||||
(* tracker->remove_func) (offset, tracker->user_data);
|
||||
section->has_separator = FALSE;
|
||||
}
|
||||
|
||||
n_items += section->has_separator;
|
||||
|
||||
return n_items;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_menu_tracker_section_measure (GtkMenuTrackerSection *section)
|
||||
{
|
||||
GSList *item;
|
||||
gint n_items;
|
||||
|
||||
if (section == NULL)
|
||||
return 1;
|
||||
|
||||
n_items = 0;
|
||||
|
||||
if (section->has_separator)
|
||||
n_items++;
|
||||
|
||||
for (item = section->items; item; item = item->next)
|
||||
n_items += gtk_menu_tracker_section_measure (item->data);
|
||||
|
||||
return n_items;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_remove_items (GtkMenuTracker *tracker,
|
||||
GSList **change_point,
|
||||
gint offset,
|
||||
gint n_items)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_items; i++)
|
||||
{
|
||||
GtkMenuTrackerSection *subsection;
|
||||
gint n;
|
||||
|
||||
subsection = (*change_point)->data;
|
||||
*change_point = g_slist_delete_link (*change_point, *change_point);
|
||||
|
||||
n = gtk_menu_tracker_section_measure (subsection);
|
||||
gtk_menu_tracker_section_free (subsection);
|
||||
|
||||
while (n--)
|
||||
(* tracker->remove_func) (offset, tracker->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_add_items (GtkMenuTracker *tracker,
|
||||
GtkMenuTrackerSection *section,
|
||||
GSList **change_point,
|
||||
gint offset,
|
||||
GMenuModel *model,
|
||||
gint position,
|
||||
gint n_items)
|
||||
{
|
||||
while (n_items--)
|
||||
{
|
||||
GMenuModel *submenu;
|
||||
|
||||
submenu = g_menu_model_get_item_link (model, position + n_items, G_MENU_LINK_SECTION);
|
||||
g_assert (submenu != model);
|
||||
if (submenu != NULL)
|
||||
{
|
||||
GtkMenuTrackerSection *subsection;
|
||||
gchar *action_namespace = NULL;
|
||||
|
||||
g_menu_model_get_item_attribute (model, position + n_items,
|
||||
G_MENU_ATTRIBUTE_ACTION_NAMESPACE, "s", &action_namespace);
|
||||
|
||||
if (section->action_namespace)
|
||||
{
|
||||
gchar *namespace;
|
||||
|
||||
namespace = g_strjoin (".", section->action_namespace, action_namespace, NULL);
|
||||
subsection = gtk_menu_tracker_section_new (tracker, submenu, FALSE, offset, namespace);
|
||||
g_free (namespace);
|
||||
}
|
||||
else
|
||||
subsection = gtk_menu_tracker_section_new (tracker, submenu, FALSE, offset, section->action_namespace);
|
||||
|
||||
*change_point = g_slist_prepend (*change_point, subsection);
|
||||
g_free (action_namespace);
|
||||
g_object_unref (submenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
(* tracker->insert_func) (offset, model, position + n_items,
|
||||
section->action_namespace, FALSE, tracker->user_data);
|
||||
*change_point = g_slist_prepend (*change_point, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_model_changed (GMenuModel *model,
|
||||
gint position,
|
||||
gint removed,
|
||||
gint added,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTracker *tracker = user_data;
|
||||
GtkMenuTrackerSection *section;
|
||||
GSList **change_point;
|
||||
gint offset = 0;
|
||||
gint i;
|
||||
|
||||
/* First find which section the changed model corresponds to, and the
|
||||
* position of that section within the overall menu.
|
||||
*/
|
||||
section = gtk_menu_tracker_section_find_model (tracker->toplevel, model, &offset);
|
||||
|
||||
/* Next, seek through that section to the change point. This gives us
|
||||
* the correct GSList** to make the change to and also finds the final
|
||||
* offset at which we will make the changes (by measuring the number
|
||||
* of items within each item of the section before the change point).
|
||||
*/
|
||||
change_point = §ion->items;
|
||||
for (i = 0; i < position; i++)
|
||||
{
|
||||
offset += gtk_menu_tracker_section_measure ((*change_point)->data);
|
||||
change_point = &(*change_point)->next;
|
||||
}
|
||||
|
||||
/* We remove items in order and add items in reverse order. This
|
||||
* means that the offset used for all inserts and removes caused by a
|
||||
* single change will be the same.
|
||||
*
|
||||
* This also has a performance advantage: GtkMenuShell stores the
|
||||
* menu items in a linked list. In the case where we are creating a
|
||||
* menu for the first time, adding the items in reverse order means
|
||||
* that we only ever insert at index zero, prepending the list. This
|
||||
* means that we can populate in O(n) time instead of O(n^2) that we
|
||||
* would do by appending.
|
||||
*/
|
||||
gtk_menu_tracker_remove_items (tracker, change_point, offset, removed);
|
||||
gtk_menu_tracker_add_items (tracker, section, change_point, offset, model, position, added);
|
||||
|
||||
/* The offsets for insertion/removal of separators will be all over
|
||||
* the place, however...
|
||||
*/
|
||||
gtk_menu_tracker_section_sync_separators (tracker->toplevel, tracker, 0, FALSE, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_section_free (GtkMenuTrackerSection *section)
|
||||
{
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
g_signal_handler_disconnect (section->model, section->handler);
|
||||
g_slist_free_full (section->items, (GDestroyNotify) gtk_menu_tracker_section_free);
|
||||
g_free (section->action_namespace);
|
||||
g_object_unref (section->model);
|
||||
g_slice_free (GtkMenuTrackerSection, section);
|
||||
}
|
||||
|
||||
static GtkMenuTrackerSection *
|
||||
gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
gint offset,
|
||||
const gchar *action_namespace)
|
||||
{
|
||||
GtkMenuTrackerSection *section;
|
||||
|
||||
section = g_slice_new0 (GtkMenuTrackerSection);
|
||||
section->model = g_object_ref (model);
|
||||
section->with_separators = with_separators;
|
||||
section->action_namespace = g_strdup (action_namespace);
|
||||
|
||||
gtk_menu_tracker_add_items (tracker, section, §ion->items, offset, model, 0, g_menu_model_get_n_items (model));
|
||||
section->handler = g_signal_connect (model, "items-changed", G_CALLBACK (gtk_menu_tracker_model_changed), tracker);
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_menu_tracker_new:
|
||||
* @model: the model to flatten
|
||||
* @with_separators: if the toplevel should have separators (ie: TRUE
|
||||
* for menus, FALSE for menubars)
|
||||
* @action_namespace: the passed-in action namespace
|
||||
* @insert_func: insert callback
|
||||
* @remove_func: remove callback
|
||||
* @user_data user data for callbacks
|
||||
*
|
||||
* Creates a GtkMenuTracker for @model, holding a ref on @model for as
|
||||
* long as the tracker is alive.
|
||||
*
|
||||
* This flattens out the model, merging sections and inserting
|
||||
* separators where appropriate. It monitors for changes and performs
|
||||
* updates on the fly. It also handles action_namespace for subsections
|
||||
* (but you will need to handle it yourself for submenus).
|
||||
*
|
||||
* When the tracker is first created, @insert_func will be called many
|
||||
* times to populate the menu with the initial contents of @model
|
||||
* (unless it is empty), before gtk_menu_tracker_new() returns. For
|
||||
* this reason, the menu that is using the tracker ought to be empty
|
||||
* when it creates the tracker.
|
||||
*
|
||||
* Future changes to @model will result in more calls to @insert_func
|
||||
* and @remove_func.
|
||||
*
|
||||
* The position argument to both functions is the linear 0-based
|
||||
* position in the menu at which the item in question should be inserted
|
||||
* or removed.
|
||||
*
|
||||
* For @insert_func, @model and @item_index are used to get the
|
||||
* information about the menu item to insert. @action_namespace is the
|
||||
* action namespace that actions referred to from that item should place
|
||||
* themselves in. Note that if the item is a submenu and the
|
||||
* "action-namespace" attribute is defined on the item, it will _not_ be
|
||||
* applied to the @action_namespace argument as it is meant for the
|
||||
* items inside of the submenu, not the submenu item itself.
|
||||
*
|
||||
* @is_separator is set to %TRUE in case the item being added is a
|
||||
* separator. @model and @item_index will still be meaningfully set in
|
||||
* this case -- to the section menu item corresponding to the separator.
|
||||
* This is useful if the section specifies a label, for example. If
|
||||
* there is an "action-namespace" attribute on this menu item then it
|
||||
* should be ignored by the consumer because #GtkMenuTracker has already
|
||||
* handled it.
|
||||
*
|
||||
* When using #GtkMenuTracker there is no need to hold onto @model or
|
||||
* monitor it for changes. The model will be unreffed when
|
||||
* gtk_menu_tracker_free() is called.
|
||||
*/
|
||||
GtkMenuTracker *
|
||||
gtk_menu_tracker_new (GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
GtkMenuTrackerRemoveFunc remove_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTracker *tracker;
|
||||
|
||||
tracker = g_slice_new (GtkMenuTracker);
|
||||
tracker->insert_func = insert_func;
|
||||
tracker->remove_func = remove_func;
|
||||
tracker->user_data = user_data;
|
||||
|
||||
tracker->toplevel = gtk_menu_tracker_section_new (tracker, model, with_separators, 0, action_namespace);
|
||||
gtk_menu_tracker_section_sync_separators (tracker->toplevel, tracker, 0, FALSE, NULL, 0);
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_menu_tracker_free:
|
||||
* @tracker: a #GtkMenuTracker
|
||||
*
|
||||
* Frees the tracker, ...
|
||||
*/
|
||||
void
|
||||
gtk_menu_tracker_free (GtkMenuTracker *tracker)
|
||||
{
|
||||
gtk_menu_tracker_section_free (tracker->toplevel);
|
||||
g_slice_free (GtkMenuTracker, tracker);
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2013 Canonical Limited
|
||||
*
|
||||
* 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: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_MENU_TRACKER_H__
|
||||
#define __GTK_MENU_TRACKER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
typedef struct _GtkMenuTracker GtkMenuTracker;
|
||||
|
||||
typedef void (* GtkMenuTrackerInsertFunc) (gint position,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (* GtkMenuTrackerRemoveFunc) (gint position,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GtkMenuTracker * gtk_menu_tracker_new (GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
GtkMenuTrackerRemoveFunc remove_func,
|
||||
gpointer user_data);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gtk_menu_tracker_free (GtkMenuTracker *tracker);
|
||||
|
||||
#endif /* __GTK_MENU_TRACKER_H__ */
|
2
src/gvc
2
src/gvc
Submodule src/gvc updated: 03894efbcd...3d6aac673b
20
src/main.c
20
src/main.c
@@ -36,8 +36,6 @@ extern GType gnome_shell_plugin_get_type (void);
|
||||
#define SHELL_DBUS_SERVICE "org.gnome.Shell"
|
||||
#define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier"
|
||||
|
||||
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
|
||||
|
||||
#define WM_NAME "GNOME Shell"
|
||||
#define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell"
|
||||
|
||||
@@ -166,23 +164,6 @@ shell_dbus_init (gboolean replace)
|
||||
g_object_unref (session);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_prefs_init (void)
|
||||
{
|
||||
meta_prefs_override_preference_schema ("attach-modal-dialogs",
|
||||
OVERRIDES_SCHEMA);
|
||||
meta_prefs_override_preference_schema ("dynamic-workspaces",
|
||||
OVERRIDES_SCHEMA);
|
||||
meta_prefs_override_preference_schema ("workspaces-only-on-primary",
|
||||
OVERRIDES_SCHEMA);
|
||||
meta_prefs_override_preference_schema ("button-layout",
|
||||
OVERRIDES_SCHEMA);
|
||||
meta_prefs_override_preference_schema ("edge-tiling",
|
||||
OVERRIDES_SCHEMA);
|
||||
meta_prefs_override_preference_schema ("focus-change-on-pointer-rest",
|
||||
OVERRIDES_SCHEMA);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_introspection_init (void)
|
||||
{
|
||||
@@ -409,7 +390,6 @@ main (int argc, char **argv)
|
||||
shell_dbus_init (meta_get_replace_current_wm ());
|
||||
shell_a11y_init ();
|
||||
shell_perf_log_init ();
|
||||
shell_prefs_init ();
|
||||
shell_introspection_init ();
|
||||
shell_fonts_init ();
|
||||
|
||||
|
133
src/shell-app.c
133
src/shell-app.c
@@ -39,14 +39,10 @@ typedef struct {
|
||||
/* Whether or not we need to resort the windows; this is done on demand */
|
||||
gboolean window_sort_stale : 1;
|
||||
|
||||
/* DBus property notification subscription */
|
||||
guint properties_changed_id : 1;
|
||||
|
||||
/* See GApplication documentation */
|
||||
GDBusMenuModel *remote_menu;
|
||||
GActionMuxer *muxer;
|
||||
char *unique_bus_name;
|
||||
GDBusConnection *session;
|
||||
char * unique_bus_name;
|
||||
} ShellAppRunningState;
|
||||
|
||||
/**
|
||||
@@ -214,6 +210,7 @@ shell_app_create_icon_texture (ShellApp *app,
|
||||
typedef struct {
|
||||
ShellApp *app;
|
||||
int size;
|
||||
ClutterTextDirection direction;
|
||||
} CreateFadedIconData;
|
||||
|
||||
static CoglHandle
|
||||
@@ -231,7 +228,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
|
||||
guint8 n_channels;
|
||||
gboolean have_alpha;
|
||||
gint fade_start;
|
||||
gint fade_range;
|
||||
gint fade_end;
|
||||
guint i, j;
|
||||
guint pixbuf_byte_size;
|
||||
guint8 *orig_pixels;
|
||||
@@ -283,14 +280,26 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
|
||||
pixels = g_malloc0 (rowstride * height);
|
||||
memcpy (pixels, orig_pixels, pixbuf_byte_size);
|
||||
|
||||
fade_start = width / 2;
|
||||
fade_range = width - fade_start;
|
||||
for (i = fade_start; i < width; i++)
|
||||
/* fade on the right side for LTR, left side for RTL */
|
||||
if (data->direction == CLUTTER_TEXT_DIRECTION_LTR)
|
||||
{
|
||||
fade_start = width / 2;
|
||||
fade_end = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
fade_start = 0;
|
||||
fade_end = width / 2;
|
||||
}
|
||||
|
||||
for (i = fade_start; i < fade_end; i++)
|
||||
{
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
guchar *pixel = &pixels[j * rowstride + i * n_channels];
|
||||
float fade = 1.0 - ((float) i - fade_start) / fade_range;
|
||||
float fade = ((float) i - fade_start) / (fade_end - fade_start);
|
||||
if (data->direction == CLUTTER_TEXT_DIRECTION_LTR)
|
||||
fade = 1.0 - fade;
|
||||
pixel[0] = 0.5 + pixel[0] * fade;
|
||||
pixel[1] = 0.5 + pixel[1] * fade;
|
||||
pixel[2] = 0.5 + pixel[2] * fade;
|
||||
@@ -316,13 +325,14 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
|
||||
* shell_app_get_faded_icon:
|
||||
* @app: A #ShellApp
|
||||
* @size: Size in pixels
|
||||
* @direction: Whether to fade on the left or right
|
||||
*
|
||||
* Return an actor with a horizontally faded look.
|
||||
*
|
||||
* Return value: (transfer none): A floating #ClutterActor, or %NULL if no icon
|
||||
*/
|
||||
ClutterActor *
|
||||
shell_app_get_faded_icon (ShellApp *app, int size)
|
||||
shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection direction)
|
||||
{
|
||||
CoglHandle texture;
|
||||
ClutterActor *result;
|
||||
@@ -338,9 +348,13 @@ shell_app_get_faded_icon (ShellApp *app, int size)
|
||||
|
||||
/* Use icon: prefix so that we get evicted from the cache on
|
||||
* icon theme changes. */
|
||||
cache_key = g_strdup_printf ("icon:%s,size=%d,faded", shell_app_get_id (app), size);
|
||||
cache_key = g_strdup_printf ("icon:%s,size=%d,faded-%s",
|
||||
shell_app_get_id (app),
|
||||
size,
|
||||
direction == CLUTTER_TEXT_DIRECTION_RTL ? "rtl" : "ltr");
|
||||
data.app = app;
|
||||
data.size = size;
|
||||
data.direction = direction;
|
||||
texture = st_texture_cache_load (st_texture_cache_get_default (),
|
||||
cache_key,
|
||||
ST_TEXTURE_CACHE_POLICY_FOREVER,
|
||||
@@ -558,7 +572,7 @@ shell_app_update_window_actions (ShellApp *app, MetaWindow *window)
|
||||
actions = g_object_get_data (G_OBJECT (window), "actions");
|
||||
if (actions == NULL)
|
||||
{
|
||||
actions = G_ACTION_GROUP (g_dbus_action_group_get (app->running_state->session,
|
||||
actions = G_ACTION_GROUP (g_dbus_action_group_get (g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL),
|
||||
meta_window_get_gtk_unique_bus_name (window),
|
||||
object_path));
|
||||
g_object_set_data_full (G_OBJECT (window), "actions", actions, g_object_unref);
|
||||
@@ -962,84 +976,6 @@ shell_app_on_ws_switch (MetaScreen *screen,
|
||||
g_signal_emit (app, shell_app_signals[WINDOWS_CHANGED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
application_properties_changed (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellApp *app = user_data;
|
||||
GVariant *changed_properties;
|
||||
GVariantIter iter;
|
||||
gboolean busy = FALSE;
|
||||
const gchar *key, *interface_name_for_signal;
|
||||
GVariant *value;
|
||||
|
||||
g_variant_get (parameters,
|
||||
"(&s@a{sv}as)",
|
||||
&interface_name_for_signal,
|
||||
&changed_properties,
|
||||
NULL);
|
||||
|
||||
if (g_strcmp0 (interface_name_for_signal, "org.gtk.Application") != 0)
|
||||
return;
|
||||
|
||||
g_variant_iter_init (&iter, changed_properties);
|
||||
while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
|
||||
{
|
||||
if (g_strcmp0 (key, "Busy") != 0)
|
||||
{
|
||||
g_variant_unref (value);
|
||||
continue;
|
||||
}
|
||||
|
||||
busy = g_variant_get_boolean (value);
|
||||
g_variant_unref (value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (busy)
|
||||
shell_app_state_transition (app, SHELL_APP_STATE_BUSY);
|
||||
else
|
||||
shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
|
||||
|
||||
if (changed_properties != NULL)
|
||||
g_variant_unref (changed_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_app_ensure_busy_watch (ShellApp *app)
|
||||
{
|
||||
ShellAppRunningState *running_state = app->running_state;
|
||||
MetaWindow *window;
|
||||
const gchar *object_path;
|
||||
|
||||
if (running_state->properties_changed_id != 0)
|
||||
return;
|
||||
|
||||
if (running_state->unique_bus_name == NULL)
|
||||
return;
|
||||
|
||||
window = g_slist_nth_data (running_state->windows, 0);
|
||||
object_path = meta_window_get_gtk_application_object_path (window);
|
||||
|
||||
if (object_path == NULL)
|
||||
return;
|
||||
|
||||
running_state->properties_changed_id =
|
||||
g_dbus_connection_signal_subscribe (running_state->session,
|
||||
running_state->unique_bus_name,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged",
|
||||
object_path,
|
||||
"org.gtk.Application",
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
application_properties_changed, app, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_shell_app_add_window (ShellApp *app,
|
||||
MetaWindow *window)
|
||||
@@ -1058,7 +994,6 @@ _shell_app_add_window (ShellApp *app,
|
||||
g_signal_connect (window, "notify::user-time", G_CALLBACK(shell_app_on_user_time_changed), app);
|
||||
|
||||
shell_app_update_app_menu (app, window);
|
||||
shell_app_ensure_busy_watch (app);
|
||||
|
||||
if (app->state != SHELL_APP_STATE_STARTING)
|
||||
shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
|
||||
@@ -1301,8 +1236,6 @@ create_running_state (ShellApp *app)
|
||||
app->running_state->workspace_switch_id =
|
||||
g_signal_connect (screen, "workspace-switched", G_CALLBACK(shell_app_on_ws_switch), app);
|
||||
|
||||
app->running_state->session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
||||
g_assert (app->running_state->session != NULL);
|
||||
app->running_state->muxer = g_action_muxer_new ();
|
||||
}
|
||||
|
||||
@@ -1329,6 +1262,7 @@ shell_app_update_app_menu (ShellApp *app,
|
||||
{
|
||||
const gchar *application_object_path;
|
||||
const gchar *app_menu_object_path;
|
||||
GDBusConnection *session;
|
||||
GDBusActionGroup *actions;
|
||||
|
||||
application_object_path = meta_window_get_gtk_application_object_path (window);
|
||||
@@ -1337,13 +1271,16 @@ shell_app_update_app_menu (ShellApp *app,
|
||||
if (application_object_path == NULL || app_menu_object_path == NULL || unique_bus_name == NULL)
|
||||
return;
|
||||
|
||||
session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
||||
g_assert (session != NULL);
|
||||
g_clear_pointer (&app->running_state->unique_bus_name, g_free);
|
||||
app->running_state->unique_bus_name = g_strdup (unique_bus_name);
|
||||
g_clear_object (&app->running_state->remote_menu);
|
||||
app->running_state->remote_menu = g_dbus_menu_model_get (app->running_state->session, unique_bus_name, app_menu_object_path);
|
||||
actions = g_dbus_action_group_get (app->running_state->session, unique_bus_name, application_object_path);
|
||||
app->running_state->remote_menu = g_dbus_menu_model_get (session, unique_bus_name, app_menu_object_path);
|
||||
actions = g_dbus_action_group_get (session, unique_bus_name, application_object_path);
|
||||
g_action_muxer_insert (app->running_state->muxer, "app", G_ACTION_GROUP (actions));
|
||||
g_object_unref (actions);
|
||||
g_object_unref (session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,12 +1298,8 @@ unref_running_state (ShellAppRunningState *state)
|
||||
screen = shell_global_get_screen (shell_global_get ());
|
||||
g_signal_handler_disconnect (screen, state->workspace_switch_id);
|
||||
|
||||
if (state->properties_changed_id != 0)
|
||||
g_dbus_connection_signal_unsubscribe (state->session, state->properties_changed_id);
|
||||
|
||||
g_clear_object (&state->remote_menu);
|
||||
g_clear_object (&state->muxer);
|
||||
g_clear_object (&state->session);
|
||||
g_clear_pointer (&state->unique_bus_name, g_free);
|
||||
g_clear_pointer (&state->remote_menu, g_free);
|
||||
|
||||
|
@@ -31,8 +31,7 @@ struct _ShellAppClass
|
||||
typedef enum {
|
||||
SHELL_APP_STATE_STOPPED,
|
||||
SHELL_APP_STATE_STARTING,
|
||||
SHELL_APP_STATE_RUNNING,
|
||||
SHELL_APP_STATE_BUSY
|
||||
SHELL_APP_STATE_RUNNING
|
||||
} ShellAppState;
|
||||
|
||||
GType shell_app_get_type (void) G_GNUC_CONST;
|
||||
@@ -43,7 +42,7 @@ GMenuTreeEntry *shell_app_get_tree_entry (ShellApp *app);
|
||||
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
|
||||
|
||||
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
|
||||
ClutterActor *shell_app_get_faded_icon (ShellApp *app, int size);
|
||||
ClutterActor *shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection direction);
|
||||
const char *shell_app_get_name (ShellApp *app);
|
||||
const char *shell_app_get_description (ShellApp *app);
|
||||
gboolean shell_app_is_window_backed (ShellApp *app);
|
||||
|
@@ -1009,6 +1009,13 @@ shell_global_end_modal (ShellGlobal *global,
|
||||
meta_plugin_end_modal (global->plugin, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
shell_global_freeze_keyboard (ShellGlobal *global,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_display_freeze_keyboard (global->meta_display, global->stage_xwindow, timestamp);
|
||||
}
|
||||
|
||||
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
|
||||
*
|
||||
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
|
||||
|
@@ -44,6 +44,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global,
|
||||
MetaModalOptions options);
|
||||
void shell_global_end_modal (ShellGlobal *global,
|
||||
guint32 timestamp);
|
||||
void shell_global_freeze_keyboard (ShellGlobal *global,
|
||||
guint32 timestamp);
|
||||
|
||||
typedef enum {
|
||||
SHELL_STAGE_INPUT_MODE_NONREACTIVE,
|
||||
|
@@ -106,6 +106,8 @@ shell_gtk_embed_window_created_cb (MetaDisplay *display,
|
||||
0, 0 /* offset x/y */);
|
||||
cairo_region_destroy (empty_region);
|
||||
|
||||
gdk_window_lower (gdk_window);
|
||||
|
||||
/* Now that we've found the window we don't need to listen for
|
||||
new windows anymore */
|
||||
g_signal_handler_disconnect (display,
|
||||
|
@@ -100,7 +100,6 @@ G_DEFINE_TYPE_WITH_CODE (ShellKeyringPrompt, shell_keyring_prompt, G_TYPE_OBJECT
|
||||
enum {
|
||||
SIGNAL_SHOW_PASSWORD,
|
||||
SIGNAL_SHOW_CONFIRM,
|
||||
SIGNAL_HIDE_PROMPT,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
@@ -258,10 +257,8 @@ shell_keyring_prompt_dispose (GObject *obj)
|
||||
{
|
||||
ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
|
||||
|
||||
if (self->shown) {
|
||||
self->shown = FALSE;
|
||||
g_signal_emit (self, signals[SIGNAL_HIDE_PROMPT], 0);
|
||||
}
|
||||
if (self->shown)
|
||||
gcr_prompt_close (GCR_PROMPT (self));
|
||||
|
||||
if (self->async_result)
|
||||
shell_keyring_prompt_cancel (self);
|
||||
@@ -384,11 +381,6 @@ shell_keyring_prompt_class_init (ShellKeyringPromptClass *klass)
|
||||
0, 0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[SIGNAL_HIDE_PROMPT] = g_signal_new ("hide-prompt", G_TYPE_FROM_CLASS (klass),
|
||||
0, 0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -482,6 +474,19 @@ shell_keyring_prompt_confirm_finish (GcrPrompt *prompt,
|
||||
return self->last_reply;
|
||||
}
|
||||
|
||||
static void
|
||||
shell_keyring_prompt_close (GcrPrompt *prompt)
|
||||
{
|
||||
ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
|
||||
|
||||
/*
|
||||
* We expect keyring.js to connect to this signal and do the
|
||||
* actual work of closing the prompt.
|
||||
*/
|
||||
|
||||
self->shown = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
shell_keyring_prompt_iface (GcrPromptIface *iface)
|
||||
{
|
||||
@@ -489,6 +494,7 @@ shell_keyring_prompt_iface (GcrPromptIface *iface)
|
||||
iface->prompt_password_finish = shell_keyring_prompt_password_finish;
|
||||
iface->prompt_confirm_async = shell_keyring_prompt_confirm_async;
|
||||
iface->prompt_confirm_finish = shell_keyring_prompt_confirm_finish;
|
||||
iface->prompt_close = shell_keyring_prompt_close;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,9 +752,19 @@ shell_keyring_prompt_cancel (ShellKeyringPrompt *self)
|
||||
GSimpleAsyncResult *res;
|
||||
|
||||
g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
|
||||
g_return_if_fail (self->mode != PROMPTING_NONE);
|
||||
g_return_if_fail (self->async_result != NULL);
|
||||
|
||||
/*
|
||||
* If cancelled while not prompting, we should just close the prompt,
|
||||
* the user wants it to go away.
|
||||
*/
|
||||
if (self->mode == PROMPTING_NONE)
|
||||
{
|
||||
if (self->shown)
|
||||
gcr_prompt_close (GCR_PROMPT (self));
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_fail (self->async_result != NULL);
|
||||
self->last_reply = GCR_PROMPT_REPLY_CANCEL;
|
||||
|
||||
res = self->async_result;
|
||||
|
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "shell-menu-tracker.h"
|
||||
#include "gtkmenutracker.h"
|
||||
|
||||
struct _ShellMenuTracker
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
GtkMenuTracker *tracker;
|
||||
|
||||
ShellMenuTrackerInsertFunc insert_func;
|
||||
gpointer insert_user_data;
|
||||
GDestroyNotify insert_notify;
|
||||
ShellMenuTrackerRemoveFunc remove_func;
|
||||
gpointer remove_user_data;
|
||||
GDestroyNotify remove_notify;
|
||||
};
|
||||
|
||||
static void
|
||||
shell_menu_tracker_insert_func (gint position,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellMenuTracker *tracker = (ShellMenuTracker *) user_data;
|
||||
tracker->insert_func (position, model, item_index,
|
||||
action_namespace, is_separator,
|
||||
tracker->insert_user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_menu_tracker_remove_func (gint position,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellMenuTracker *tracker = (ShellMenuTracker *) user_data;
|
||||
tracker->remove_func (position, tracker->remove_user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_menu_tracker_new:
|
||||
* @model:
|
||||
* @action_namespace: (allow-none):
|
||||
* @insert_func:
|
||||
* @insert_user_data:
|
||||
* @insert_notify:
|
||||
* @remove_func:
|
||||
* @remove_user_data:
|
||||
* @remove_notify:
|
||||
*/
|
||||
ShellMenuTracker *
|
||||
shell_menu_tracker_new (GMenuModel *model,
|
||||
const gchar *action_namespace,
|
||||
ShellMenuTrackerInsertFunc insert_func,
|
||||
gpointer insert_user_data,
|
||||
GDestroyNotify insert_notify,
|
||||
ShellMenuTrackerRemoveFunc remove_func,
|
||||
gpointer remove_user_data,
|
||||
GDestroyNotify remove_notify)
|
||||
{
|
||||
ShellMenuTracker *tracker = g_slice_new0 (ShellMenuTracker);
|
||||
|
||||
tracker->ref_count = 1;
|
||||
tracker->insert_func = insert_func;
|
||||
tracker->insert_user_data = insert_user_data;
|
||||
tracker->insert_notify = insert_notify;
|
||||
tracker->remove_func = remove_func;
|
||||
tracker->remove_user_data = remove_user_data;
|
||||
tracker->remove_notify = remove_notify;
|
||||
|
||||
tracker->tracker = gtk_menu_tracker_new (model,
|
||||
TRUE, /* with separators */
|
||||
action_namespace,
|
||||
shell_menu_tracker_insert_func,
|
||||
shell_menu_tracker_remove_func,
|
||||
tracker);
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
ShellMenuTracker *
|
||||
shell_menu_tracker_ref (ShellMenuTracker *tracker)
|
||||
{
|
||||
tracker->ref_count++;
|
||||
return tracker;
|
||||
}
|
||||
|
||||
void
|
||||
shell_menu_tracker_unref (ShellMenuTracker *tracker)
|
||||
{
|
||||
if (tracker->ref_count-- <= 0)
|
||||
{
|
||||
shell_menu_tracker_destroy (tracker);
|
||||
g_slice_free (ShellMenuTracker, tracker);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shell_menu_tracker_destroy (ShellMenuTracker *tracker)
|
||||
{
|
||||
if (tracker->tracker != NULL)
|
||||
{
|
||||
gtk_menu_tracker_free (tracker->tracker);
|
||||
tracker->tracker = NULL;
|
||||
tracker->insert_notify (tracker->insert_user_data);
|
||||
tracker->remove_notify (tracker->remove_user_data);
|
||||
}
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE(ShellMenuTracker,
|
||||
shell_menu_tracker,
|
||||
shell_menu_tracker_ref,
|
||||
shell_menu_tracker_unref)
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __SHELL_MENU_TRACKER_H__
|
||||
#define __SHELL_MENU_TRACKER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
typedef struct _ShellMenuTracker ShellMenuTracker;
|
||||
|
||||
GType shell_menu_tracker_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef void (* ShellMenuTrackerInsertFunc) (gint position,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (* ShellMenuTrackerRemoveFunc) (gint position,
|
||||
gpointer user_data);
|
||||
|
||||
ShellMenuTracker * shell_menu_tracker_new (GMenuModel *model,
|
||||
const gchar *action_namespace,
|
||||
ShellMenuTrackerInsertFunc insert_func,
|
||||
gpointer insert_user_data,
|
||||
GDestroyNotify insert_notify,
|
||||
ShellMenuTrackerRemoveFunc remove_func,
|
||||
gpointer remove_user_data,
|
||||
GDestroyNotify remove_notify);
|
||||
ShellMenuTracker * shell_menu_tracker_ref (ShellMenuTracker *tracker);
|
||||
void shell_menu_tracker_unref (ShellMenuTracker *tracker);
|
||||
void shell_menu_tracker_destroy (ShellMenuTracker *tracker);
|
||||
|
||||
#endif /* __SHELL_MENU_TRACKER_H__ */
|
@@ -25,6 +25,9 @@
|
||||
/* This is also hard-coded in mutter and GDK */
|
||||
#define VIRTUAL_CORE_POINTER_ID 2
|
||||
|
||||
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
|
||||
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
|
||||
|
||||
typedef enum {
|
||||
RECORDER_STATE_CLOSED,
|
||||
RECORDER_STATE_RECORDING
|
||||
@@ -50,6 +53,8 @@ struct _ShellRecorder {
|
||||
RecorderState state;
|
||||
|
||||
ClutterStage *stage;
|
||||
gboolean custom_area;
|
||||
cairo_rectangle_int_t area;
|
||||
int stage_width;
|
||||
int stage_height;
|
||||
|
||||
@@ -66,6 +71,8 @@ struct _ShellRecorder {
|
||||
|
||||
CoglHandle recording_icon; /* icon shown while playing */
|
||||
|
||||
GSettings *a11y_settings;
|
||||
gboolean draw_cursor;
|
||||
cairo_surface_t *cursor_image;
|
||||
int cursor_hot_x;
|
||||
int cursor_hot_y;
|
||||
@@ -110,6 +117,8 @@ static void recorder_set_pipeline (ShellRecorder *recorder,
|
||||
const char *pipeline);
|
||||
static void recorder_set_file_template (ShellRecorder *recorder,
|
||||
const char *file_template);
|
||||
static void recorder_set_draw_cursor (ShellRecorder *recorder,
|
||||
gboolean draw_cursor);
|
||||
|
||||
static void recorder_pipeline_set_caps (RecorderPipeline *pipeline);
|
||||
static void recorder_pipeline_closed (RecorderPipeline *pipeline);
|
||||
@@ -119,7 +128,8 @@ enum {
|
||||
PROP_STAGE,
|
||||
PROP_FRAMERATE,
|
||||
PROP_PIPELINE,
|
||||
PROP_FILE_TEMPLATE
|
||||
PROP_FILE_TEMPLATE,
|
||||
PROP_DRAW_CURSOR
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
|
||||
@@ -271,8 +281,11 @@ shell_recorder_init (ShellRecorder *recorder)
|
||||
recorder->recording_icon = create_recording_icon ();
|
||||
recorder->memory_target = get_memory_target();
|
||||
|
||||
recorder->a11y_settings = g_settings_new (A11Y_APPS_SCHEMA);
|
||||
|
||||
recorder->state = RECORDER_STATE_CLOSED;
|
||||
recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
|
||||
recorder->draw_cursor = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -292,6 +305,8 @@ shell_recorder_finalize (GObject *object)
|
||||
|
||||
cogl_handle_unref (recorder->recording_icon);
|
||||
|
||||
g_clear_object (&recorder->a11y_settings);
|
||||
|
||||
G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -429,10 +444,10 @@ recorder_draw_cursor (ShellRecorder *recorder,
|
||||
/* We don't show a cursor unless the hot spot is in the frame; this
|
||||
* means that sometimes we aren't going to draw a cursor even when
|
||||
* there is a little bit overlapping within the stage */
|
||||
if (recorder->pointer_x < 0 ||
|
||||
recorder->pointer_y < 0 ||
|
||||
recorder->pointer_x >= recorder->stage_width ||
|
||||
recorder->pointer_y >= recorder->stage_height)
|
||||
if (recorder->pointer_x < recorder->area.x ||
|
||||
recorder->pointer_y < recorder->area.y ||
|
||||
recorder->pointer_x >= recorder->area.x + recorder->area.width ||
|
||||
recorder->pointer_y >= recorder->area.y + recorder->area.height)
|
||||
return;
|
||||
|
||||
if (!recorder->cursor_image)
|
||||
@@ -444,15 +459,15 @@ recorder_draw_cursor (ShellRecorder *recorder,
|
||||
gst_buffer_map (buffer, &info, GST_MAP_WRITE);
|
||||
surface = cairo_image_surface_create_for_data (info.data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
recorder->stage_width,
|
||||
recorder->stage_height,
|
||||
recorder->stage_width * 4);
|
||||
recorder->area.width,
|
||||
recorder->area.height,
|
||||
recorder->area.width * 4);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_surface (cr,
|
||||
recorder->cursor_image,
|
||||
recorder->pointer_x - recorder->cursor_hot_x,
|
||||
recorder->pointer_y - recorder->cursor_hot_y);
|
||||
recorder->pointer_x - recorder->cursor_hot_x - recorder->area.x,
|
||||
recorder->pointer_y - recorder->cursor_hot_y - recorder->area.y);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
@@ -470,7 +485,7 @@ recorder_draw_buffer_meter (ShellRecorder *recorder)
|
||||
GdkRectangle primary_monitor;
|
||||
float rects[16];
|
||||
|
||||
gdk_screen_get_monitor_geometry (recorder->gdk_screen,
|
||||
gdk_screen_get_monitor_workarea (recorder->gdk_screen,
|
||||
gdk_screen_get_primary_monitor (recorder->gdk_screen),
|
||||
&primary_monitor);
|
||||
|
||||
@@ -555,12 +570,13 @@ recorder_record_frame (ShellRecorder *recorder)
|
||||
|
||||
recorder->last_frame_time = now;
|
||||
|
||||
size = recorder->stage_width * recorder->stage_height * 4;
|
||||
size = recorder->area.width * recorder->area.height * 4;
|
||||
|
||||
data = g_malloc (recorder->stage_width * 4 * recorder->stage_height);
|
||||
cogl_read_pixels (0, 0, /* x/y */
|
||||
recorder->stage_width,
|
||||
recorder->stage_height,
|
||||
data = g_malloc (recorder->area.width * 4 * recorder->area.height);
|
||||
cogl_read_pixels (recorder->area.x,
|
||||
recorder->area.y,
|
||||
recorder->area.width,
|
||||
recorder->area.height,
|
||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||
data);
|
||||
@@ -572,7 +588,9 @@ recorder_record_frame (ShellRecorder *recorder)
|
||||
|
||||
GST_BUFFER_PTS(buffer) = now - recorder->start_time;
|
||||
|
||||
recorder_draw_cursor (recorder, buffer);
|
||||
if (recorder->draw_cursor &&
|
||||
!g_settings_get_boolean (recorder->a11y_settings, MAGNIFIER_ACTIVE_KEY))
|
||||
recorder_draw_cursor (recorder, buffer);
|
||||
|
||||
shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer);
|
||||
gst_buffer_unref (buffer);
|
||||
@@ -593,7 +611,7 @@ recorder_on_stage_paint (ClutterActor *actor,
|
||||
{
|
||||
GdkRectangle primary_monitor;
|
||||
|
||||
gdk_screen_get_monitor_geometry (recorder->gdk_screen,
|
||||
gdk_screen_get_monitor_workarea (recorder->gdk_screen,
|
||||
gdk_screen_get_primary_monitor (recorder->gdk_screen),
|
||||
&primary_monitor);
|
||||
if (!recorder->only_paint)
|
||||
@@ -616,6 +634,14 @@ recorder_update_size (ShellRecorder *recorder)
|
||||
clutter_actor_get_allocation_box (CLUTTER_ACTOR (recorder->stage), &allocation);
|
||||
recorder->stage_width = (int)(0.5 + allocation.x2 - allocation.x1);
|
||||
recorder->stage_height = (int)(0.5 + allocation.y2 - allocation.y1);
|
||||
|
||||
if (!recorder->custom_area)
|
||||
{
|
||||
recorder->area.x = 0;
|
||||
recorder->area.y = 0;
|
||||
recorder->area.width = recorder->stage_width;
|
||||
recorder->area.height = recorder->stage_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1006,6 +1032,18 @@ recorder_set_file_template (ShellRecorder *recorder,
|
||||
g_object_notify (G_OBJECT (recorder), "file-template");
|
||||
}
|
||||
|
||||
static void
|
||||
recorder_set_draw_cursor (ShellRecorder *recorder,
|
||||
gboolean draw_cursor)
|
||||
{
|
||||
if (draw_cursor == recorder->draw_cursor)
|
||||
return;
|
||||
|
||||
recorder->draw_cursor = draw_cursor;
|
||||
|
||||
g_object_notify (G_OBJECT (recorder), "draw-cursor");
|
||||
}
|
||||
|
||||
static void
|
||||
shell_recorder_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -1028,6 +1066,9 @@ shell_recorder_set_property (GObject *object,
|
||||
case PROP_FILE_TEMPLATE:
|
||||
recorder_set_file_template (recorder, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_DRAW_CURSOR:
|
||||
recorder_set_draw_cursor (recorder, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -1056,6 +1097,9 @@ shell_recorder_get_property (GObject *object,
|
||||
case PROP_FILE_TEMPLATE:
|
||||
g_value_set_string (value, recorder->file_template);
|
||||
break;
|
||||
case PROP_DRAW_CURSOR:
|
||||
g_value_set_boolean (value, recorder->draw_cursor);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -1104,6 +1148,14 @@ shell_recorder_class_init (ShellRecorderClass *klass)
|
||||
"The filename template to use for output files",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DRAW_CURSOR,
|
||||
g_param_spec_boolean ("draw-cursor",
|
||||
"Draw Cursor",
|
||||
"Whether to record the cursor",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
/* Sets the GstCaps (video format, in this case) on the stream
|
||||
@@ -1126,8 +1178,8 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
||||
"bpp", G_TYPE_INT, 32,
|
||||
"depth", G_TYPE_INT, 24,
|
||||
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
|
||||
"width", G_TYPE_INT, pipeline->recorder->stage_width,
|
||||
"height", G_TYPE_INT, pipeline->recorder->stage_height,
|
||||
"width", G_TYPE_INT, pipeline->recorder->area.width,
|
||||
"height", G_TYPE_INT, pipeline->recorder->area.height,
|
||||
NULL);
|
||||
g_object_set (pipeline->src, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
@@ -1678,6 +1730,15 @@ shell_recorder_set_file_template (ShellRecorder *recorder,
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
shell_recorder_set_draw_cursor (ShellRecorder *recorder,
|
||||
gboolean draw_cursor)
|
||||
{
|
||||
g_return_if_fail (SHELL_IS_RECORDER (recorder));
|
||||
|
||||
recorder_set_draw_cursor (recorder, draw_cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_recorder_set_pipeline:
|
||||
* @recorder: the #ShellRecorder
|
||||
@@ -1705,9 +1766,35 @@ shell_recorder_set_pipeline (ShellRecorder *recorder,
|
||||
recorder_set_pipeline (recorder, pipeline);
|
||||
}
|
||||
|
||||
void
|
||||
shell_recorder_set_area (ShellRecorder *recorder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (SHELL_IS_RECORDER (recorder));
|
||||
|
||||
recorder->custom_area = TRUE;
|
||||
recorder->area.x = CLAMP (x, 0, recorder->stage_width);
|
||||
recorder->area.y = CLAMP (y, 0, recorder->stage_height);
|
||||
recorder->area.width = CLAMP (width,
|
||||
0, recorder->stage_width - recorder->area.x);
|
||||
recorder->area.height = CLAMP (height,
|
||||
0, recorder->stage_height - recorder->area.y);
|
||||
|
||||
/* This breaks the recording but tweaking the GStreamer pipeline a bit
|
||||
* might make it work, at least if the codec can handle a stream where
|
||||
* the frame size changes in the middle.
|
||||
*/
|
||||
if (recorder->current_pipeline)
|
||||
recorder_pipeline_set_caps (recorder->current_pipeline);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_recorder_record:
|
||||
* @recorder: the #ShellRecorder
|
||||
* @filename_used: (out) (allow-none): actual filename used for recording
|
||||
*
|
||||
* Starts recording, Starting the recording may fail if the output file
|
||||
* cannot be opened, or if the output stream cannot be created
|
||||
@@ -1724,7 +1811,8 @@ shell_recorder_set_pipeline (ShellRecorder *recorder,
|
||||
* Return value: %TRUE if recording was succesfully started
|
||||
*/
|
||||
gboolean
|
||||
shell_recorder_record (ShellRecorder *recorder)
|
||||
shell_recorder_record (ShellRecorder *recorder,
|
||||
char **filename_used)
|
||||
{
|
||||
g_return_val_if_fail (SHELL_IS_RECORDER (recorder), FALSE);
|
||||
g_return_val_if_fail (recorder->stage != NULL, FALSE);
|
||||
@@ -1733,6 +1821,9 @@ shell_recorder_record (ShellRecorder *recorder)
|
||||
if (!recorder_open_pipeline (recorder))
|
||||
return FALSE;
|
||||
|
||||
if (filename_used)
|
||||
*filename_used = g_strdup (recorder->current_pipeline->filename);
|
||||
|
||||
recorder_connect_stage_callbacks (recorder);
|
||||
|
||||
recorder->start_time = get_wall_time();
|
||||
|
@@ -36,7 +36,15 @@ void shell_recorder_set_file_template (ShellRecorder *recorder,
|
||||
const char *file_template);
|
||||
void shell_recorder_set_pipeline (ShellRecorder *recorder,
|
||||
const char *pipeline);
|
||||
gboolean shell_recorder_record (ShellRecorder *recorder);
|
||||
void shell_recorder_set_draw_cursor (ShellRecorder *recorder,
|
||||
gboolean draw_cursor);
|
||||
void shell_recorder_set_area (ShellRecorder *recorder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
gboolean shell_recorder_record (ShellRecorder *recorder,
|
||||
char **filename_used);
|
||||
void shell_recorder_close (ShellRecorder *recorder);
|
||||
void shell_recorder_pause (ShellRecorder *recorder);
|
||||
gboolean shell_recorder_is_recording (ShellRecorder *recorder);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user