Compare commits

..

157 Commits

Author SHA1 Message Date
Cédric Valmary
c64f195e96 Added Occitan translation 2015-05-16 07:17:17 +00:00
Daniel Mustieles
247546d531 Updated Spanish translation 2014-10-06 13:01:13 +02:00
Sam Friedmann
44252b052d Updated French translation 2014-04-07 10:53:41 +00:00
Simon McVittie
226032d2e1 Specifically ask for Telepathy 0.x
Telepathy 1.0 will not be compatible, and will probably require
source changes. telepathy-glib 0.12 and telepathy-logger 0.2 are
the 0.x ABIs (they were the first stable-branches to have g-i).

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=721704
Reviewed-by: Giovanni Campagna
2014-03-25 17:19:57 +00:00
Wylmer Wang
53f28074ad Updated Chinese (China) translation 2014-03-10 12:06:14 +00:00
Gil Forcada
2993e02c33 [l10n] Update Catalan translation 2014-02-21 23:26:26 +01:00
Ankit Patel
628bfc8311 Updated Gujarati translations 2014-02-03 17:51:19 +05:30
Shankar Prasad
27bfaf9b35 updated kn.po 2014-02-03 16:59:07 +05:30
A S Alam
e4e87d03c5 update translation for 3.8 branch 2014-02-01 17:03:08 -06:00
Wylmer Wang
956d89fbec Update Chinese simplified translation 2014-01-14 18:41:18 +08:00
Мирослав Николић
1ad62527ea Updated Serbian translation 2014-01-13 09:49:54 +01:00
Мирослав Николић
1d79d74e97 Updated Serbian translation 2014-01-13 09:24:04 +01:00
Christian Kirbach
b90183665f Updated German translation 2014-01-02 14:48:37 +01:00
Andika Triwidada
73fde364c8 Updated Indonesian translation 2013-12-30 13:38:18 +07:00
Marek Černocký
21b05e8150 Updated Czech translation 2013-12-30 00:03:09 +01:00
Marek Černocký
e8391a726d Updated Czech translation 2013-12-29 23:54:11 +01:00
Aurimas Černius
fb85a476a1 Updated Lithuanian translation 2013-12-21 16:32:53 +02:00
Andika Triwidada
047acb887e Updated Indonesian translation 2013-12-20 23:10:15 +07:00
Muhammet Kara
eaadeb8ef4 [l10n]Updated Turkish translation 2013-12-07 08:37:01 +02:00
Shantha kumar
03946a9621 Updated Tamil Translations 2013-11-11 14:56:49 +05:30
Florian Müllner
820f689f77 popupMenu: Fix removing the active menu from PopupMenuManager
Commit b42af9aa99 changed the parameter list of _closeMenu()
to account for changes in the GrabHelper ungrab mechanism, but
didn't update other callers.

https://bugzilla.gnome.org/show_bug.cgi?id=709806
2013-11-07 00:13:43 +01:00
Lasse Liehu
724f99cc62 Finnish translation update 2013-11-05 08:02:42 +02:00
Yuri Myasoedov
83125c4849 Updated Russian translation 2013-11-01 23:29:03 +04:00
Antonio Fernandes C. Neto
d8a1ce0871 Updated Brazilian Portuguese translation, proofread by Enrico Nicoletto 2013-10-30 23:35:03 -02:00
Мирослав Николић
e156e1a438 Updated Serbian translation 2013-10-25 22:31:28 +02:00
Stas Solovey
83f3084415 Updated Russian translation 2013-10-18 18:31:50 +04:00
Мирослав Николић
81e93d083e Updated Serbian translation 2013-10-15 19:56:50 +02:00
Мирослав Николић
542353b8d8 Updated Serbian translation 2013-10-15 19:50:28 +02:00
Balázs Úr
8868d3aa6d Updated Hungarian translation 2013-10-13 13:43:29 +02:00
Andika Triwidada
c419649fe7 Updated Indonesian translation 2013-10-08 17:10:12 +07:00
Aurimas Černius
130c726fff Updated Lithuanian translation 2013-10-05 16:49:08 +03:00
Adel Gadllah
ac478727cc layout: Use monitor index when adding bg managers
Don't assume that this._bgManagers.push() (i.e adding to the end) is always
correct.

On startup we call _createPrimaryBackground which passes in the primary index
which may not be 0.
2013-10-02 15:59:32 +02:00
Adel Gadllah
331c73002f background: Disconnect settings signal handler on destroy
We connect to the changed signal in _init() but never actually disconnect from
it. The callback has a reference to "this" which results into the background
object not getting garbage collected.

Fix that leaks by disconnecting in _destroy()

https://bugzilla.gnome.org/show_bug.cgi?id=709263
2013-10-02 15:44:57 +02:00
Marek Černocký
95a587e81b Updated Czech translation 2013-10-02 09:56:07 +02:00
Nilamdyuti Goswami
38a45b4f0f Assamese translation updated 2013-10-01 11:27:23 +05:30
Dimitris Spingos
c730cd3296 Updated Greek translation 2013-09-30 17:45:35 +03:00
Daniel Mustieles
c10a18ab71 Updated Spanish translation 2013-09-30 12:13:12 +02:00
Matej Urbančič
ca2f7597b4 Updated Slovenian translation 2013-09-28 21:31:19 +02:00
Fran Diéguez
3c70435969 Updated Galician translations 2013-09-28 16:26:41 +02:00
Adel Gadllah
0a1b9867fc Revert "background: fix asynchronous management of background loading operations"
This reverts commit 1020d8a0f8.

https://bugzilla.gnome.org/show_bug.cgi?id=704646
2013-08-16 14:52:22 +02:00
Giovanni Campagna
d8177a8f3b ScreenShield: don't allow events through the lock dialog
Make the lock dialog group reactive, to intercept any events
before they go to the actors below.
In the future, we may restructure our chrome to have a clear
layer system, but for now it fixes a security issue in the lock
screen (you can see the contents of the windows by dragging
if the screen was locked with the overview active)

https://bugzilla.gnome.org/show_bug.cgi?id=705840
2013-08-13 17:11:44 +02:00
Adel Gadllah
52417a8363 st-scroll-view: Unconditionally allocate scrollbars
Commit cfecd063c9 changed the allocation logic to not allocate
scrollbars when the *_visible booleans are false. This breaks the
fade effect as well as the NEVER policy. We do not paint scrollbars
when they are not supposed to be visible, so not allocating them
and thus leaving them in a "needs allocation" state just causes problems.

I am not convinced that it solved any problem to begin with (we don't paint
them anyway).

As the previous condition has basically always been true, just do it
unconditionally.

https://bugzilla.gnome.org/show_bug.cgi?id=705664
2013-08-11 18:19:56 +02:00
Inaki Larranaga Murgoitio
8191e10665 Updated Basque language 2013-08-05 10:24:19 +02:00
Adel Gadllah
a6f39a12d7 overview: Reset opacity when not animating
We are not resetting the opacity when we are not animating, which can cause
a hidden window to end up with opacity 0 if we remove the tween to early.
2013-08-04 11:38:40 +02:00
Ray Strode
79a42e097d Bump version to 3.8.4
Update NEWS.
2013-07-30 21:03:28 -04:00
Jasper St. Pierre
4a5e276551 messageTray: Ensure notifications are focused after they are expanded
If we focus notifications before they're expanded, the body and action
area won't be visible, and the can_focus members like the text entry
will not be able to be focused.

Ensure that all of the all actors that would be in an expanded notification
are visible before we attempt to focus them.

https://bugzilla.gnome.org/show_bug.cgi?id=698778
2013-07-30 18:38:21 -04:00
Giovanni Campagna
35abf39971 Background: don't require a URI scheme for picture-uri
Migration from old settings can result in a path instead of URI
there. This is technically invalid, but can easily recognize it
and avoid the crash.

Minor changes by Ray Strode

https://bugzilla.gnome.org/show_bug.cgi?id=702121
2013-07-30 18:31:25 -04:00
Jasper St. Pierre
c1d107a682 shell-app: Fade the app icon on the left in RTL layouts
The point of fading the icon is to make the text displayed over the
icon more legible. In RTL layouts, the text is displayed on the left
of the icon, so fading the right-hand-side of the icon doesn't work
well.

https://bugzilla.gnome.org/show_bug.cgi?id=704583
2013-07-30 18:20:54 -04:00
Giovanni Campagna
31f67d9142 MessageTray: don't list the sources all the time
The point of a hash table is that you don't need to list all the
elements. To avoid that, keep a "clearableCount" in MessageTray,
which can be used by the message tray menu to show and hide the
clear item, and that is updated in constant time when sources
are added or removed.

https://bugzilla.gnome.org/show_bug.cgi?id=700194
2013-07-30 18:13:17 -04:00
Giovanni Campagna
3a0197c8db Hash: make .size() constant time
MessageTray calls .size() very often to update the no messages label,
so a linear time implementation is not good enough.

https://bugzilla.gnome.org/show_bug.cgi?id=700194
2013-07-30 18:12:25 -04:00
Jasper St. Pierre
c4f744d7ec overview: Don't allow exiting the overview if we have a DND drag
Otherwise, people can drag app icons or window thumbnails out of
the overview, and it just looks weird.

https://bugzilla.gnome.org/show_bug.cgi?id=698484
2013-07-30 18:11:14 -04:00
Alban Browaeys
61b1679719 st-icon: check if gicon is null before unref.
Commit a6b49fe7d6
introduced a check for equality of priv->gicon vs gicon
and unref then return early if so. But if both are null,
we should not unref gicon. Only return.

https://bugzilla.gnome.org/show_bug.cgi?id=698863
2013-07-30 18:00:15 -04:00
Emilio Pozuelo Monfort
cdbb1bb665 st-scroll-view: properly check if the scrollbars are visible
We don't set :visible on the scrollbars, but use booleans to track
if they are visible. Thus check the booleans instead of the actor's
properties when allocating the scrollbars.

https://bugzilla.gnome.org/show_bug.cgi?id=704265
2013-07-17 17:31:04 +02:00
Lionel Landwerlin
1020d8a0f8 background: fix asynchronous management of background loading operations
This fixes a blue background being drawn when switching the monitors
configuration using hardware keys
(clone/multimonitor/external/internal).

The problem is that the shell gather all background loading requests
under the same meta_background_load_file_async call using one
GCancellable (the first one to come). So when the shell receives a
batch of 12 or so XRandr events, it creates 12 new background managers
which end up trying to load 12 times the same background picture. All
of these requests are batched into the same
meta_background_load_file_async using the first GCancellable received
on the first request. Unfortunately, when the first request is
cancelled by the following event indicating a new monitor setup, all
of the background picture requests are dropped on the floor, and
nothing gets loaded (hence the blue screen background).

https://bugzilla.gnome.org/show_bug.cgi?id=703001
2013-07-03 17:05:30 +01:00
Matthias Clasen
1f6811ca06 Make autorun notifications work
The code that checks for various conditions is confusing and
undercommented. It appears one of the recent refactorings
inadvertedly inverted the sense of the 'hidden mountpoint'
check, and caused autorun to not work for anything that does
not have a 'native root' - which is pretty much all volumes
implemented by gvfs.

https://bugzilla.gnome.org/show_bug.cgi?id=703418
2013-07-01 21:48:19 -04:00
Emilio Pozuelo Monfort
c256154190 boxpointer: fix left/right arrow side calculation
Commit d6cace32 introduced a typo in the left/right arrow side
calculation code that causes in most scenarios (where the monitor
width is greater then the height) to not flip the box when it doesn't
fit inside the monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=703403
2013-07-01 18:54:05 +02:00
Lionel Landwerlin
60225ef86d screenShield: fix empty screen shield
If the drag action ends after something else has put the screen shield
into a different state we can end up in an inconsistent screen shield
state where the whole thing is empty.

https://bugzilla.gnome.org/show_bug.cgi?id=703126
2013-06-27 11:19:15 +01:00
Carlos Soriano
48498d83d3 telepathyClient: Align timestamps to the right again
Commit 3de0ebf changed timestamps to be center-aligned. New
design updates change this, so revert it.

http://bugzilla.gnome.org/show_bug.cgi?id=687809
2013-06-26 15:55:24 +02:00
Carlos Soriano
14757dbd6c telepathyClient: Increase the timestamp timeout to 3 minutes
The timestamp timeout specifies how long we should wait before
adding a timestamp to the notification. A timeout of one minute
ended up showing a lot of timestamps, so increase it to 3 minutes.

https://bugzilla.gnome.org/show_bug.cgi?id=687809
2013-06-26 15:55:02 +02:00
Florian Müllner
df89d4dc59 layout: Keep the top_window group above newly added chrome
The top_window_group was introduced for popup windows that should
appear above system chrome, but as the group itself is just a child
of Main.uiGroup, chrome that is added after top_window_group will
still be stacked on top.
At least correct the stacking for actors added via addChrome().

https://bugzilla.gnome.org/show_bug.cgi?id=702338
2013-06-26 13:39:18 +02:00
Florian Müllner
ace549c1bf st: Be more forgiving when calling get_theme_node() on unstaged widgets
While it is obviously still an error to call get_theme_node() on a
widget that hasn't been added to the stage hierarchy yet, asserting
on it hasn't proven too successful in avoiding those errors - it's
likely the most frequent reason for crash reports. Just accept that
there'll always be code paths where we can hit this case and make
it non-fatal.

https://bugzilla.gnome.org/show_bug.cgi?id=610279
2013-06-24 23:07:50 +02:00
Mathieu Bridon
1198ffd297 gdm: Align the "Not Listed?" label
https://bugzilla.gnome.org/show_bug.cgi?id=702307
2013-06-24 13:28:29 +02:00
Adel Gadllah
1aac5c43e4 Fix syntax error 2013-06-18 23:01:26 +02:00
Adel Gadllah
4d785d249f osdWindow: Don't call enable_unredirection on startup
This is wrong because it is already enabled. So move this
to out of reset, which gets called from _init().
2013-06-18 22:46:33 +02:00
Jonh Wendell
efbf102b63 gdm: clear the messages queue when the user answers a prompt
the messages were being shown even when the user entered the
right information they were asked for.

https://bugzilla.gnome.org/show_bug.cgi?id=702458
2013-06-18 11:56:33 -03:00
Matthias Clasen
4d1668b01c logout dialog: Show the correct text right away
The end session dialog was waiting a second before updating
its text to display the timer. It is nicer to show the correct
message from the start.

https://bugzilla.gnome.org/show_bug.cgi?id=702056
2013-06-12 05:49:00 -04:00
Florian Müllner
cad6f31c1a Bump version to 3.8.3
Update NEWS.
2013-06-07 21:46:20 +02:00
Florian Müllner
294f59103f window-switcher: Only show windows from current workspace by default
When adding the window switcher, we copied our default values from
the alternate-tab extension. Arguably it makes more sense to mimick
the old mutter/metacity behavior though, so change the default
accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=701214
2013-06-07 21:34:01 +02:00
Adel Gadllah
f88f51dd99 osdWindow: Disable unredirection while showing the OSD
This allows OSDs to be visible even when displayed on top
of unredirected windows.

https://bugzilla.gnome.org/show_bug.cgi?id=701224
2013-06-07 21:22:03 +02:00
Xavier Claessens
c1eaf97bc6 RemoteMenu: Avoid useless signal connections
If we are missing more than one action, every time action-added is
called, it calls modelChanged() again and re-connect signal for
all action still missing. This patch prevent from connecting signals
again when doing a refresh because a missing action is now available.
All necessary signals have already been connected.

https://bugzilla.gnome.org/show_bug.cgi?id=694612
2013-06-07 20:08:37 +02:00
Xavier Claessens
1420f62dfa RemoteMenu: use detailed action-added signal
This avoid disconnecting all signals if we are waiting for
different actions to be added, leading to incomplete menu.
Previously if we were waiting for 2 different actions in 2
different sections, the first action-added signal would
disconnect the 2nd signal handler as well, so the model of
that section would not be updated when the 2nd action is added.

https://bugzilla.gnome.org/show_bug.cgi?id=694612
2013-06-07 20:08:37 +02:00
Florian Müllner
3ff194247a main: Use the correct schema for 'dynamic-workspaces'
We currently monitor the shell's override schema for changes to
the 'dynamic-workspaces' key, which ends up being the wrong
schema in classic mode. With the new ability to use mode-specific
overides, we can finally fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=701717
2013-06-07 19:59:41 +02:00
Florian Müllner
36b1cd13c9 main: Pick up overridesSchema from sessionMode
This will allow the use of mode-specific defaults. For classic mode
we currently implement this with mini-extensions, but this may result
in confusing behavior when settings change due to extensions being
disabled during screen locks (not to mention that those mini-extensions
are hardly an elegant approach).

https://bugzilla.gnome.org/show_bug.cgi?id=701717
2013-06-07 19:59:39 +02:00
Florian Müllner
bcede26d77 main: Move pref overrides to JS
We will allow to use mode-specific overrides; in preparation for that,
move the code so that we only override preferences after initializing
the session mode.

https://bugzilla.gnome.org/show_bug.cgi?id=701717
2013-06-07 19:58:52 +02:00
eternalhui
fbf1ee8a01 update Simplified Chinese (zh_CN) translation 2013-06-06 11:44:18 +08:00
Florian Müllner
1360747c9e dnd: Use pushModal() to grab the keyboard
Currently we "only" grab the keyboard when starting a drag operation,
which does not impede keybindings to be processed. This is at best
not harmful (like workspace switching), but may have unintended effects
otherwise - for instance, the hot corner is disabled, so having the
corresponding keyboard shortcut still active is fairly odd (not to
mention that it leaves the system in a confused state).
Fix this by switching to pushModal()/popModal(), which will push a
dedicated keybinding mode for us.

https://bugzilla.gnome.org/show_bug.cgi?id=700877
2013-06-05 16:36:23 +02:00
Florian Müllner
1d95841da0 screenShield: Clear clipboard on lock
Currently the clipboard's contents may leak to unauthorized parties by
pasting into the unlock dialog's password entry and unmasking the entry.
Prevent this from happening by clearing the clipboard on lock.

https://bugzilla.gnome.org/show_bug.cgi?id=698922
2013-06-05 16:23:52 +02:00
Rui Matos
494fcfecf8 osdWindow: Make sure the OSD is always our topmost chrome element
In particular this fixes the OSD showing up behind a modal dialog's
lightbox.

https://bugzilla.gnome.org/show_bug.cgi?id=701269
2013-06-05 15:36:12 +02:00
Florian Müllner
75705b45ef dash: Grow the empty dash during drag operations
When the dash does not contain any applications (either favorites
or running), it is currently impossable to add a favorite via DND.
Grow the dash slightly in that case to provide a drop target.

https://bugzilla.gnome.org/show_bug.cgi?id=684618
2013-06-05 14:54:45 +02:00
Florian Müllner
1ad1e48741 dash: Minor cleanup
https://bugzilla.gnome.org/show_bug.cgi?id=684618
2013-06-05 14:54:45 +02:00
Florian Müllner
ddb682e4fe dash: Use a single code path for clearing the drag placeholder
We currently only keep track of old placeholders when moving past
the dragged app's current favorite position, as this is the only
case where we need to worry about jitter. Still, moving it into
_clearDragPlaceholder() allows us to consolidate code paths, which
is a good thing ...

https://bugzilla.gnome.org/show_bug.cgi?id=684618
2013-06-05 14:54:45 +02:00
Florian Müllner
5216b77600 dash: Make sure _clearDragPlaceholder() resets _dragPlaceholderPos
The function currently only resets the placeholder position if
there is a placeholder; this is not necessarily true, as the
placeholder may be reset outside _clearDragPlaceholder().
If this happens, the placeholder will temporarily stop working
for the "old" position (and permanently if it's the only position).
Just reset the position unconditionally.

https://bugzilla.gnome.org/show_bug.cgi?id=684618
2013-06-05 14:28:25 +02:00
Cheng-Chia Tseng
c93d91d80b Updated Traditional Chinese translation(Hong Kong and Taiwan) 2013-06-04 21:50:40 +08:00
Carlos Soriano
f9e3467b70 appDisplay: Give more horizontal space to control buttons
Before, the text of those buttons were truncated when the text exceeded
the fixed width we had in the CSS.
Now, we give more horizontal space to the control buttons to match
the maximum text length of all buttons.

https://bugzilla.gnome.org/show_bug.cgi?id=696307
2013-06-04 13:53:42 +02:00
Florian Müllner
13bea1a01b Bump gvc submodule
As of commit 95a1b874d8, the submodule is supposed to be at
revision 3d6aac673b88ff, but commit 31774a7711 accidentally
reverted it back to the previously used revision.
2013-05-31 20:50:42 +02:00
Florian Müllner
76c930e471 build: Bump gcr requirement
https://bugzilla.gnome.org/show_bug.cgi?id=700972
2013-05-31 20:44:13 +02:00
Adel Gadllah
9f6cd75170 shell-gtk-embed: Lower tray icon windows to the bottom of the stack
Otherwise they break the "top level window" detection used by the
unredirect code in mutter, causes game windows not to be unredirected
when tray icons are present.

https://bugzilla.gnome.org/show_bug.cgi?id=701224
2013-05-30 00:59:11 +02:00
Adel Gadllah
c107882828 xdnd: Lower window activation timeout
The current one is perceived as too high by users, so try a shorter timeout.

https://bugzilla.gnome.org/show_bug.cgi?id=700150
2013-05-29 22:06:32 +02:00
Giovanni Campagna
d18e084cd5 Keyboard: clear currentSource after destruction
StLabel doesn't like that we set its properties after destructions,
and this would happen in currentInputSourceChanged() at the end,
when setting the ornament.
2013-05-25 20:39:33 +02:00
Rui Matos
2eb779740c messageTray: Check if the clicked summary item has a right click menu
Commit e71129aa68 introduced the
possibility of having summary items without a right click menu so we
should check for one before trying to show it.

https://bugzilla.gnome.org/show_bug.cgi?id=700190
2013-05-24 23:57:47 +02:00
Rui Matos
3ce20568d0 status/keyboard: Allow switching input source in the message tray
We still can't show a popup switcher in the message tray but we can at
least degrade gracefully and advance to the next input source.

https://bugzilla.gnome.org/show_bug.cgi?id=697009
2013-05-24 23:57:47 +02:00
Rui Matos
d45ab6f15e status/keyboard: Switch input source on special modifiers accelerator
This simply mimics the X server's layout switching behavior by
advancing to the next input source and wrapping around.

https://bugzilla.gnome.org/show_bug.cgi?id=697008
2013-05-24 23:57:47 +02:00
Rui Matos
cd7197e605 status/keyboard: Synchronize input source switching with key events
Currently we simply set the gsettings key when activating an input
source. This obviously introduces a time window, between the event that
activates the switch and when the switch is complete, under which key
events are being delivered to applications and interpreted according
to the previous input source.

The patches in bug 696996 introduce a DBus API in g-s-d that allows us
to know when an input source if effectively active. Using that and
freezing keyboard events in the X server until we hear back from g-s-d
we can ensure that events won't be misinterpreted after an input
source switch.

https://bugzilla.gnome.org/show_bug.cgi?id=697007
2013-05-24 23:57:47 +02:00
Stef Walter
3f6c1aadef Depend on gcr-base instead of gcr pkg-config file
gnome-shell does not use the UI bits of the Gcr library

https://bugzilla.gnome.org/show_bug.cgi?id=700944
2013-05-24 11:18:17 +02:00
Florian Müllner
29e8290b65 docs: Include ShellKeyBindingMode in docs
https://bugzilla.gnome.org/show_bug.cgi?id=700900
2013-05-23 17:10:37 +02:00
Florian Müllner
3074e48405 popupMenu: Allow for an optional border for slider handle
While the default style works well will a solid handle, using both
border and fill color would be desirable in classic mode. Add the
necessary (optional) style properties to allow this.

https://bugzilla.gnome.org/show_bug.cgi?id=697917
2013-05-22 18:47:37 +02:00
Florian Müllner
12c2939b64 screenshot: Hide cursor while magnifier is active
As with the screen recorder, the magnifier already adds its own
copy of the system cursor, so we should not add it again. Just
as in the screen recorder case, we don't address the case where
the cursor should not be included in the screenshot, but the
magnifier adds it anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=700488
2013-05-22 18:34:45 +02:00
Florian Müllner
c7eed59562 recorder: Hide cursor while magnifier is active
The magnifier adds its own copy of the system cursor to apply the
expected transformations, so we don't need to add it again in the
recorder; this avoids two different cursors showing up in recordings,
but doesn't address the case where the cursor should not be recorded
at all, but the magnifier adds it anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=700488
2013-05-22 18:34:45 +02:00
Florian Müllner
73903400c5 screencast: Fix return value in case of invalid file template
If we are passed an invalid file template, ShellRecorder.record()
will return a %NULL filename; as the Screencast DBus interface
expects a string return value, we cannot return the value unmodified
in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=700842
2013-05-22 17:24:04 +02:00
Rui Matos
dc7cc9b517 userWidget: Fix leaking instances
UserWidget instances should be destroyed when the actor is. That's
what consumer code expects since the destroy() method is never called.

https://bugzilla.gnome.org/show_bug.cgi?id=700807
2013-05-21 21:55:21 +02:00
Florian Müllner
b18c239240 appDisplay: Also account for folder popup's close buttons
As the close button of folder popups overlaps at the top, it ends
up being cut off if the folder is located at the very top of the
view. Fix this glitch by taking the button's overlap into account
in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=694371
2013-05-20 18:21:16 +02:00
Florian Müllner
3c66f1a4d9 appDisplay: Fix cut-off folders in All view
We already take care of growing the view if open folders overlap
at the bottom, however folder popups may still end up being cut
off when opening above the source icon - if the popup is high enough,
its y coordinate will be negative and therefore outside the parent's
allocation. To fix, we can either make sure that folders pop up below
their source icon in that case, or adjust the parent grid's position
as necessary while a folder is open. This implements the latter.

https://bugzilla.gnome.org/show_bug.cgi?id=694371
2013-05-20 18:21:16 +02:00
Florian Müllner
1dff5fb5b2 appDisplay: Expand AllView
If the view doesn't fill the available space, content should still
start at the top rather than the center - not least the positioning
code for folder popups assumes that, so set the appropriate expand
flags.

https://bugzilla.gnome.org/show_bug.cgi?id=694371
2013-05-20 18:21:16 +02:00
Allan Day
e2561d15b5 theme: polish the session chooser
The session chooser list has an embedded look which doesn't fit
well with the rest of the theme. Give it more of a flat appearance
and simplify the visuals.
https://bugzilla.gnome.org/show_bug.cgi?id=695742
2013-05-19 15:25:58 -04:00
Florian Müllner
326c3732b8 screenshot: Check for NULL window in screenshot_window()
screenshot_window() currently assumes a focus window, which will
result in a crash if that's not the case.

https://bugzilla.gnome.org/show_bug.cgi?id=700625
2013-05-19 15:32:56 +02:00
Florian Müllner
5dd020f2e2 recorder: Use workarea to position the recording icon
It looks a bit unpolished to overlap our own chrome with the recording
icon, which may happen when an existing adds UI at the bottom edge.
Fix this by using the primary monitor's workarea for the position rather
than the entire monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=700409
2013-05-18 14:30:16 +02:00
Florian Müllner
b6edbd46b9 overview: Add focusSearch() method and export it over DBus
Some keyboard spot a dedicated search key, which gnome-settings-daemon
currently handles by spawning gnome-search-tool. It makes a lot of
sense to promote the Shell's integrated search feature instead, so
expose an appropriate DBus method g-s-d can use.

https://bugzilla.gnome.org/show_bug.cgi?id=700536
2013-05-17 18:28:47 +02:00
Matthias Clasen
c330036fef Document --clutter-display in the man page
This is the sole option that was missing from the
man page.

https://bugzilla.gnome.org/show_bug.cgi?id=700339
2013-05-16 18:45:25 -04:00
Florian Müllner
d0a864b9b9 windowManager: Enable switch-to-workspace-n keybindings in overview
Those keybindings are unassigned by default, but that's not a valid
reason they shouldn't work like the related switch-up/down bindings.

https://bugzilla.gnome.org/show_bug.cgi?id=649977
2013-05-16 00:41:17 +02:00
Florian Müllner
9bed5b725e network: Fix stupid typo
There is no ACTIVE state in NetworkManager.ActionConnectionState,
it's ACTIVATED.

https://bugzilla.gnome.org/show_bug.cgi?id=700394
2013-05-15 17:48:21 +02:00
Florian Müllner
f374ecfc75 altTab: Always activate MRU window when activating an app
Commit 2499f2ed80 went back to using shell_app_activate() for
selecting an app, which favors windows on the current workspace;
this is the behavior we want for instance when activating a
launcher, but it's wrong for the alt-tab list - explicitly
request the first (e.g. MRU) window in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=700356
2013-05-15 12:13:41 +02:00
Florian Müllner
dd8ca02425 PopupMenuManager: Fix child menus
Since commit c84dc6254d, popup menus are closed automatically
when another menu opens (to catch the case where a menu is opened
by keyboard shortcut, which wasn't handled before). However in the
case of child menus, both child and parent are expected to be visible,
so handle this case explicitly.

https://bugzilla.gnome.org/show_bug.cgi?id=699678
2013-05-14 19:09:09 +02:00
Florian Müllner
ff3f9bdd7d volume: Adjust to icon name changes
The headphone icon gained an audio- prefix, use that instead of
the old name.
2013-05-14 14:28:34 +02:00
Florian Müllner
fab02ae82f Bump version to 3.8.2
Update NEWS.
2013-05-14 01:33:19 +02:00
Rui Matos
d43c5ec27a shellEntry: Set the input-purpose property for password entries
This way input methods can disable themselves automatically for
entries holding passwords.

https://bugzilla.gnome.org/show_bug.cgi?id=700043
2013-05-14 00:40:27 +02:00
Daiki Ueno
f7de35b852 st-entry: add input purpose and hints
Add input-purpose and input-hints properties to StEntry,
and pass these on to StIMText.

https://bugzilla.gnome.org/show_bug.cgi?id=691392
2013-05-14 00:40:18 +02:00
Daiki Ueno
cde0045851 st-im-text: add input purpose and hints
Add input-purpose and input-hints properties to StIMText,
and pass these on to GtkIMContext.

https://bugzilla.gnome.org/show_bug.cgi?id=691392
2013-05-14 00:40:15 +02:00
Daiki Ueno
f844613292 st-im-text: remove undefined st_im_text_set_autoshow_im decl
https://bugzilla.gnome.org/show_bug.cgi?id=691392
2013-05-14 00:40:11 +02:00
Rui Matos
ff2e44de53 status/keyboard: Stop destroying the IBusBus object
This is a singleton object inside libibus which means that if we
destroy it (e.g. because ibus-daemon got restarted) then, other
library users, like the ibus gtk+ IM module that we also use
in-process, will break.

https://bugzilla.gnome.org/show_bug.cgi?id=699189
2013-05-14 00:34:55 +02:00
Stef Walter
17aa8e0488 polkitAgent: Allow retrying mistyped passwords
Don't hide the polkit agent window when someone mistypes their password.
Allow them to try again. The user can cancel at any point.

https://bugzilla.gnome.org/show_bug.cgi?id=684431
2013-05-13 20:08:34 +02:00
Florian Müllner
a33df9b046 appDisplay: Implement folder keynav and shortcuts
When opening an application folder, it should take key focus to
allow for keynav; also, Escape closing both folder and app picker
is unexpected, it should only close the popup.

https://bugzilla.gnome.org/show_bug.cgi?id=695314
2013-05-13 19:46:16 +02:00
Kjartan Maraas
c25f399f7c Updated Norwegian bokmål translation 2013-05-13 09:48:12 +02:00
Giovanni Campagna
bd47d07fbc ScreenShield: clear the lock screen early when deactivating
Upon popMode, MessageTray will try readding all notifications
to their rightful parent, so we must tell NotificationBox to
relinquish them before st_bin_set_child() fails (leaving a dangling
child pointer and crashing at the next allocation)

https://bugzilla.gnome.org/show_bug.cgi?id=698812
2013-05-12 20:20:36 +02:00
Florian Müllner
72282237e1 data: Fix typo in Screencast docs 2013-05-10 23:44:14 +02:00
Florian Müllner
dfb44aa51d Expose screencast functionality via DBus
Like screenshots, the screen recorder can be a useful tool in other cases
than being triggered by a keyboard shortcut. To account for that, export
a Screencast DBus API similar to the existing Screenshot interface.

https://bugzilla.gnome.org/show_bug.cgi?id=696247
2013-05-10 19:49:41 +02:00
Florian Müllner
5516cad087 sessionMode: Add 'allowScreencast' property
Our built-in screen recorder is implemented as a component, so it will
just be disabled when the session mode doesn't allow screencasting.
However we will expose screencasting functionality on DBus as well, and
while it makes sense to restrict its availablity to the same modes as
the existing recorder, exporting/unexporting the service depending on
the session mode is not very consumer friendly.
For that reason, add an additional 'allowScreencast' property that for now
mirrors the availability of the 'recorder' component.

https://bugzilla.gnome.org/show_bug.cgi?id=696247
2013-05-10 19:49:41 +02:00
Florian Müllner
ab60c31629 shell-recorder: Make drawing the cursor optional
As with screenshots, showing the cursor in a recording may not be
desirable, so add a property to control whether the cursor is drawn
or not.

https://bugzilla.gnome.org/show_bug.cgi?id=696247
2013-05-10 19:49:41 +02:00
Florian Müllner
52dd030087 shell-recorder: Support specifying the recorded area
Currently we will always record the entire screen. It has been requested
to support recording a specified area analogous to the screenshot API as
well, so add a set_area() method which allows this.

https://bugzilla.gnome.org/show_bug.cgi?id=696247
2013-05-10 19:49:41 +02:00
Florian Müllner
98240c2857 shell-recorder: Optionally return the filename of the recording
It is currently not always possible to predict the actual output filename
of a recording - the file-template does not necessarily use an absolute
path and may contain %d and %t escape sequences.
This is OK for fire-and-forget uses like the existing keyboard shortcut,
but we will soon expose the functionality on DBus and consumers of that
API might very well need to access the file after the recording. So do
the same as our screenshot API and add an optional (out) parameter to
record().

https://bugzilla.gnome.org/show_bug.cgi?id=696247
2013-05-10 19:49:41 +02:00
Simon McVittie
65bfd6c6d2 Don't put non-Shell windows in Ctrl+Alt+Tab if they wouldn't be visible
Metacity's Ctrl+Alt+Tab would include X11 windows
with hints like GDK_WINDOW_TYPE_HINT_DOCK and
GDK_WINDOW_TYPE_HINT_DESKTOP (there are more conditions, but that's a
good start). If we're in normal mode, those are visible and it's OK
to display those in the Ctrl+Alt+Tab order, but if we're in the lock
screen or the unlock dialog, they're not visible and it doesn't make
sense to focus them.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=699862
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: Florian Müllner <fmuellner@gnome.org>
2013-05-09 19:31:08 +01:00
Stef Walter
1034e33c35 modalDialog: Show spinner when working
Use the same UI concept from the login screen to show spinners when
the polkit or keyring dialogs are working

https://bugzilla.gnome.org/show_bug.cgi?id=684438
2013-05-09 06:41:07 +02:00
Stef Walter
d7528b878c components: Allow cancelling of dialog between prompts
Some callers of the keyring prompt keep the dialog up while
processing the prompt. Allow the user to cancel the prompt
while in this state.

This is propagated to the caller, who can cancel the operation
in question when this occurs.

https://bugzilla.gnome.org/show_bug.cgi?id=682830
2013-05-09 05:55:15 +02:00
Giovanni Campagna
eb2e66c539 network: don't use active connections that are in invalid states
Only ACTIVE or ACTIVATING connections are important when deciding
what icon to show, don't fallback on any, possibly invalid or deactivating,
active connection object.

https://bugzilla.gnome.org/show_bug.cgi?id=676285
2013-05-09 00:05:36 +02:00
Stef Walter
30e9a2a7d0 keyring: Fix button disabled when prompting for confirmation
https://bugzilla.gnome.org/show_bug.cgi?id=696304
2013-05-08 22:13:56 +02:00
Lionel Landwerlin
e842694316 st-shadow: Fix offset shadow offscreen rendering
The shadows are currently rendered by painting the actor we want to
apply shadow on, in an offscreen buffer. The problem is that when this
actor has an allocation padding (ie allocation that isn't at 0x0
relatively to its parent), this padding is added within the offscreen
buffer and as a result the shadow rendering is truncated because the
offscreen buffer size is the size of the allocation box, not the
allocation box + padding.

This patch reposition the actor at 0x0 with rendering it by changing
the initial transformation matrix when rendering the actor offscreen.

https://bugzilla.gnome.org/show_bug.cgi?id=698301
2013-05-08 16:16:07 +01:00
Florian Müllner
b33d87a762 loginDialog: Adjust logoBin to modalDialog changes
With modalDialogs' backgroundStack using a BinLayout now, we need
to set approriate expand flags on the iconBin.

https://bugzilla.gnome.org/show_bug.cgi?id=699877
2013-05-08 00:09:53 +02:00
Florian Müllner
0ff3599d91 modalDialog: Replace Shell.Stack with layout manager
Commit e98eb57e3e added flags to expand the dialog's background
stack, which works fine with the current clutter-1.16 branch, but
breaks on clutter-1.14 (as shipped with GNOME 3.8).
Using an St.Widget with a Clutter.BinLayout fixes this, and is more
modern Clutter usage.

https://bugzilla.gnome.org/show_bug.cgi?id=699877
2013-05-08 00:09:53 +02:00
Marta Milakovic
28d79a1235 osdWindow: Allow popup to grow if necessary
The popup currently has a fixed size based on monitor size. As a result,
the popup's content may overflow if its minimum size is larger than the
popup size. To prevent this, use min-width/min-height for the popup size
so that the popup can grow if necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=696523
2013-05-07 21:35:47 +02:00
Florian Müllner
522d21154b loginDialog: Remove logo in upper left corner
With optional branding now being shown below the user list, we can
remove the unloved instance in the upper left corner ...

https://bugzilla.gnome.org/show_bug.cgi?id=694912
2013-05-07 20:52:04 +02:00
Florian Müllner
7c231916c1 loginDialog: (Optionally) show logo below user list
The optional logo on the login screen is currently shown in the
top bar, which is not only a rather unprominent position, it also
gives the wrong suggestion of a clickable element.
Newer designs call for the logo to be shown horizontally centered
at the bottom of the screen, so implement that instead.

https://bugzilla.gnome.org/show_bug.cgi?id=694912
2013-05-07 20:52:04 +02:00
Florian Müllner
a40bb67fc6 modalDialog: Always use a stack for the background
Currently a system modal dialog's actor hierarchy depends on whether
events should be blocked while the dialog is shown or not. Change
it to always contain a stack, to allow subclasses to add additional
background elements.

https://bugzilla.gnome.org/show_bug.cgi?id=694912
2013-05-07 20:52:04 +02:00
Lionel Landwerlin
4c350b90c7 dateMenu: do not show "Open Calendar" button with no installed calendar application
https://bugzilla.gnome.org/show_bug.cgi?id=697725
2013-05-06 15:59:17 +01:00
Stef Walter
47dee22b05 gdm: Fix regression where domain login hint not shown
Also only keep around realmd while we're actually using it, allow it
to quit if no other clients are active.

https://bugzilla.gnome.org/show_bug.cgi?id=698200
2013-05-03 21:55:45 +02:00
Matthias Clasen
13c0e575f6 ctrlAltTab: Use a symbolic icon for desktop windows
The nautilus icon sticks out pretty badly among the symbolic
icons we use for other desktop components. This commit finds
windows of type DESKTOP, and uses the video-display-symbolic
icon for them.
https://bugzilla.gnome.org/show_bug.cgi?id=697914
2013-05-03 10:27:01 -04:00
Tim Lunn
ea8736b13a AppMenuButton: Improve handling of signals
If for some reason an extension needs to destroy the AppMenu object,
currently it is not possible to do this cleanly due to these signals
remaining connected.

https://bugzilla.gnome.org/show_bug.cgi?id=698531
2013-05-01 18:33:31 +10:00
Giovanni Campagna
303d53e7f5 StIcon: use g_signal_connect_object() for safety
Prevent a crash in case an icon is destroyed before the texture
finishes loading, and something else is keeping the texture alive
for any reason.

https://bugzilla.gnome.org/show_bug.cgi?id=696720
2013-04-29 00:26:51 +02:00
Žygimantas Beručka
31295dfe83 Updated Lithuanian translation 2013-04-28 13:36:38 +03:00
Tim Lunn
69ea4553cb dateMenu: append .desktop to evolution strings
Since that is what the actual app_id's are.
2013-04-27 08:32:23 +10:00
Florian Müllner
0d8d77356e PopupMenuManager: Close active menu when another one opens
We already do this when navigating between menus via mouse or
keynav, but miss cases where a menu is opened by other means,
for instance via a keyboard shortcut.

https://bugzilla.gnome.org/show_bug.cgi?id=686756
2013-04-26 18:16:14 +02:00
Florian Müllner
8b78032248 panel: Change openAppMenu() to a toggle action
It makes sense to allow closing the app menu with the same shortcut
that is used to open it, so make it a toggle action and allow it
TOPBAR_POPUP mode.

https://bugzilla.gnome.org/show_bug.cgi?id=686756
2013-04-26 18:16:13 +02:00
Florian Müllner
ad277a563c panel: Add keybinding mode for top bar popups and use it
Allow some keybindings to still work while a top bar menu is open
by assigning it a keybinding mode.

https://bugzilla.gnome.org/show_bug.cgi?id=698938
2013-04-26 18:16:13 +02:00
Florian Müllner
db26fb201e popupMenu: Allow setting grabHelper params for PopupMenuManager
Currently all keybindings are disabled while some popup menu is open.
However some keybindings may still be useful in some cases, so expose
GrabHelper's modal params parameter to allow specifying a keybinding
mode for particular menus.

https://bugzilla.gnome.org/show_bug.cgi?id=698938
2013-04-26 18:16:13 +02:00
Florian Müllner
9f00be50d6 shellDBus: Fix Eval() return value when disabled
Eval() is expected to return a boolean success value and a string result.
However when the function is disabled (via the development-tools setting),
we return null for the latter which is not a valid string value.
Return an empty string instead.

https://bugzilla.gnome.org/show_bug.cgi?id=698959
2013-04-26 18:16:12 +02:00
Jasper St. Pierre
77d21e53d0 backgroundMenu: Ignore releases when using long-press
Otherwise, a release from the long-press will be seen as a
button event that should close the menu.

https://bugzilla.gnome.org/show_bug.cgi?id=697203
2013-04-26 11:24:30 -04:00
Jasper St. Pierre
ba0b4ba590 layout: Correct hot corner barriers in RTL layouts
https://bugzilla.gnome.org/show_bug.cgi?id=698884
2013-04-26 11:24:25 -04:00
Nik Kalach
b9fc7a3050 [l10n] Add Interlingua translation 2013-04-24 15:52:53 +02:00
Muhammet Kara
aa053a906d [l10n] Updated Turkish translation 2013-04-20 00:48:22 +03:00
112 changed files with 11079 additions and 10266 deletions

102
NEWS
View File

@@ -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] * Fix hotcorner regression in RTL locales [Jasper; #698884]
* Allow some keybindings to work while a top bar menu is open [Florian; #698938] * Allow some keybindings to work while a top bar menu is open [Florian; #698938]
* Make open-app-menu keybinding a toggle action [Florian; #686756] * Make open-app-menu keybinding a toggle action [Florian; #686756]
* Only recognize common URL schemes in notification messages [Monica; #661225] * ctrlAltTab: Use symbolic icons for desktop windows [Matthias; #697914]
* Misc fixes and cleanups [Tim, Jasper, Florian, Giovanni, Owen; #698531, * gdm: Fix regression where domain login hint not shown [Stef; #698200]
#698622, #698427, #698483, #698513, #697203, #698959, #698918, #699029, * Hide "Open Calendar" item when no calendar app is installed [Lionel; #697725]
#699075, #696720, #649748] * 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: Contributors:
Giovanni Campagna, Cosimo Cecchi, Monica Chelliah, Matthias Clasen, Tim Lunn, Giovanni Campagna, Matthias Clasen, Lionel Landwerlin, Tim Lunn, Rui Matos,
Florian Müllner, Jasper St. Pierre, Michael Wood, Owen W. Taylor Simon McVittie, Marta Milakovic, Florian Müllner, Jasper St. Pierre,
Daiki Ueno, Stef Walter
Translations: Translations:
Fran Diéguez [gl], Muhammet Kara [tr], Daniel Mustieles [es], Muhammet Kara [tr], Nik Kalach [ia], Žygimantas Beručka [lt],
Gil Forcada [ia], Anish A [ml], Dimitris Spingos [el], Marek Černocký [cs], Kjartan Maraas [nb]
Žygimantas Beručka [lt]
3.8.1 3.8.1
===== =====

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.63) 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_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@@ -63,18 +63,18 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.13.4 CLUTTER_MIN_VERSION=1.13.4
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.35.4 GJS_MIN_VERSION=1.35.4
MUTTER_MIN_VERSION=3.9.1 MUTTER_MIN_VERSION=3.8.3
GTK_MIN_VERSION=3.7.9 GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0 GIO_MIN_VERSION=2.35.0
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3
LIBEDATASERVER_MIN_VERSION=3.5.3 LIBEDATASERVER_MIN_VERSION=3.5.3
TELEPATHY_GLIB_MIN_VERSION=0.17.5 TELEPATHY_GLIB_MIN_VERSION=0.17.5
POLKIT_MIN_VERSION=0.100 POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11 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_DESKTOP_REQUIRED_VERSION=3.7.90
GNOME_MENUS_REQUIRED_VERSION=3.5.3 GNOME_MENUS_REQUIRED_VERSION=3.5.3
NETWORKMANAGER_MIN_VERSION=0.9.8 NETWORKMANAGER_MIN_VERSION=0.9.6
PULSE_MIN_VERS=2.0 PULSE_MIN_VERS=2.0
# Collect more than 20 libraries for a prize! # 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 polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $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(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11) PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)

View File

@@ -11,9 +11,6 @@
<KeyListEntry name="focus-active-notification" <KeyListEntry name="focus-active-notification"
_description="Focus the active notification"/> _description="Focus the active notification"/>
<KeyListEntry name="toggle-overview"
_description="Show the overview"/>
<KeyListEntry name="toggle-application-view" <KeyListEntry name="toggle-application-view"
_description="Show all applications"/> _description="Show all applications"/>

View File

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

View 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>

View File

@@ -46,7 +46,7 @@
<!-- <!--
GetResultMetas: GetResultMetas:
@identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet() @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 Return an array of meta data used to display each given result
--> -->

View File

@@ -117,13 +117,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
Overview. Overview.
</_description> </_description>
</key> </key>
<key name="toggle-overview" type="as">
<default>["&lt;Super&gt;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"> <key name="toggle-message-tray" type="as">
<default>["&lt;Super&gt;m"]</default> <default>["&lt;Super&gt;m"]</default>
<_summary>Keybinding to toggle the visibility of the message tray</_summary> <_summary>Keybinding to toggle the visibility of the message tray</_summary>
@@ -214,7 +207,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
</_description> </_description>
</key> </key>
<key type="b" name="current-workspace-only"> <key type="b" name="current-workspace-only">
<default>false</default> <default>true</default>
<summary>Limit switcher to current workspace.</summary> <summary>Limit switcher to current workspace.</summary>
<description> <description>
If true, only windows from the current workspace are shown in the switcher. If true, only windows from the current workspace are shown in the switcher.

View File

@@ -125,10 +125,6 @@ StScrollBar StButton#vhandle:active {
/* PopupMenu */ /* PopupMenu */
.popup-menu-ornament {
text-align: center;
}
.popup-menu-boxpointer, .popup-menu-boxpointer,
.candidate-popup-boxpointer { .candidate-popup-boxpointer {
-arrow-border-radius: 8px; -arrow-border-radius: 8px;
@@ -804,6 +800,11 @@ StScrollBar StButton#vhandle:active {
height: 24px; height: 24px;
} }
.empty-dash-drop-target {
width: 24px;
height: 24px;
}
/* Search Box */ /* Search Box */
#searchEntry { #searchEntry {
@@ -891,12 +892,11 @@ StScrollBar StButton#vhandle:active {
} }
.app-view-controls { .app-view-controls {
width: 250px;
padding-bottom: 32px; padding-bottom: 32px;
} }
.app-view-control { .app-view-control {
padding: 4px 16px; padding: 4px 32px;
} }
.search-display > StBoxLayout, .search-display > StBoxLayout,
@@ -2312,6 +2312,7 @@ StScrollBar StButton#vhandle:active {
font-weight: bold; font-weight: bold;
color: #666666; color: #666666;
padding-top: 1em; padding-top: 1em;
padding-left: 2px;
} }
.login-dialog-not-listed-button:focus .login-dialog-not-listed-label, .login-dialog-not-listed-button:focus .login-dialog-not-listed-label,
@@ -2342,52 +2343,47 @@ StScrollBar StButton#vhandle:active {
width: 15em; width: 15em;
} }
.login-dialog-session-list { .login-dialog-session-list,
color: #ffffff; .login-dialog-session-list-item {
font-size: 10.5pt; 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 { .login-dialog-session-list-button {
padding: 4px; 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 { .login-dialog-session-list-scroll-view {
background-gradient-start: rgba(80,80,80,0.3); padding: 6px;
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;
} }
.login-dialog-session-list-item:focus { .login-dialog-session-list-item {
background-color: #666666; padding-bottom: 6px;
} }
.login-dialog-session-list-triangle { .login-dialog-session-list-triangle {
padding-right: .5em; padding-right: 6px;
} }
.login-dialog-session-list-item-box { .login-dialog-session-list-item-box {
spacing: .25em; padding-left: 6px;
spacing: 6px;
} }
.login-dialog-session-list-item-dot { .login-dialog-session-list-item-dot {
width: .75em; width: 10px;
height: .75em; height: 10px;
}
.login-dialog-logo-bin {
padding: 24px 0px;
} }
.login-dialog .modal-dialog-button-box { .login-dialog .modal-dialog-button-box {

View File

@@ -46,6 +46,7 @@
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/> <xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/>
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/> <xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/>
<xi:include href="xml/shell-global.xml"/> <xi:include href="xml/shell-global.xml"/>
<xi:include href="xml/shell-keybinding-modes.xml"/>
<xi:include href="xml/shell-wm.xml"/> <xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-xfixes-cursor.xml"/> <xi:include href="xml/shell-xfixes-cursor.xml"/>
<xi:include href="xml/shell-util.xml"/> <xi:include href="xml/shell-util.xml"/>

View File

@@ -78,6 +78,7 @@ nobase_dist_js_DATA = \
ui/popupMenu.js \ ui/popupMenu.js \
ui/remoteSearch.js \ ui/remoteSearch.js \
ui/runDialog.js \ ui/runDialog.js \
ui/screencast.js \
ui/screenshot.js \ ui/screenshot.js \
ui/screenShield.js \ ui/screenShield.js \
ui/scripting.js \ ui/scripting.js \

View File

@@ -28,6 +28,7 @@ const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Lang = imports.lang; const Lang = imports.lang;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const Realmd = imports.gdm.realmd;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
@@ -39,7 +40,6 @@ const GdmUtil = imports.gdm.util;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const Panel = imports.ui.panel;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu; const UserMenu = imports.ui.userMenu;
@@ -48,44 +48,10 @@ const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 0.25; const _FADE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 0.5; const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 16; const _LOGO_ICON_HEIGHT = 48;
const WORK_SPINNER_ICON_SIZE = 24;
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
const WORK_SPINNER_ANIMATION_TIME = 0.3;
let _loginDialog = null; 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({ const UserListItem = new Lang.Class({
Name: 'UserListItem', Name: 'UserListItem',
@@ -552,6 +518,12 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._updateBanner)); Lang.bind(this, this._updateBanner));
this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY, this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
Lang.bind(this, this._updateDisableUserList)); 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', this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
vertical: true }); vertical: true });
@@ -609,7 +581,6 @@ const LoginDialog = new Lang.Class({
this._promptBox.add(this._promptLoginHint); this._promptBox.add(this._promptLoginHint);
this._signInButton = null; this._signInButton = null;
this._workSpinner = null;
this._sessionList = new SessionList(); this._sessionList = new SessionList();
this._sessionList.connect('session-activated', this._sessionList.connect('session-activated',
@@ -644,6 +615,11 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START, x_align: St.Align.START,
x_fill: true }); 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) if (!this._userManager.is_loaded)
this._userManagerLoadedId = this._userManager.connect('notify::is-loaded', this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
Lang.bind(this, function() { 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() { _reset: function() {
this._userVerifier.clear(); this._userVerifier.clear();
@@ -708,7 +702,7 @@ const LoginDialog = new Lang.Class({
this._promptEntry.text = ''; this._promptEntry.text = '';
this._updateSensitivity(true); this._updateSensitivity(true);
this._setWorking(false); this.setWorking(false);
}, },
_onDefaultSessionChanged: function(client, sessionId) { _onDefaultSessionChanged: function(client, sessionId) {
@@ -774,11 +768,6 @@ const LoginDialog = new Lang.Class({
}, },
_prepareDialog: function(forSecret, hold) { _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.buttonLayout.visible = true;
this.clearButtons(); this.clearButtons();
@@ -791,12 +780,11 @@ const LoginDialog = new Lang.Class({
y_fill: false, y_fill: false,
x_align: St.Align.START, x_align: St.Align.START,
y_align: St.Align.MIDDLE }); y_align: St.Align.MIDDLE });
this.buttonLayout.add(this._workSpinner.actor, this.placeSpinner({ expand: false,
{ expand: false, x_fill: false,
x_fill: false, y_fill: false,
y_fill: false, x_align: St.Align.END,
x_align: St.Align.END, y_align: St.Align.MIDDLE });
y_align: St.Align.MIDDLE });
this._signInButton = this.addButton({ action: Lang.bind(this, function() { this._signInButton = this.addButton({ action: Lang.bind(this, function() {
hold.release(); hold.release();
}), }),
@@ -849,7 +837,7 @@ const LoginDialog = new Lang.Class({
this._promptEntryActivateId = 0; this._promptEntryActivateId = 0;
} }
this._setWorking(false); this.setWorking(false);
this._promptBox.hide(); this._promptBox.hide();
this._promptLoginHint.hide(); this._promptLoginHint.hide();
@@ -862,36 +850,9 @@ const LoginDialog = new Lang.Class({
this._promptLoginHint.hide(); this._promptLoginHint.hide();
this.clearButtons(); this.clearButtons();
this._workSpinner = null;
this._signInButton = 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) { _askQuestion: function(verifier, serviceName, question, passwordChar) {
this._promptLabel.set_text(question); this._promptLabel.set_text(question);
@@ -906,7 +867,7 @@ const LoginDialog = new Lang.Class({
function() { function() {
let text = this._promptEntry.get_text(); let text = this._promptEntry.get_text();
this._updateSensitivity(false); this._updateSensitivity(false);
this._setWorking(true); this.setWorking(true);
this._userVerifier.answerQuery(serviceName, text); this._userVerifier.answerQuery(serviceName, text);
}]; }];
@@ -914,17 +875,40 @@ const LoginDialog = new Lang.Class({
return batch.run(); 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() { _askForUsernameAndLogIn: function() {
this._promptLabel.set_text(_("Username: ")); this._promptLabel.set_text(_("Username: "));
this._promptEntry.set_text(''); this._promptEntry.set_text('');
this._promptEntry.clutter_text.set_password_char(''); 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, let tasks = [this._showPrompt,
function() { function() {
let userName = this._promptEntry.get_text(); let userName = this._promptEntry.get_text();
this._promptEntry.reactive = false; this._promptEntry.reactive = false;
return this._beginVerificationForUser(userName); return this._beginVerificationForUser(userName);
},
function() {
realmManager.disconnect(signalId)
realmManager.release();
}]; }];
let batch = new Batch.ConsecutiveBatch(this, tasks); let batch = new Batch.ConsecutiveBatch(this, tasks);

View File

@@ -63,7 +63,7 @@ const Manager = new Lang.Class({
Lang.bind(this, this._reloadRealms)) Lang.bind(this, this._reloadRealms))
this._realms = {}; this._realms = {};
this._aggregateProvider.connect('g-properties-changed', this._signalId = this._aggregateProvider.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) { Lang.bind(this, function(proxy, properties) {
if ('Realms' in properties.deep_unpack()) if ('Realms' in properties.deep_unpack())
this._reloadRealms(); this._reloadRealms();
@@ -106,7 +106,7 @@ const Manager = new Lang.Class({
realm.connect('g-properties-changed', realm.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) { Lang.bind(this, function(proxy, properties) {
if ('Configured' in properties.deep_unpack()) if ('Configured' in properties.deep_unpack())
this._reloadRealm(); this._reloadRealm(realm);
})); }));
}, },
@@ -134,6 +134,18 @@ const Manager = new Lang.Class({
this._updateLoginFormat(); this._updateLoginFormat();
return this._loginFormat; 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) Signals.addSignalMethods(Manager.prototype)

View File

@@ -9,7 +9,6 @@ const Signals = imports.signals;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint; const Fprint = imports.gdm.fingerprint;
const Realmd = imports.gdm.realmd;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@@ -117,7 +116,6 @@ const ShellUserVerifier = new Lang.Class({
this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA }); this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
this._fprintManager = new Fprint.FprintManager(); this._fprintManager = new Fprint.FprintManager();
this._realmManager = new Realmd.Manager();
this._messageQueue = []; this._messageQueue = [];
this._messageQueueTimeoutId = 0; this._messageQueueTimeoutId = 0;
this.hasPendingMessages = false; this.hasPendingMessages = false;
@@ -166,6 +164,7 @@ const ShellUserVerifier = new Lang.Class({
answerQuery: function(serviceName, answer) { answerQuery: function(serviceName, answer) {
if (!this._userVerifier.hasPendingMessages) { if (!this._userVerifier.hasPendingMessages) {
this._clearMessageQueue();
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
} else { } else {
let signalId = this._userVerifier.connect('no-more-messages', let signalId = this._userVerifier.connect('no-more-messages',
@@ -377,30 +376,11 @@ const ShellUserVerifier = new Lang.Class({
this._queueMessage(problem, 'login-dialog-message-warning'); 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) { _onInfoQuery: function(client, serviceName, question) {
// We only expect questions to come from the main auth service // We only expect questions to come from the main auth service
if (serviceName != PASSWORD_SERVICE_NAME) if (serviceName != PASSWORD_SERVICE_NAME)
return; return;
this._showRealmLoginHint();
this._realmLoginHintSignalId = this._realmManager.connect('login-format-changed',
Lang.bind(this, this._showRealmLoginHint));
this.emit('ask-question', serviceName, question, ''); this.emit('ask-question', serviceName, question, '');
}, },
@@ -476,11 +456,6 @@ const ShellUserVerifier = new Lang.Class({
} }
this.emit('hide-login-hint'); this.emit('hide-login-hint');
if (this._realmLoginHintSignalId) {
this._realmManager.disconnect(this._realmLoginHintSignalId);
this._realmLoginHintSignalId = 0;
}
}, },
}); });
Signals.addSignalMethods(ShellUserVerifier.prototype); Signals.addSignalMethods(ShellUserVerifier.prototype);

View File

@@ -58,6 +58,7 @@ const Map = new Lang.Class({
_init: function(iterable) { _init: function(iterable) {
this._pool = { }; this._pool = { };
this._size = 0;
if (iterable) { if (iterable) {
for (let i = 0; i < iterable.length; i++) { for (let i = 0; i < iterable.length; i++) {
@@ -99,6 +100,7 @@ const Map = new Lang.Class({
node.value = value; node.value = value;
} else { } else {
this._pool[hash] = { key: key, value: value }; this._pool[hash] = { key: key, value: value };
this._size++;
} }
}, },
@@ -108,6 +110,7 @@ const Map = new Lang.Class({
if (node && _sameValue(node.key, key)) { if (node && _sameValue(node.key, key)) {
delete this._pool[hash]; delete this._pool[hash];
this._size--;
return [node.key, node.value]; return [node.key, node.value];
} else { } else {
return [null, null]; return [null, null];
@@ -136,6 +139,6 @@ const Map = new Lang.Class({
}, },
size: function() { size: function() {
return Object.getOwnPropertyNames(this._pool).length; return this._size;
}, },
}); });

View File

@@ -18,7 +18,7 @@ const _urlRegexp = new RegExp(
'(^|' + _leadingJunk + ')' + '(^|' + _leadingJunk + ')' +
'(' + '(' +
'(?:' + '(?:' +
'(?:http|https|ftp)://' + // scheme:// '[a-z][\\w-]+://' + // scheme://
'|' + '|' +
'www\\d{0,3}[.]' + // www. 'www\\d{0,3}[.]' + // www.
'|' + '|' +

View File

@@ -234,7 +234,7 @@ const AppSwitcherPopup = new Lang.Class({
_finish : function(timestamp) { _finish : function(timestamp) {
let appIcon = this._items[this._selectedIndex]; let appIcon = this._items[this._selectedIndex];
if (this._currentWindow < 0) if (this._currentWindow < 0)
appIcon.app.activate_full(-1, timestamp); appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp);
else else
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp); Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);

View File

@@ -187,6 +187,9 @@ const AllView = new Lang.Class({
_init: function() { _init: function() {
this.parent(); this.parent();
this._grid.actor.y_align = Clutter.ActorAlign.START;
this._grid.actor.y_expand = true;
let box = new St.BoxLayout({ vertical: true }); let box = new St.BoxLayout({ vertical: true });
this._stack = new St.Widget({ layout_manager: new AllViewLayout() }); this._stack = new St.Widget({ layout_manager: new AllViewLayout() });
this._stack.add_actor(this._grid.actor); this._stack.add_actor(this._grid.actor);
@@ -276,8 +279,12 @@ const AllView = new Lang.Class({
this._eventBlocker.reactive = isOpen; this._eventBlocker.reactive = isOpen;
this._currentPopup = isOpen ? popup : null; this._currentPopup = isOpen ? popup : null;
this._updateIconOpacities(isOpen); this._updateIconOpacities(isOpen);
if (isOpen) if (isOpen) {
this._ensureIconVisible(popup.actor); 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() { loadApps: function() {
let mostUsed = this._usage.get_most_used (""); let mostUsed = this._usage.get_most_used ("");
for (let i = 0; i < mostUsed.length; i++) { for (let i = 0; i < mostUsed.length; i++) {
if (!mostUsed[i].get_app_info().should_show())
continue;
let appIcon = new AppIcon(mostUsed[i]); let appIcon = new AppIcon(mostUsed[i]);
this._grid.addItem(appIcon.actor, -1); this._grid.addItem(appIcon.actor, -1);
} }
@@ -329,6 +334,42 @@ const Views = {
ALL: 1 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({ const AppDisplay = new Lang.Class({
Name: 'AppDisplay', Name: 'AppDisplay',
@@ -369,9 +410,9 @@ const AppDisplay = new Lang.Class({
x_expand: true, y_expand: true }); x_expand: true, y_expand: true });
this.actor.add(this._viewStack, { expand: true }); this.actor.add(this._viewStack, { expand: true });
let layout = new Clutter.BoxLayout({ homogeneous: true }); let layout = new ControlsBoxLayout({ homogeneous: true });
this._controls = new St.Widget({ style_class: 'app-view-controls', this._controls = new St.Widget({ style_class: 'app-view-controls' });
layout_manager: layout }); this._controls.set_layout_manager(layout);
this.actor.add(new St.Bin({ child: this._controls })); 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 // Position the popup above or below the source icon
if (side == St.Side.BOTTOM) { if (side == St.Side.BOTTOM) {
this._popup.actor.show(); 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(); this._popup.actor.hide();
} else { } else {
this._popup.actor.y = this.actor.y + this.actor.height; this._popup.actor.y = this.actor.y + this.actor.height;
@@ -597,6 +642,7 @@ const AppFolderPopup = new Lang.Class({
this._arrowSide = side; this._arrowSide = side;
this._isOpen = false; this._isOpen = false;
this.parentOffset = 0;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(), this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
visible: false, visible: false,
@@ -620,17 +666,31 @@ const AppFolderPopup = new Lang.Class({
this.actor.add_actor(this._boxPointer.actor); this.actor.add_actor(this._boxPointer.actor);
this._boxPointer.bin.set_child(this._view.actor); this._boxPointer.bin.set_child(this._view.actor);
let closeButton = Util.makeCloseButton(); this.closeButton = Util.makeCloseButton();
closeButton.connect('clicked', Lang.bind(this, this.popdown)); this.closeButton.connect('clicked', Lang.bind(this, this.popdown));
this.actor.add_actor(closeButton); 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); GObject.BindingFlags.SYNC_CREATE);
global.focus_manager.add_group(this.actor);
source.actor.connect('destroy', Lang.bind(this, source.actor.connect('destroy', Lang.bind(this,
function() { function() {
this.actor.destroy(); 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() { toggle: function() {
@@ -645,6 +705,7 @@ const AppFolderPopup = new Lang.Class({
return; return;
this.actor.show(); this.actor.show();
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
this._boxPointer.setArrowActor(this._source.actor); this._boxPointer.setArrowActor(this._source.actor);
this._boxPointer.show(BoxPointer.PopupAnimation.FADE | this._boxPointer.show(BoxPointer.PopupAnimation.FADE |

View File

@@ -318,9 +318,9 @@ const Background = new Lang.Class({
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
this.isLoaded = false; this.isLoaded = false;
this._settings.connect('changed', Lang.bind(this, function() { this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() {
this.emit('changed'); this.emit('changed');
})); }));
this._load(); this._load();
}, },
@@ -361,6 +361,10 @@ const Background = new Lang.Class({
this.actor.disconnect(this._destroySignalId); this.actor.disconnect(this._destroySignalId);
this._destroySignalId = 0; this._destroySignalId = 0;
if (this._settingsChangedSignalId != 0)
this._settings.disconnect(this._settingsChangedSignalId);
this._settingsChangedSignalId = 0;
}, },
_setLoaded: function() { _setLoaded: function() {
@@ -571,7 +575,16 @@ const Background = new Lang.Class({
} }
let uri = this._settings.get_string(PICTURE_URI_KEY); 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); this._loadFile(filename);
}, },

View File

@@ -589,12 +589,12 @@ const BoxPointer = new Lang.Class({
return St.Side.TOP; return St.Side.TOP;
break; break;
case St.Side.LEFT: 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) boxWidth < sourceAllocation.x1 - monitor.x)
return St.Side.RIGHT; return St.Side.RIGHT;
break; break;
case St.Side.RIGHT: case St.Side.RIGHT:
if (sourceAllocation.y1 - boxWidth < monitor.x && if (sourceAllocation.x1 - boxWidth < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2) boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return St.Side.LEFT; return St.Side.LEFT;
break; break;

View File

@@ -31,7 +31,7 @@ function shouldAutorunMount(mount, forTransient) {
if (!volume || (!volume.allowAutorun && forTransient)) if (!volume || (!volume.allowAutorun && forTransient))
return false; return false;
if (!root.is_native() || isMountRootHidden(root)) if (root.is_native() && isMountRootHidden(root))
return false; return false;
return true; return true;

View File

@@ -25,7 +25,7 @@ const KeyringDialog = new Lang.Class({
this.prompt = new Shell.KeyringPrompt(); this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword)); this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword));
this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm)); 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', let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
vertical: false }); vertical: false });
@@ -63,11 +63,17 @@ const KeyringDialog = new Lang.Class({
this._cancelButton = this.addButton({ label: '', this._cancelButton = this.addButton({ label: '',
action: Lang.bind(this, this._onCancelButton), 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: '', this._continueButton = this.addButton({ label: '',
action: Lang.bind(this, this._onContinueButton), action: Lang.bind(this, this._onContinueButton),
default: true }, 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('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, '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) { _updateSensitivity: function(sensitive) {
this._passwordEntry.reactive = sensitive; if (this._passwordEntry) {
this._passwordEntry.clutter_text.editable = sensitive; 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.can_focus = sensitive;
this._continueButton.reactive = sensitive; this._continueButton.reactive = sensitive;
this.setWorking(!sensitive);
}, },
_ensureOpen: function() { _ensureOpen: function() {

View File

@@ -31,7 +31,6 @@ const AuthenticationDialog = new Lang.Class({
this.message = message; this.message = message;
this.userNames = userNames; this.userNames = userNames;
this._wasDismissed = false; this._wasDismissed = false;
this._completed = false;
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout', let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
vertical: false }); vertical: false });
@@ -161,26 +160,32 @@ const AuthenticationDialog = new Lang.Class({
this._cancelButton = this.addButton({ label: _("Cancel"), this._cancelButton = this.addButton({ label: _("Cancel"),
action: Lang.bind(this, this.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"), this._okButton = this.addButton({ label: _("Authenticate"),
action: Lang.bind(this, this._onAuthenticateButtonPressed), action: Lang.bind(this, this._onAuthenticateButtonPressed),
default: true }, 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._doneEmitted = false;
this._identityToAuth = Polkit.UnixUser.new_for_name(userName); this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
this._cookie = cookie; this._cookie = cookie;
},
performAuthentication: function() {
this.destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth, this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie }); cookie: this._cookie });
this._session.connect('completed', Lang.bind(this, this._onSessionCompleted)); this._session.connect('completed', Lang.bind(this, this._onSessionCompleted));
this._session.connect('request', Lang.bind(this, this._onSessionRequest)); this._session.connect('request', Lang.bind(this, this._onSessionRequest));
this._session.connect('show-error', Lang.bind(this, this._onSessionShowError)); this._session.connect('show-error', Lang.bind(this, this._onSessionShowError));
this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo)); this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo));
},
startAuthentication: function() {
this._session.initiate(); this._session.initiate();
}, },
@@ -202,14 +207,14 @@ const AuthenticationDialog = new Lang.Class({
log('polkitAuthenticationAgent: Failed to show modal dialog.' + log('polkitAuthenticationAgent: Failed to show modal dialog.' +
' Dismissing authentication request for action-id ' + this.actionId + ' Dismissing authentication request for action-id ' + this.actionId +
' cookie ' + this._cookie); ' cookie ' + this._cookie);
this._emitDone(false, true); this._emitDone(true);
} }
}, },
_emitDone: function(keepVisible, dismissed) { _emitDone: function(dismissed) {
if (!this._doneEmitted) { if (!this._doneEmitted) {
this._doneEmitted = true; 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.can_focus = sensitive;
this._okButton.reactive = sensitive; this._okButton.reactive = sensitive;
this.setWorking(!sensitive);
}, },
_onEntryActivate: function() { _onEntryActivate: function() {
@@ -237,12 +243,16 @@ const AuthenticationDialog = new Lang.Class({
}, },
_onSessionCompleted: function(session, gainedAuthorization) { _onSessionCompleted: function(session, gainedAuthorization) {
if (this._completed) if (this._completed || this._doneEmitted)
return; return;
this._completed = true; 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 /* Unless we are showing an existing error message from the PAM
* module (the PAM module could be reporting the authentication * module (the PAM module could be reporting the authentication
* error providing authentication-method specific information), * error providing authentication-method specific information),
@@ -258,8 +268,10 @@ const AuthenticationDialog = new Lang.Class({
this._infoMessageLabel.hide(); this._infoMessageLabel.hide();
this._nullMessageLabel.hide(); this._nullMessageLabel.hide();
} }
/* Try and authenticate again */
this.performAuthentication();
} }
this._emitDone(!gainedAuthorization, false);
}, },
_onSessionRequest: function(session, request, echo_on) { _onSessionRequest: function(session, request, echo_on) {
@@ -303,6 +315,7 @@ const AuthenticationDialog = new Lang.Class({
if (this._session) { if (this._session) {
if (!this._completed) if (!this._completed)
this._session.cancel(); this._session.cancel();
this._completed = false;
this._session = null; this._session = null;
} }
}, },
@@ -317,7 +330,7 @@ const AuthenticationDialog = new Lang.Class({
cancel: function() { cancel: function() {
this._wasDismissed = true; this._wasDismissed = true;
this.close(global.get_current_time()); this.close(global.get_current_time());
this._emitDone(false, true); this._emitDone(true);
}, },
}); });
Signals.addSignalMethods(AuthenticationDialog.prototype); Signals.addSignalMethods(AuthenticationDialog.prototype);
@@ -327,7 +340,6 @@ const AuthenticationAgent = new Lang.Class({
_init: function() { _init: function() {
this._currentDialog = null; this._currentDialog = null;
this._isCompleting = false;
this._handle = null; this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent(); this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', Lang.bind(this, this._onInitiate)); this._native.connect('initiate', Lang.bind(this, this._onInitiate));
@@ -364,45 +376,24 @@ const AuthenticationAgent = new Lang.Class({
// discussion. // discussion.
this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone)); this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone));
this._currentDialog.startAuthentication(); this._currentDialog.performAuthentication();
}, },
_onCancel: function(nativeAgent) { _onCancel: function(nativeAgent) {
this._completeRequest(false, false); this._completeRequest(false);
}, },
_onDialogDone: function(dialog, keepVisible, dismissed) { _onDialogDone: function(dialog, dismissed) {
this._completeRequest(keepVisible, dismissed); this._completeRequest(dismissed);
}, },
_reallyCompleteRequest: function(dismissed) { _completeRequest: function(dismissed) {
this._currentDialog.close(); this._currentDialog.close();
this._currentDialog.destroySession(); this._currentDialog.destroySession();
this._currentDialog = null; 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; const Component = AuthenticationAgent;

View File

@@ -18,7 +18,7 @@ const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
// See Notification.appendMessage // 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_TIME = 15 * 60; // 15 minutes
const SCROLLBACK_RECENT_LENGTH = 20; const SCROLLBACK_RECENT_LENGTH = 20;
const SCROLLBACK_IDLE_LENGTH = 5; const SCROLLBACK_IDLE_LENGTH = 5;
@@ -967,7 +967,8 @@ const ChatNotification = new Lang.Class({
let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate), let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate),
group: 'meta', group: 'meta',
styles: ['chat-meta-message'], styles: ['chat-meta-message'],
childProps: { expand: true, x_fill: false }, childProps: { expand: true, x_fill: false,
x_align: St.Align.END },
noTimestamp: true, noTimestamp: true,
timestamp: lastMessageTime }); timestamp: lastMessageTime });

View File

@@ -89,19 +89,25 @@ const CtrlAltTabManager = new Lang.Class({
let items = this._items.filter(function (item) { return item.proxy.mapped; }); let items = this._items.filter(function (item) { return item.proxy.mapped; });
// And add the windows metacity would show in its Ctrl-Alt-Tab list // 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 screen = global.screen;
let display = screen.get_display(); let display = screen.get_display();
let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ()); let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ());
let windowTracker = Shell.WindowTracker.get_default(); let windowTracker = Shell.WindowTracker.get_default();
let textureCache = St.TextureCache.get_default(); let textureCache = St.TextureCache.get_default();
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let icon; let icon = null;
let app = windowTracker.get_window_app(windows[i]); let iconName = null;
if (app) if (windows[i].get_window_type () == Meta.WindowType.DESKTOP) {
icon = app.create_icon_texture(POPUP_APPICON_SIZE); iconName = 'video-display-symbolic';
else } else {
icon = textureCache.bind_pixbuf_property(windows[i], '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');
}
items.push({ name: windows[i].title, items.push({ name: windows[i].title,
proxy: windows[i].get_compositor_private(), proxy: windows[i].get_compositor_private(),
focusCallback: Lang.bind(windows[i], focusCallback: Lang.bind(windows[i],
@@ -109,6 +115,7 @@ const CtrlAltTabManager = new Lang.Class({
Main.activateWindow(this, timestamp); Main.activateWindow(this, timestamp);
}), }),
iconActor: icon, iconActor: icon,
iconName: iconName,
sortGroup: SortGroup.MIDDLE }); sortGroup: SortGroup.MIDDLE });
} }
} }

View File

@@ -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({ const DashActor = new Lang.Class({
Name: 'DashActor', Name: 'DashActor',
Extends: St.Widget, Extends: St.Widget,
@@ -441,6 +451,12 @@ const Dash = new Lang.Class({
dragMotion: Lang.bind(this, this._onDragMotion) dragMotion: Lang.bind(this, this._onDragMotion)
}; };
DND.addDragMonitor(this._dragMonitor); 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() { _onDragCancelled: function() {
@@ -457,6 +473,7 @@ const Dash = new Lang.Class({
_endDrag: function() { _endDrag: function() {
this._clearDragPlaceholder(); this._clearDragPlaceholder();
this._clearEmptyDropTarget();
this._showAppsIcon.setDragApp(null); this._showAppsIcon.setDragApp(null);
DND.removeDragMonitor(this._dragMonitor); DND.removeDragMonitor(this._dragMonitor);
}, },
@@ -797,9 +814,21 @@ const Dash = new Lang.Class({
_clearDragPlaceholder: function() { _clearDragPlaceholder: function() {
if (this._dragPlaceholder) { if (this._dragPlaceholder) {
this._animatingPlaceholdersCount++;
this._dragPlaceholder.animateOutAndDestroy(); this._dragPlaceholder.animateOutAndDestroy();
this._dragPlaceholder.connect('destroy',
Lang.bind(this, function() {
this._animatingPlaceholdersCount--;
}));
this._dragPlaceholder = null; 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--; 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) { if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
this._dragPlaceholderPos = pos; this._dragPlaceholderPos = pos;
// Don't allow positioning before or after self // Don't allow positioning before or after self
if (favPos != -1 && (pos == favPos || pos == favPos + 1)) { if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
if (this._dragPlaceholder) { this._clearDragPlaceholder();
this._dragPlaceholder.animateOutAndDestroy();
this._animatingPlaceholdersCount++;
this._dragPlaceholder.connect('destroy',
Lang.bind(this, function() {
this._animatingPlaceholdersCount--;
}));
}
this._dragPlaceholder = null;
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
} }
@@ -868,9 +892,9 @@ const Dash = new Lang.Class({
// Remove the drag placeholder if we are not in the // Remove the drag placeholder if we are not in the
// "favorites zone" // "favorites zone"
if (pos > numFavorites && this._dragPlaceholder) { if (pos > numFavorites)
this._clearDragPlaceholder(); this._clearDragPlaceholder();
}
if (!this._dragPlaceholder) if (!this._dragPlaceholder)
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;

View File

@@ -100,7 +100,6 @@ const DateMenuButton = new Lang.Class({
Shell.AppSystem.get_default().connect('installed-changed', Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._appInstalledChanged)); Lang.bind(this, this._appInstalledChanged));
this._appInstalledChanged();
item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop'); item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop');
if (item) { if (item) {
@@ -157,14 +156,16 @@ const DateMenuButton = new Lang.Class({
}, },
_appInstalledChanged: function() { _appInstalledChanged: function() {
let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); this._calendarApp = undefined;
this._openClocksItem.actor.visible = app !== null; this._updateEventsVisibility();
}, },
_updateEventsVisibility: function() { _updateEventsVisibility: function() {
let visible = this._eventSource.hasCalendars; let visible = this._eventSource.hasCalendars;
this._openCalendarItem.actor.visible = visible; this._openCalendarItem.actor.visible = visible &&
this._openClocksItem.actor.visible = visible; (this._getCalendarApp() != null);
this._openClocksItem.actor.visible = visible &&
(this._getClockApp() != null);
this._separator.visible = visible; this._separator.visible = visible;
if (visible) { if (visible) {
let alignment = 0.25; let alignment = 0.25;
@@ -217,10 +218,26 @@ const DateMenuButton = new Lang.Class({
this._date.set_text(displayDate.toLocaleFormat(dateFormat)); 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() { _onOpenCalendarActivate: function() {
this.menu.close(); this.menu.close();
let app = Gio.AppInfo.get_default_for_type('text/calendar', false); let app = this._getCalendarApp();
if (app.get_id() == 'evolution.desktop') if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop'); app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context()); app.launch([], global.create_app_launch_context());
@@ -228,7 +245,7 @@ const DateMenuButton = new Lang.Class({
_onOpenClocksActivate: function() { _onOpenClocksActivate: function() {
this.menu.close(); this.menu.close();
let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); let app = this._getClockApp();
app.activate(); app.activate();
} }
}); });

View File

@@ -149,16 +149,16 @@ const _Draggable = new Lang.Class({
_grabEvents: function() { _grabEvents: function() {
if (!this._eventsGrabbed) { if (!this._eventsGrabbed) {
Clutter.grab_pointer(_getEventHandlerActor()); this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
Clutter.grab_keyboard(_getEventHandlerActor()); if (this._eventsGrabbed)
this._eventsGrabbed = true; Clutter.grab_pointer(_getEventHandlerActor());
} }
}, },
_ungrabEvents: function() { _ungrabEvents: function() {
if (this._eventsGrabbed) { if (this._eventsGrabbed) {
Clutter.ungrab_pointer(); Clutter.ungrab_pointer();
Clutter.ungrab_keyboard(); Main.popModal(_getEventHandlerActor());
this._eventsGrabbed = false; this._eventsGrabbed = false;
} }
}, },

View File

@@ -420,6 +420,7 @@ const EndSessionDialog = new Lang.Class({
_startTimer: function() { _startTimer: function() {
let startTime = GLib.get_monotonic_time(); let startTime = GLib.get_monotonic_time();
this._secondsLeft = this._totalSecondsToStayOpen; this._secondsLeft = this._totalSecondsToStayOpen;
this._updateDescription();
this._timerId = Mainloop.timeout_add_seconds(1, Lang.bind(this, this._timerId = Mainloop.timeout_add_seconds(1, Lang.bind(this,
function() { function() {

View File

@@ -5,6 +5,8 @@ imports.gi.versions.Gio = '2.0';
imports.gi.versions.Gdk = '3.0'; imports.gi.versions.Gdk = '3.0';
imports.gi.versions.GdkPixbuf = '2.0'; imports.gi.versions.GdkPixbuf = '2.0';
imports.gi.versions.Gtk = '3.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 Clutter = imports.gi.Clutter;;
const Gettext = imports.gettext; const Gettext = imports.gettext;

View File

@@ -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 = { const defaultParams = {
trackFullscreen: false, trackFullscreen: false,
affectsStruts: false, affectsStruts: false,
@@ -277,7 +261,7 @@ const LayoutManager = new Lang.Class({
this.monitors = []; this.monitors = [];
let nMonitors = screen.get_n_monitors(); let nMonitors = screen.get_n_monitors();
for (let i = 0; i < nMonitors; i++) 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) { if (nMonitors == 1) {
this.primaryIndex = this.bottomIndex = 0; this.primaryIndex = this.bottomIndex = 0;
@@ -299,10 +283,8 @@ const LayoutManager = new Lang.Class({
_updateHotCorners: function() { _updateHotCorners: function() {
// destroy old hot corners // destroy old hot corners
this.hotCorners.forEach(function(corner) { for (let i = 0; i < this.hotCorners.length; i++)
if (corner) this.hotCorners[i].destroy();
corner.destroy();
});
this.hotCorners = []; this.hotCorners = [];
let size = this.panelBox.height; 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 cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
let cornerY = monitor.y; let cornerY = monitor.y;
let haveTopLeftCorner = true;
if (i != this.primaryIndex) { if (i != this.primaryIndex) {
let haveTopLeftCorner = true;
// Check if we have a top left (right for RTL) corner. // 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) // I.e. if there is no monitor directly above or to the left(right)
let besideX = this._rtl ? monitor.x + 1 : cornerX - 1; let besideX = this._rtl ? monitor.x + 1 : cornerX - 1;
@@ -342,15 +324,14 @@ const LayoutManager = new Lang.Class({
break; break;
} }
} }
if (!haveTopLeftCorner)
continue;
} }
if (haveTopLeftCorner) { let corner = new HotCorner(this, monitor, cornerX, cornerY);
let corner = new HotCorner(this, monitor, cornerX, cornerY); corner.setBarrierSize(size);
corner.setBarrierSize(size); this.hotCorners.push(corner);
this.hotCorners.push(corner);
} else {
this.hotCorners.push(null);
}
} }
this.emit('hot-corners-changed'); this.emit('hot-corners-changed');
@@ -366,7 +347,7 @@ const LayoutManager = new Lang.Class({
BackgroundMenu.addBackgroundMenu(bgManager.background.actor); BackgroundMenu.addBackgroundMenu(bgManager.background.actor);
})); }));
this._bgManagers.push(bgManager); this._bgManagers[monitorIndex] = bgManager;
return bgManager.background; return bgManager.background;
}, },
@@ -427,8 +408,7 @@ const LayoutManager = new Lang.Class({
let size = this.panelBox.height; let size = this.panelBox.height;
this.hotCorners.forEach(function(corner) { 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) // and shown otherwise)
addChrome: function(actor, params) { addChrome: function(actor, params) {
this.uiGroup.add_actor(actor); 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); this._trackActor(actor, params);
}, },
@@ -920,8 +902,13 @@ const LayoutManager = new Lang.Class({
}, },
_updateFullscreen: function() { _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._updateVisibility();
this._queueUpdateRegions(); this._queueUpdateRegions();
this.emit('fullscreen-changed');
}, },
_windowsRestacked: function() { _windowsRestacked: function() {

View File

@@ -38,12 +38,8 @@ const Magnifier = imports.ui.magnifier;
const XdndHandler = imports.ui.xdndHandler; const XdndHandler = imports.ui.xdndHandler;
const Util = imports.misc.util; const Util = imports.misc.util;
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff); 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 componentManager = null;
let panel = null; let panel = null;
let overview = null; let overview = null;
@@ -71,8 +67,7 @@ let layoutManager = null;
let _startDate; let _startDate;
let _defaultCssStylesheet = null; let _defaultCssStylesheet = null;
let _cssStylesheet = null; let _cssStylesheet = null;
let _overridesSettings = null; let _workspacesSettings = null;
let _a11ySettings = null;
function _sessionUpdated() { function _sessionUpdated() {
_loadDefaultStylesheet(); _loadDefaultStylesheet();
@@ -110,6 +105,7 @@ function start() {
function _sessionsLoaded() { function _sessionsLoaded() {
sessionMode.connect('updated', _sessionUpdated); sessionMode.connect('updated', _sessionUpdated);
_initializePrefs();
_initializeUI(); _initializeUI();
shellDBusService = new ShellDBus.GnomeShell(); shellDBusService = new ShellDBus.GnomeShell();
@@ -118,6 +114,21 @@ function _sessionsLoaded() {
_sessionUpdated(); _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() { function _initializeUI() {
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem // also initialize ShellAppSystem first. ShellAppSystem
@@ -161,14 +172,9 @@ function _initializeUI() {
layoutManager.init(); layoutManager.init();
overview.init(); overview.init();
_a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA });
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1); false, -1, 1);
global.display.connect('overlay-key', Lang.bind(overview, function () { global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE))
overview.toggle();
}));
// Provide the bus object for gnome-session to // Provide the bus object for gnome-session to
// initiate logouts. // initiate logouts.
@@ -188,9 +194,6 @@ function _initializeUI() {
Scripting.runPerfScript(module, perfOutput); 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('notify::n-workspaces', _nWorkspacesChanged);
global.screen.connect('window-entered-monitor', _windowEnteredMonitor); global.screen.connect('window-entered-monitor', _windowEnteredMonitor);

View File

@@ -1530,11 +1530,7 @@ const MessageTrayContextMenu = new Lang.Class({
}, },
_updateClearSensitivity: function() { _updateClearSensitivity: function() {
let sources = this._tray.getSources(); this._clearItem.setSensitive(this._tray.clearableCount > 0);
sources = sources.filter(function(source) {
return !source.trayIcon && !source.isChat && !source.resident;
});
this._clearItem.setSensitive(sources.length > 0);
}, },
setPosition: function(x, y) { setPosition: function(x, y) {
@@ -1557,22 +1553,23 @@ const MessageTray = new Lang.Class({
this.actor = new St.Widget({ name: 'message-tray', this.actor = new St.Widget({ name: 'message-tray',
reactive: true, reactive: true,
track_hover: true,
layout_manager: new Clutter.BinLayout(), layout_manager: new Clutter.BinLayout(),
x_expand: true, x_expand: true,
y_expand: true, y_expand: true,
y_align: Clutter.ActorAlign.START, y_align: Clutter.ActorAlign.START,
}); });
this.actor.connect('notify::hover', Lang.bind(this, this._onTrayHoverChanged));
this._notificationWidget = new St.Widget({ name: 'notification-container', this._notificationWidget = new St.Widget({ name: 'notification-container',
reactive: true,
track_hover: true,
y_align: Clutter.ActorAlign.START, y_align: Clutter.ActorAlign.START,
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_expand: true, y_expand: true,
x_expand: true, x_expand: true,
layout_manager: new Clutter.BinLayout() }); layout_manager: new Clutter.BinLayout() });
this._notificationWidget.connect('key-release-event', Lang.bind(this, this._onNotificationKeyRelease)); 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 = new St.Bin({ y_expand: true });
this._notificationBin.set_y_align(Clutter.ActorAlign.START); this._notificationBin.set_y_align(Clutter.ActorAlign.START);
@@ -1627,25 +1624,24 @@ const MessageTray = new Lang.Class({
{ keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY }); { keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY });
this._grabHelper.addActor(this._summaryBoxPointer.actor); this._grabHelper.addActor(this._summaryBoxPointer.actor);
this._grabHelper.addActor(this.actor); this._grabHelper.addActor(this.actor);
this._grabHelper.addActor(this._notificationWidget);
Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, this._onKeyboardVisibleChanged)); Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, this._onKeyboardVisibleChanged));
this._trayState = State.HIDDEN; this._trayState = State.HIDDEN;
this._traySummoned = false; this._traySummoned = false;
this._useLongerNotificationLeftTimeout = false; this._useLongerTrayLeftTimeout = false;
this._trayLeftTimeoutId = 0; 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 // 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 // a lot of complex state related to timeouts and the current
// state of the pointer when a notification pops up. // 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 // This tracks this.actor.hover and is used to fizzle
// out non-changing hover notifications in onNotificationHoverChanged. // out non-changing hover notifications in onTrayHoverChanged.
this._notificationHovered = false; this._trayHovered = false;
this._keyboardVisible = false; this._keyboardVisible = false;
this._notificationClosed = false; this._notificationClosed = false;
@@ -1657,9 +1653,12 @@ const MessageTray = new Lang.Class({
this._desktopCloneState = State.HIDDEN; this._desktopCloneState = State.HIDDEN;
this._notificationRemoved = false; this._notificationRemoved = false;
this._reNotifyAfterHideNotification = null; this._reNotifyAfterHideNotification = null;
this._inFullscreen = false;
this._desktopClone = null; this._desktopClone = null;
this._inCtrlAltTab = false; this._inCtrlAltTab = false;
this.clearableCount = 0;
this._lightbox = new Lightbox.Lightbox(global.overlay_group, this._lightbox = new Lightbox.Lightbox(global.overlay_group,
{ inhibitEvents: true, { inhibitEvents: true,
fadeInTime: ANIMATION_TIME, 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.actor);
Main.layoutManager.trayBox.add_actor(this._notificationWidget);
Main.layoutManager.trackChrome(this.actor); Main.layoutManager.trackChrome(this.actor);
Main.layoutManager.trackChrome(this._notificationWidget); Main.layoutManager.trackChrome(this._notificationWidget);
Main.layoutManager.trackChrome(this._closeButton); 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)); Main.layoutManager.connect('hot-corners-changed', Lang.bind(this, this._hotCornersChanged));
// If the overview shows or hides while we're in // If the overview shows or hides while we're in
@@ -1721,6 +1719,9 @@ const MessageTray = new Lang.Class({
this.actor.add_action(clickAction); this.actor.add_action(clickAction);
clickAction.connect('clicked', Lang.bind(this, function(action) { clickAction.connect('clicked', Lang.bind(this, function(action) {
if (this._trayState != State.SHOWN)
return;
let button = action.get_button(); let button = action.get_button();
if (button == 3) if (button == 3)
this._openContextMenu(); this._openContextMenu();
@@ -1731,7 +1732,7 @@ const MessageTray = new Lang.Class({
clickAction.connect('long-press', Lang.bind(this, function(action, actor, state) { clickAction.connect('long-press', Lang.bind(this, function(action, actor, state) {
switch (state) { switch (state) {
case Clutter.LongPressState.QUERY: case Clutter.LongPressState.QUERY:
return true; return this._trayState == State.SHOWN;
case Clutter.LongPressState.ACTIVATE: case Clutter.LongPressState.ACTIVATE:
this._openContextMenu(); this._openContextMenu();
} }
@@ -1747,7 +1748,7 @@ const MessageTray = new Lang.Class({
let [x, y, mask] = global.get_pointer(); let [x, y, mask] = global.get_pointer();
this._contextMenu.setPosition(Math.round(x), Math.round(y)); this._contextMenu.setPosition(Math.round(x), Math.round(y));
this._grabHelper.grab({ actor: this._contextMenu.actor, this._grabHelper.grab({ actor: this._contextMenu.actor,
modal: true, grabFocus: true,
onUngrab: Lang.bind(this, function () { onUngrab: Lang.bind(this, function () {
this._contextMenu.close(BoxPointer.PopupAnimation.FULL); this._contextMenu.close(BoxPointer.PopupAnimation.FULL);
}) })
@@ -1793,12 +1794,12 @@ const MessageTray = new Lang.Class({
y == monitor.y + monitor.height - 1); y == monitor.y + monitor.height - 1);
if (shouldDwell) { if (shouldDwell) {
// We only set up dwell timeout when the user is not hovering over the tray // 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 // 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 // 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), // 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. // 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 // Save the interaction timestamp so we can detect user input
let focusWindow = global.display.focus_window; let focusWindow = global.display.focus_window;
this._trayDwellUserTime = focusWindow ? focusWindow.user_time : 0; 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); this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount);
} }
if (!source.trayIcon && !source.isChat && !source.resident)
this.clearableCount++;
this._sources.set(source, obj); this._sources.set(source, obj);
obj.notifyId = source.connect('notify', Lang.bind(this, this._onNotify)); obj.notifyId = source.connect('notify', Lang.bind(this, this._onNotify));
@@ -1937,6 +1941,9 @@ const MessageTray = new Lang.Class({
if (source.isChat) if (source.isChat)
this._chatSummaryItemsCount--; this._chatSummaryItemsCount--;
if (!source.trayIcon && !source.isChat && !source.resident)
this.clearableCount--;
source.disconnect(obj.notifyId); source.disconnect(obj.notifyId);
source.disconnect(obj.destroyId); source.disconnect(obj.destroyId);
source.disconnect(obj.mutedChangedId); source.disconnect(obj.mutedChangedId);
@@ -2021,6 +2028,7 @@ const MessageTray = new Lang.Class({
hide: function() { hide: function() {
this._traySummoned = false; this._traySummoned = false;
this.actor.set_hover(false);
this._updateState(); this._updateState();
}, },
@@ -2087,21 +2095,25 @@ const MessageTray = new Lang.Class({
this._grabHelper.addActor(corner.actor); this._grabHelper.addActor(corner.actor);
}, },
_onNotificationHoverChanged: function() { _onTrayHoverChanged: function() {
if (this._notificationWidget.hover == this._notificationHovered) if (this.actor.hover == this._trayHovered)
return; return;
this._notificationHovered = this._notificationWidget.hover; this._trayHovered = this.actor.hover;
if (this._notificationHovered) { if (this._trayHovered) {
// No dwell inside notifications at the bottom of the screen // No dwell inside notifications at the bottom of the screen
this._cancelTrayDwell(); this._cancelTrayDwell();
this._useLongerNotificationLeftTimeout = false; // Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
if (this._notificationLeftTimeoutId) { if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
Mainloop.source_remove(this._notificationLeftTimeoutId); return;
this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1; this._useLongerTrayLeftTimeout = false;
this._notificationLeftMouseY = -1; if (this._trayLeftTimeoutId) {
Mainloop.source_remove(this._trayLeftTimeoutId);
this._trayLeftTimeoutId = 0;
this._trayLeftMouseX = -1;
this._trayLeftMouseY = -1;
return; return;
} }
@@ -2110,32 +2122,32 @@ const MessageTray = new Lang.Class({
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, this._showNotificationMouseX, this._showNotificationMouseY); global.stage.get_actor_at_pos(Clutter.PickMode.ALL, this._showNotificationMouseX, this._showNotificationMouseY);
this._showNotificationMouseX = -1; this._showNotificationMouseX = -1;
this._showNotificationMouseY = -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 // 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 // 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 // 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. // timeout should be used before popping down the notification.
if (this.actor.contains(actorAtShowNotificationPosition)) { if (this.actor.contains(actorAtShowNotificationPosition)) {
this._useLongerNotificationLeftTimeout = true; this._useLongerTrayLeftTimeout = true;
return; return;
} }
} }
this._pointerInNotification = true; this._pointerInTray = true;
this._updateState(); this._updateState();
} else { } else {
// We record the position of the mouse the moment it leaves the tray. These coordinates are used in // 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 // 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. // close to its previous position, we extend the timeout once.
let [x, y, mods] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
this._notificationLeftMouseX = x; this._trayLeftMouseX = x;
this._notificationLeftMouseY = y; 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 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. // 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. // 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; let timeout = this._useLongerTrayLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout)); this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
} }
}, },
@@ -2159,22 +2171,22 @@ const MessageTray = new Lang.Class({
this._updateState(); this._updateState();
}, },
_onNotificationLeftTimeout: function() { _onTrayLeftTimeout: function() {
let [x, y, mods] = global.get_pointer(); 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 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, // 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. // is close to the tray.
if (this._notificationLeftMouseX > -1 && if (this._trayLeftMouseX > -1 &&
y > this._notificationLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD && y > this._trayLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD &&
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD && x < this._trayLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) { x > this._trayLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
this._notificationLeftMouseX = -1; this._trayLeftMouseX = -1;
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000, this._trayLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
Lang.bind(this, this._onNotificationLeftTimeout)); Lang.bind(this, this._onTrayLeftTimeout));
} else { } else {
this._notificationLeftTimeoutId = 0; this._trayLeftTimeoutId = 0;
this._useLongerNotificationLeftTimeout = false; this._useLongerTrayLeftTimeout = false;
this._pointerInNotification = false; this._pointerInTray = false;
this._updateNotificationTimeout(0); this._updateNotificationTimeout(0);
this._updateState(); this._updateState();
} }
@@ -2182,7 +2194,7 @@ const MessageTray = new Lang.Class({
}, },
_escapeTray: function() { _escapeTray: function() {
this._pointerInNotification = false; this._pointerInTray = false;
this._traySummoned = false; this._traySummoned = false;
this._setClickedSummaryItem(null); this._setClickedSummaryItem(null);
this._updateNotificationTimeout(0); this._updateNotificationTimeout(0);
@@ -2191,7 +2203,7 @@ const MessageTray = new Lang.Class({
// All of the logic for what happens when occurs here; the various // All of the logic for what happens when occurs here; the various
// event handlers merely update variables such as // 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 // _updateState() figures out what (if anything) needs to be done
// at the present time. // at the present time.
_updateState: function() { _updateState: function() {
@@ -2202,12 +2214,12 @@ const MessageTray = new Lang.Class({
let notificationsLimited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen; let notificationsLimited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen;
let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && Main.sessionMode.hasNotifications; let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && Main.sessionMode.hasNotifications;
let nextNotification = notificationQueue.length > 0 ? notificationQueue[0] : null; 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 notificationExpanded = this._notification && this._notification.expanded;
let notificationExpired = this._notificationTimeoutId == 0 && let notificationExpired = this._notificationTimeoutId == 0 &&
!(this._notification && this._notification.urgency == Urgency.CRITICAL) && !(this._notification && this._notification.urgency == Urgency.CRITICAL) &&
!(this._notification && this._notification.focused) && !(this._notification && this._notification.focused) &&
!this._pointerInNotification; !this._pointerInTray;
let notificationLockedOut = !Main.sessionMode.hasNotifications && this._notification; let notificationLockedOut = !Main.sessionMode.hasNotifications && this._notification;
let notificationMustClose = this._notificationRemoved || notificationLockedOut || (notificationExpired && this._userActiveWhileNotificationShown) || this._notificationClosed; let notificationMustClose = this._notificationRemoved || notificationLockedOut || (notificationExpired && this._userActiveWhileNotificationShown) || this._notificationClosed;
let canShowNotification = notificationsPending && this._trayState == State.HIDDEN; let canShowNotification = notificationsPending && this._trayState == State.HIDDEN;
@@ -2237,10 +2249,15 @@ const MessageTray = new Lang.Class({
let canShowSummaryBoxPointer = this._trayState == State.SHOWN; let canShowSummaryBoxPointer = this._trayState == State.SHOWN;
// We only have sources with empty notification stacks for legacy tray icons. Currently, we never attempt // 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. // 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 requestedNotificationStackIsEmpty = (haveClickedSummaryItem &&
let wrongSummaryNotificationStack = (this._clickedSummaryItemMouseButton == 1 && this._clickedSummaryItemMouseButton == 1 &&
this._clickedSummaryItem.source.notifications.length == 0);
let wrongSummaryNotificationStack = (haveClickedSummaryItem &&
this._clickedSummaryItemMouseButton == 1 &&
this._summaryBoxPointer.bin.child != this._clickedSummaryItem.notificationStackWidget); 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); this._summaryBoxPointer.bin.child != this._clickedSummaryItem.rightClickMenu);
let wrongSummaryBoxPointer = (haveClickedSummaryItem && let wrongSummaryBoxPointer = (haveClickedSummaryItem &&
(wrongSummaryNotificationStack || wrongSummaryRightClickMenu)); (wrongSummaryNotificationStack || wrongSummaryRightClickMenu));
@@ -2420,7 +2437,7 @@ const MessageTray = new Lang.Class({
let [x, y, mods] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
// We save the position of the mouse at the time when we started showing the notification // 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 // 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 // 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. // explicitly mouses away from it and then mouses back in.
this._showNotificationMouseX = x; this._showNotificationMouseX = x;
@@ -2482,13 +2499,13 @@ const MessageTray = new Lang.Class({
_notificationTimeout: function() { _notificationTimeout: function() {
let [x, y, mods] = global.get_pointer(); 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 // The mouse is moving towards the notification, so don't
// hide it yet. (We just create a new timeout (and destroy // hide it yet. (We just create a new timeout (and destroy
// the old one) each time because the bookkeeping is // the old one) each time because the bookkeeping is
// simpler.) // simpler.)
this._updateNotificationTimeout(1000); this._updateNotificationTimeout(1000);
} else if (this._useLongerNotificationLeftTimeout && !this._notificationLeftTimeoutId && } else if (this._useLongerTrayLeftTimeout && !this._trayLeftTimeoutId &&
(x != this._lastSeenMouseX || y != this._lastSeenMouseY)) { (x != this._lastSeenMouseX || y != this._lastSeenMouseY)) {
// Refresh the timeout if the notification originally // Refresh the timeout if the notification originally
// popped up under the pointer, and the pointer is hovering // popped up under the pointer, and the pointer is hovering
@@ -2532,12 +2549,12 @@ const MessageTray = new Lang.Class({
this._notificationUnfocusedId = 0; this._notificationUnfocusedId = 0;
} }
this._useLongerNotificationLeftTimeout = false; this._useLongerTrayLeftTimeout = false;
if (this._notificationLeftTimeoutId) { if (this._trayLeftTimeoutId) {
Mainloop.source_remove(this._notificationLeftTimeoutId); Mainloop.source_remove(this._trayLeftTimeoutId);
this._notificationLeftTimeoutId = 0; this._trayLeftTimeoutId = 0;
this._notificationLeftMouseX = -1; this._trayLeftMouseX = -1;
this._notificationLeftMouseY = -1; this._trayLeftMouseY = -1;
} }
if (this._notificationRemoved) { if (this._notificationRemoved) {
@@ -2567,9 +2584,14 @@ const MessageTray = new Lang.Class({
if (notification.isTransient) if (notification.isTransient)
notification.destroy(NotificationDestroyedReason.EXPIRED); notification.destroy(NotificationDestroyedReason.EXPIRED);
this._closeButton.hide();
this._pointerInNotification = false;
this._notificationRemoved = 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._notificationBin.child = null;
this._notificationWidget.hide(); this._notificationWidget.hide();
}, },
@@ -2582,16 +2604,16 @@ const MessageTray = new Lang.Class({
}, },
_expandNotification: function(autoExpanding) { _expandNotification: function(autoExpanding) {
// Don't focus notifications that are auto-expanding.
if (!autoExpanding)
this._ensureNotificationFocused();
if (!this._notificationExpandedId) if (!this._notificationExpandedId)
this._notificationExpandedId = this._notificationExpandedId =
this._notification.connect('expanded', this._notification.connect('expanded',
Lang.bind(this, this._onNotificationExpanded)); Lang.bind(this, this._onNotificationExpanded));
// Don't animate changes in notifications that are auto-expanding. // Don't animate changes in notifications that are auto-expanding.
this._notification.expand(!autoExpanding); this._notification.expand(!autoExpanding);
// Don't focus notifications that are auto-expanding.
if (!autoExpanding)
this._ensureNotificationFocused();
}, },
_onNotificationExpanded: function() { _onNotificationExpanded: function() {
@@ -2660,7 +2682,7 @@ const MessageTray = new Lang.Class({
} }
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child, this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
modal: true, grabFocus: true,
onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) }); onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) });
this._summaryBoxPointer.actor.opacity = 0; this._summaryBoxPointer.actor.opacity = 0;

View File

@@ -22,6 +22,10 @@ const Tweener = imports.ui.tweener;
const OPEN_AND_CLOSE_TIME = 0.1; const OPEN_AND_CLOSE_TIME = 0.1;
const FADE_OUT_DIALOG_TIME = 1.0; 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 = { const State = {
OPENED: 0, OPENED: 0,
CLOSED: 1, 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-press-event', Lang.bind(this, this._onKeyPressEvent));
this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent)); 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._monitorConstraint = new Layout.MonitorConstraint();
this._backgroundBin.add_constraint(this._monitorConstraint); this._backgroundBin.add_constraint(this._monitorConstraint);
this._group.add_actor(this._backgroundBin); this._group.add_actor(this._backgroundBin);
@@ -81,15 +87,10 @@ const ModalDialog = new Lang.Class({
{ inhibitEvents: true }); { inhibitEvents: true });
this._lightbox.highlight(this._backgroundBin); this._lightbox.highlight(this._backgroundBin);
let stack = new Shell.Stack();
this._backgroundBin.child = stack;
this._eventBlocker = new Clutter.Actor({ reactive: true }); this._eventBlocker = new Clutter.Actor({ reactive: true });
stack.add_actor(this._eventBlocker); this.backgroundStack.add_actor(this._eventBlocker);
stack.add_actor(this.dialogLayout);
} else {
this._backgroundBin.child = this.dialogLayout;
} }
this.backgroundStack.add_actor(this.dialogLayout);
this.contentLayout = new St.BoxLayout({ vertical: true }); this.contentLayout = new St.BoxLayout({ vertical: true });
@@ -110,6 +111,8 @@ const ModalDialog = new Lang.Class({
this._initialKeyFocus = this.dialogLayout; this._initialKeyFocus = this.dialogLayout;
this._initialKeyFocusDestroyId = 0; this._initialKeyFocusDestroyId = 0;
this._savedKeyFocus = null; this._savedKeyFocus = null;
this._workSpinner = null;
}, },
destroy: function() { destroy: function() {
@@ -183,6 +186,44 @@ const ModalDialog = new Lang.Class({
return button; 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) { _onKeyPressEvent: function(object, event) {
this._pressedKey = event.get_key_symbol(); this._pressedKey = event.get_key_symbol();
}, },

View File

@@ -8,6 +8,7 @@ const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Meta = imports.gi.Meta;
const HIDE_TIMEOUT = 1500; const HIDE_TIMEOUT = 1500;
const FADE_TIME = 0.1; const FADE_TIME = 0.1;
@@ -71,6 +72,7 @@ const OsdWindow = new Lang.Class({
Name: 'OsdWindow', Name: 'OsdWindow',
_init: function() { _init: function() {
this._popupSize = 0;
this.actor = new St.Widget({ x_expand: true, this.actor = new St.Widget({ x_expand: true,
y_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
@@ -80,6 +82,15 @@ const OsdWindow = new Lang.Class({
vertical: true }); vertical: true });
this.actor.add_actor(this._box); 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._icon = new St.Icon();
this._box.add(this._icon, { expand: true }); this._box.add(this._icon, { expand: true });
@@ -125,8 +136,10 @@ const OsdWindow = new Lang.Class({
return; return;
if (!this.actor.visible) { if (!this.actor.visible) {
Meta.disable_unredirect_for_screen(global.screen);
this.actor.show(); this.actor.show();
this.actor.opacity = 0; this.actor.opacity = 0;
this.actor.get_parent().set_child_above_sibling(this.actor, null);
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
{ opacity: 255, { opacity: 255,
@@ -154,7 +167,11 @@ const OsdWindow = new Lang.Class({
{ opacity: 0, { opacity: 0,
time: FADE_TIME, time: FADE_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: Lang.bind(this, this._reset) }); onComplete: Lang.bind(this, function() {
this._reset();
Meta.enable_unredirect_for_screen(global.screen);
})
});
}, },
_reset: function() { _reset: function() {
@@ -169,11 +186,25 @@ const OsdWindow = new Lang.Class({
let scalew = monitor.width / 640.0; let scalew = monitor.width / 640.0;
let scaleh = monitor.height / 480.0; let scaleh = monitor.height / 480.0;
let scale = Math.min(scalew, scaleh); 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._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));
} }
}); });

View File

@@ -11,6 +11,7 @@ const Shell = imports.gi.Shell;
const Gdk = imports.gi.Gdk; const Gdk = imports.gi.Gdk;
const Background = imports.ui.background; const Background = imports.ui.background;
const Dash = imports.ui.dash;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const LayoutManager = imports.ui.layout; const LayoutManager = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -19,6 +20,7 @@ const OverviewControls = imports.ui.overviewControls;
const Panel = imports.ui.panel; const Panel = imports.ui.panel;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail; const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode // 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 // and don't want the shading animation to get cut off
const SHADE_ANIMATION_TIME = .20; const SHADE_ANIMATION_TIME = .20;
const DND_WINDOW_SWITCH_TIMEOUT = 1250; const DND_WINDOW_SWITCH_TIMEOUT = 750;
const OVERVIEW_ACTIVATION_TIMEOUT = 0.5; const OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
@@ -131,6 +133,14 @@ const Overview = new Lang.Class({
y_expand: true }); y_expand: true });
this._overview._delegate = this; 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(); this._backgroundGroup = new Meta.BackgroundGroup();
global.overlay_group.add_child(this._backgroundGroup); global.overlay_group.add_child(this._backgroundGroup);
this._backgroundGroup.hide(); this._backgroundGroup.hide();
@@ -167,6 +177,7 @@ const Overview = new Lang.Class({
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd)); Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
global.screen.connect('restacked', Lang.bind(this, this._onRestacked)); global.screen.connect('restacked', Lang.bind(this, this._onRestacked));
this._group.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this._windowSwitchTimeoutId = 0; this._windowSwitchTimeoutId = 0;
this._windowSwitchTimestamp = 0; this._windowSwitchTimestamp = 0;
@@ -265,13 +276,28 @@ const Overview = new Lang.Class({
this._overview.add_actor(this._searchEntryBin); this._overview.add_actor(this._searchEntryBin);
// Create controls // Create controls
this._controls = new OverviewControls.ControlsManager(this._searchEntry); this._dash = new Dash.Dash();
this._dash = this._controls.dash; this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
this._viewSelector = this._controls.viewSelector; 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 // Add our same-line elements after the search entry
this._overview.add(this._controls.actor, { y_fill: true, expand: true }); this._overview.add(this._groupStack, { y_fill: true, expand: true });
this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this._stack.add_actor(this._controls.indicatorActor); this._stack.add_actor(this._controls.indicatorActor);
@@ -435,6 +461,7 @@ const Overview = new Lang.Class({
beginItemDrag: function(source) { beginItemDrag: function(source) {
this.emit('item-drag-begin'); this.emit('item-drag-begin');
this._inDrag = true;
}, },
cancelledItemDrag: function(source) { cancelledItemDrag: function(source) {
@@ -443,10 +470,12 @@ const Overview = new Lang.Class({
endItemDrag: function(source) { endItemDrag: function(source) {
this.emit('item-drag-end'); this.emit('item-drag-end');
this._inDrag = false;
}, },
beginWindowDrag: function(source) { beginWindowDrag: function(source) {
this.emit('window-drag-begin'); this.emit('window-drag-begin');
this._inDrag = true;
}, },
cancelledWindowDrag: function(source) { cancelledWindowDrag: function(source) {
@@ -455,6 +484,7 @@ const Overview = new Lang.Class({
endWindowDrag: function(source) { endWindowDrag: function(source) {
this.emit('window-drag-end'); this.emit('window-drag-end');
this._inDrag = false;
}, },
// show: // show:
@@ -473,6 +503,11 @@ const Overview = new Lang.Class({
this._animateVisible(); this._animateVisible();
}, },
focusSearch: function() {
this.show();
this._searchEntry.grab_key_focus();
},
fadeInDesktop: function() { fadeInDesktop: function() {
this._desktopFade.opacity = 0; this._desktopFade.opacity = 0;
this._desktopFade.show(); this._desktopFade.show();
@@ -578,6 +613,8 @@ const Overview = new Lang.Class({
shouldToggleByCornerOrButton: function() { shouldToggleByCornerOrButton: function() {
if (this.animationInProgress) if (this.animationInProgress)
return false; return false;
if (this._inDrag)
return false;
if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT) if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
return true; return true;
return false; return false;

View File

@@ -6,12 +6,10 @@ const Meta = imports.gi.Meta;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Dash = imports.ui.dash;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector; const ViewSelector = imports.ui.viewSelector;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
const SIDE_CONTROLS_ANIMATION_TIME = 0.16; const SIDE_CONTROLS_ANIMATION_TIME = 0.16;
@@ -271,11 +269,6 @@ const ThumbnailsSlider = new Lang.Class({
return alwaysZoomOut; return alwaysZoomOut;
}, },
getNonExpandedWidth: function() {
let child = this.actor.get_first_child();
return child.get_theme_node().get_length('visible-width');
},
getSlide: function() { getSlide: function() {
if (!this.visible) if (!this.visible)
return 0; return 0;
@@ -287,16 +280,18 @@ const ThumbnailsSlider = new Lang.Class({
let child = this.actor.get_first_child(); let child = this.actor.get_first_child();
let preferredHeight = child.get_preferred_height(-1)[1]; let preferredHeight = child.get_preferred_height(-1)[1];
let expandedWidth = child.get_preferred_width(preferredHeight)[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() { getVisibleWidth: function() {
let alwaysZoomOut = this._getAlwaysZoomOut(); let alwaysZoomOut = this._getAlwaysZoomOut();
if (alwaysZoomOut) if (alwaysZoomOut)
return this.parent(); 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 // available allocation
this._dash.actor.x_expand = true; this._dash.actor.x_expand = true;
this._dash.actor.y_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.actor.add_actor(this._dash.actor);
this._dash.connect('icon-size-changed', Lang.bind(this, this.updateSlide)); 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({ const ControlsManager = new Lang.Class({
Name: 'ControlsManager', Name: 'ControlsManager',
_init: function(searchEntry) { _init: function(dash, thumbnails, viewSelector) {
this.dash = new Dash.Dash(); this._dashSlider = new DashSlider(dash);
this._dashSlider = new DashSlider(this.dash); this.dashActor = this._dashSlider.actor;
this._dashSpacer = new DashSpacer(); this.dashSpacer = new DashSpacer();
this._dashSpacer.setDashActor(this._dashSlider.actor); this.dashSpacer.setDashActor(this.dashActor);
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox(); this._thumbnailsSlider = new ThumbnailsSlider(thumbnails);
this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox); this.thumbnailsActor = this._thumbnailsSlider.actor;
this.viewSelector = new ViewSelector.ViewSelector(searchEntry, this._indicator = new MessagesIndicator(viewSelector);
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.indicatorActor = this._indicator.actor; this.indicatorActor = this._indicator.actor;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(), this._viewSelector = viewSelector;
x_expand: true, y_expand: true, this._viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
clip_to_allocation: true }); this._viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
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));
Main.overview.connect('showing', Lang.bind(this, this._updateSpacerVisibility)); Main.overview.connect('showing', Lang.bind(this, this._updateSpacerVisibility));
Main.overview.connect('item-drag-begin', Lang.bind(this, Main.overview.connect('item-drag-begin', Lang.bind(this,
function() { function() {
let activePage = this.viewSelector.getActivePage(); let activePage = this._viewSelector.getActivePage();
if (activePage != ViewSelector.ViewPage.WINDOWS) if (activePage != ViewSelector.ViewPage.WINDOWS)
this.viewSelector.fadeHalf(); this._viewSelector.fadeHalf();
})); }));
Main.overview.connect('item-drag-end', Lang.bind(this, Main.overview.connect('item-drag-end', Lang.bind(this,
function() { function() {
this.viewSelector.fadeIn(); this._viewSelector.fadeIn();
})); }));
Main.overview.connect('item-drag-cancelled', Lang.bind(this, Main.overview.connect('item-drag-cancelled', Lang.bind(this,
function() { 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() { _setVisibility: function() {
// Ignore the case when we're leaving the overview, since // Ignore the case when we're leaving the overview, since
// actors will be made visible again when entering the overview // 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)) (Main.overview.animationInProgress && !Main.overview.visibleTarget))
return; return;
let activePage = this.viewSelector.getActivePage(); let activePage = this._viewSelector.getActivePage();
let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS || let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS ||
activePage == ViewSelector.ViewPage.APPS); activePage == ViewSelector.ViewPage.APPS);
let thumbnailsVisible = (activePage == ViewSelector.ViewPage.WINDOWS); let thumbnailsVisible = (activePage == ViewSelector.ViewPage.WINDOWS);
@@ -588,8 +541,8 @@ const ControlsManager = new Lang.Class({
if (Main.overview.animationInProgress && !Main.overview.visibleTarget) if (Main.overview.animationInProgress && !Main.overview.visibleTarget)
return; return;
let activePage = this.viewSelector.getActivePage(); let activePage = this._viewSelector.getActivePage();
this._dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS); this.dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS);
}, },
_onPageEmpty: function() { _onPageEmpty: function() {

View File

@@ -371,13 +371,16 @@ const AppMenuButton = new Lang.Class({
this._updateIconBoxClip(); 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() { _onIconThemeChanged: function() {
if (this._iconBox.child == null) if (this._iconBox.child == null)
return; return;
this._iconBox.child.destroy(); this._syncIcon();
let icon = this._targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
this._iconBox.set_child(icon);
}, },
_updateIconBoxClip: function() { _updateIconBoxClip: function() {
@@ -568,14 +571,9 @@ const AppMenuButton = new Lang.Class({
} }
if (targetApp == this._targetApp) { if (targetApp == this._targetApp) {
if (targetApp && if (targetApp && targetApp.get_state() != Shell.AppState.STARTING) {
targetApp.get_state() != Shell.AppState.STARTING &&
targetApp.get_state() != Shell.AppState.BUSY) {
this.stopAnimation(); this.stopAnimation();
this._maybeSetMenu(); this._maybeSetMenu();
} else if (targetApp &&
targetApp.get_state() == Shell.AppState.BUSY) {
this.startAnimation();
} }
return; return;
} }
@@ -600,16 +598,13 @@ const AppMenuButton = new Lang.Class({
} }
this._targetApp = targetApp; this._targetApp = targetApp;
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
this._label.setText(targetApp.get_name()); this._label.setText(targetApp.get_name());
this.setName(targetApp.get_name()); this.setName(targetApp.get_name());
this._iconBox.set_child(icon); this._syncIcon();
this._iconBox.show(); this._iconBox.show();
if (targetApp.get_state() == Shell.AppState.STARTING || if (targetApp.get_state() == Shell.AppState.STARTING)
targetApp.get_state() == Shell.AppState.BUSY)
this.startAnimation(); this.startAnimation();
else else
this._maybeSetMenu(); this._maybeSetMenu();
@@ -929,7 +924,6 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
'volume': imports.ui.status.volume.Indicator, 'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator, 'battery': imports.ui.status.power.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator, 'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
'logo': imports.gdm.loginDialog.LogoMenuButton,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator, 'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton, 'powerMenu': imports.gdm.powerMenu.PowerMenuButton,
'userMenu': imports.ui.userMenu.UserMenuButton 'userMenu': imports.ui.userMenu.UserMenuButton

View File

@@ -19,12 +19,6 @@ const Tweener = imports.ui.tweener;
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */ const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
const Ornament = {
NONE: 0,
DOT: 1,
CHECK: 2,
};
function _ensureStyle(actor) { function _ensureStyle(actor) {
if (actor.get_children) { if (actor.get_children) {
let children = actor.get_children(); let children = actor.get_children();
@@ -59,9 +53,7 @@ const PopupBaseMenuItem = new Lang.Class({
this.actor._delegate = this; this.actor._delegate = this;
this._children = []; this._children = [];
this._ornament = Ornament.NONE; this._dot = null;
this._ornamentLabel = new St.Label({ style_class: 'popup-menu-ornament' });
this.actor.add_actor(this._ornamentLabel);
this._columnWidths = null; this._columnWidths = null;
this._spacing = 0; this._spacing = 0;
this.active = false; this.active = false;
@@ -184,24 +176,40 @@ const PopupBaseMenuItem = new Lang.Class({
this._removeChild(child); this._removeChild(child);
}, },
setOrnament: function(ornament) { setShowDot: function(show) {
if (ornament == this._ornament) if (show) {
return; 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._dot.destroy();
this._ornamentLabel.text = '\u2022'; this._dot = null;
this.actor.add_accessible_state(Atk.StateType.CHECKED); this.actor.remove_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);
} }
}, },
_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 // This returns column widths in logical order (i.e. from the dot
// to the image), not in visual order (left to right) // to the image), not in visual order (left to right)
getColumnWidths: function() { getColumnWidths: function() {
@@ -272,25 +280,26 @@ const PopupBaseMenuItem = new Lang.Class({
let height = box.y2 - box.y1; let height = box.y2 - box.y1;
let direction = this.actor.get_text_direction(); let direction = this.actor.get_text_direction();
// The ornament is placed outside box if (this._dot) {
// one quarter of padding from the border of the container // The dot is placed outside box
// (so 3/4 from the inner border) // one quarter of padding from the border of the container
// (padding is box.x1) // (so 3/4 from the inner border)
let ornamentBox = new Clutter.ActorBox(); // (padding is box.x1)
let ornamentWidth = box.x1; let dotBox = new Clutter.ActorBox();
let dotWidth = Math.round(box.x1 / 2);
ornamentBox.x1 = 0; if (direction == Clutter.TextDirection.LTR) {
ornamentBox.x2 = ornamentWidth; dotBox.x1 = Math.round(box.x1 / 4);
ornamentBox.y1 = box.y1; dotBox.x2 = dotBox.x1 + dotWidth;
ornamentBox.y2 = box.y2; } else {
dotBox.x2 = box.x2 + 3 * Math.round(box.x1 / 4);
if (direction == Clutter.TextDirection.RTL) { dotBox.x1 = dotBox.x2 - dotWidth;
ornamentBox.x1 += box.x2; }
ornamentBox.x2 += box.x2; 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; let x;
if (direction == Clutter.TextDirection.LTR) if (direction == Clutter.TextDirection.LTR)
x = box.x1; x = box.x1;
@@ -544,6 +553,10 @@ const PopupSliderMenuItem = new Lang.Class({
let handleRadius = themeNode.get_length('-slider-handle-radius'); 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 sliderWidth = width - 2 * handleRadius;
let sliderHeight = themeNode.get_length('-slider-height'); let sliderHeight = themeNode.get_length('-slider-height');
@@ -595,7 +608,16 @@ const PopupSliderMenuItem = new Lang.Class({
color.blue / 255, color.blue / 255,
color.alpha / 255); color.alpha / 255);
cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI); 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(); cr.$dispose();
}, },
@@ -1466,12 +1488,23 @@ const PopupMenuSection = new Lang.Class({
this.actor = this.box; this.actor = this.box;
this.actor._delegate = this; this.actor._delegate = this;
this.isOpen = true; this.isOpen = true;
// an array of externally managed separators
this.separators = [];
}, },
// deliberately ignore any attempt to open() or close(), but emit the // deliberately ignore any attempt to open() or close(), but emit the
// corresponding signal so children can still pick it up // corresponding signal so children can still pick it up
open: function() { this.emit('open-state-changed', true); }, open: function() { this.emit('open-state-changed', true); },
close: function() { this.emit('open-state-changed', false); }, 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({ const PopupSubMenuMenuItem = new Lang.Class({
@@ -1788,11 +1821,13 @@ const RemoteMenu = new Lang.Class({
this.model = model; this.model = model;
this.actionGroup = actionGroup; this.actionGroup = actionGroup;
this._actions = {}; this._actions = { };
this._trackMenu(model, this); 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._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._actionEnableChangeId = this.actionGroup.connect('action-enabled-changed', Lang.bind(this, this._actionEnabledChanged));
this._skipSignalConnection = false;
}, },
destroy: function() { destroy: function() {
@@ -1809,8 +1844,39 @@ const RemoteMenu = new Lang.Class({
this.parent(); this.parent();
}, },
_actionAdded: function(model, item, index) { _createMenuItem: function(model, index) {
let action_id = item.action_id; 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]) if (!this._actions[action_id])
this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id), this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id),
@@ -1818,7 +1884,7 @@ const RemoteMenu = new Lang.Class({
items: [ ], items: [ ],
}; };
let action = this._actions[action_id]; let action = this._actions[action_id];
let target, destroyId, specificSignalId; let item, target, destroyId, specificSignalId;
if (action.state) { if (action.state) {
// Docs have get_state_hint(), except that the DBus protocol // 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())) { switch (String.fromCharCode(action.state.classify())) {
case 'b': case 'b':
item = new PopupSwitchMenuItem(label, action.state.get_boolean());
action.items.push(item); action.items.push(item);
item.setOrnament(action.state.get_boolean() ? specificSignalId = item.connect('toggled', Lang.bind(this, function(item) {
Ornament.CHECK : Ornament.NONE);
specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
this.actionGroup.activate_action(action_id, null); this.actionGroup.activate_action(action_id, null);
})); }));
break; break;
case 's': 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._remoteTarget = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null).deep_unpack();
item.setOrnament(action.state.deep_unpack() == item._remoteTarget ? action.items.push(item);
Ornament.DOT : Ornament.NONE); item.setShowDot(action.state.deep_unpack() == item._remoteTarget);
specificSignalId = item.connect('activate', Lang.bind(this, function(item) { specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget)); this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget));
})); }));
break; break;
default: default:
log('Action "%s" has state of type %s, which is not supported'.format(action_id, action.state.get_type_string())); 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 { } else {
target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null); target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null);
item = new PopupMenuItem(label);
action.items.push(item); action.items.push(item);
specificSignalId = item.connect('activate', Lang.bind(this, function() { specificSignalId = item.connect('activate', Lang.bind(this, function() {
this.actionGroup.activate_action(action_id, target); this.actionGroup.activate_action(action_id, target);
@@ -1867,52 +1933,97 @@ const RemoteMenu = new Lang.Class({
if (pos != -1) if (pos != -1)
action.items.splice(pos, 1); action.items.splice(pos, 1);
})); }));
return [item, false, ''];
}, },
_trackMenu: function(model, item) { _modelChanged: function(model, position, removed, added, target) {
item._tracker = Shell.MenuTracker.new(model, let j, k;
null, /* action namespace */ let j0, k0;
Lang.bind(this, this._insertItem, item),
Lang.bind(this, this._removeItem, item));
item.connect('destroy', function() { let currentItems = target._getMenuItems();
item._tracker.destroy();
item._tracker = null;
});
},
_createMenuItem: function(model, index) { k0 = 0;
let labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null); // skip ignored items at the beginning
let label = labelValue ? labelValue.deep_unpack() : ''; while (k0 < currentItems.length && currentItems[k0]._ignored)
// remove all underscores that are not followed by another underscore k0++;
label = label.replace(/_([^_])/, '$1'); // find the right menu item matching the model item
for (j0 = 0; k0 < currentItems.length && j0 < position; j0++, k0++) {
let submenuModel = model.get_item_link(index, Gio.MENU_LINK_SUBMENU); if (currentItems[k0]._ignored)
if (submenuModel) { k0++;
let item = new PopupSubMenuMenuItem(label);
this._trackMenu(submenuModel, item.menu);
return item;
} }
let item = new PopupMenuItem(label); if (removed == -1) {
let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack(); // special flag to indicate we should destroy everything
item.actor.can_focus = item.actor.reactive = false; 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 (currentItems[k]._ignored)
j--;
if (this.actionGroup.has_action(action_id)) { }
this._actionAdded(model, item, index);
return item;
} }
let signalId = this.actionGroup.connect('action-added', Lang.bind(this, function(actionGroup, actionName) { for (j = j0, k = k0; j < j0 + added; j++, k++) {
actionGroup.disconnect(signalId); let [item, addSeparator, changeSignal] = this._createMenuItem(model, j);
if (this._actions[actionName]) return;
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) { _actionStateChanged: function(actionGroup, action_id) {
@@ -1925,8 +2036,7 @@ const RemoteMenu = new Lang.Class({
switch (String.fromCharCode(action.state.classify())) { switch (String.fromCharCode(action.state.classify())) {
case 'b': case 'b':
for (let i = 0; i < action.items.length; i++) for (let i = 0; i < action.items.length; i++)
action.items[i].setOrnament(action.state.get_boolean() ? action.items[i].setToggleState(action.state.get_boolean());
Ornament.CHECK : Ornament.NONE);
break; break;
case 'd': case 'd':
for (let i = 0; i < action.items.length; i++) for (let i = 0; i < action.items.length; i++)
@@ -1934,8 +2044,7 @@ const RemoteMenu = new Lang.Class({
break; break;
case 's': case 's':
for (let i = 0; i < action.items.length; i++) for (let i = 0; i < action.items.length; i++)
action.items[i].setOrnament(action.items[i]._remoteTarget == action.state.deep_unpack() ? action.items[i].setShowDot(action.items[i]._remoteTarget == action.state.deep_unpack());
Ornament.DOT : Ornament.NONE);
} }
} }
}, },
@@ -1952,23 +2061,7 @@ const RemoteMenu = new Lang.Class({
item.actor.reactive = item.actor.can_focus = action.enabled; 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. /* Basic implementation of a menu manager.
@@ -2013,7 +2106,7 @@ const PopupMenuManager = new Lang.Class({
removeMenu: function(menu) { removeMenu: function(menu) {
if (menu == this.activeMenu) if (menu == this.activeMenu)
this._closeMenu(menu); this._closeMenu(false, menu);
let position = this._findMenu(menu); let position = this._findMenu(menu);
if (position == -1) // not a menu we manage if (position == -1) // not a menu we manage
@@ -2049,7 +2142,7 @@ const PopupMenuManager = new Lang.Class({
_onMenuOpenState: function(menu, open) { _onMenuOpenState: function(menu, open) {
if (open) { if (open) {
if (this.activeMenu) if (this.activeMenu && !this.activeMenu.isChildMenu(menu))
this.activeMenu.close(BoxPointer.PopupAnimation.FADE); this.activeMenu.close(BoxPointer.PopupAnimation.FADE);
this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor, this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor,
onUngrab: Lang.bind(this, this._closeMenu, menu) }); onUngrab: Lang.bind(this, this._closeMenu, menu) });

View File

@@ -187,9 +187,7 @@ const RemoteSearchProvider = new Lang.Class({
createIcon: function(size, meta) { createIcon: function(size, meta) {
let gicon; let gicon;
if (meta['icon']) { if (meta['gicon']) {
gicon = Gio.icon_deserialize(meta['icon']);
} else if (meta['gicon']) {
gicon = Gio.icon_new_for_string(meta['gicon']); gicon = Gio.icon_new_for_string(meta['gicon']);
} else if (meta['icon-data']) { } else if (meta['icon-data']) {
let [width, height, rowStride, hasAlpha, let [width, height, rowStride, hasAlpha,
@@ -242,12 +240,8 @@ const RemoteSearchProvider = new Lang.Class({
let metas = results[0]; let metas = results[0];
let resultMetas = []; let resultMetas = [];
for (let i = 0; i < metas.length; i++) { for (let i = 0; i < metas.length; i++) {
for (let prop in metas[i]) { for (let prop in metas[i])
// we can use the serialized icon variant directly metas[i][prop] = metas[i][prop].deep_unpack();
if (prop != 'icon')
metas[i][prop] = metas[i][prop].deep_unpack();
}
resultMetas.push({ id: metas[i]['id'], resultMetas.push({ id: metas[i]['id'],
name: metas[i]['name'], name: metas[i]['name'],
description: metas[i]['description'], description: metas[i]['description'],

View File

@@ -478,6 +478,7 @@ const ScreenShield = new Lang.Class({
this._lockDialogGroup = new St.Widget({ x_expand: true, this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: true, y_expand: true,
reactive: true,
opacity: 0, opacity: 0,
pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }), pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
name: 'lockDialogGroup' }); name: 'lockDialogGroup' });
@@ -709,6 +710,8 @@ const ScreenShield = new Lang.Class({
}, },
_onDragEnd: function(action, actor, eventX, eventY, modifiers) { _onDragEnd: function(action, actor, eventX, eventY, modifiers) {
if (this._lockScreenState != MessageTray.State.HIDING)
return;
if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) { if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) {
// Complete motion automatically // Complete motion automatically
let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0); let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
@@ -1115,6 +1118,9 @@ const ScreenShield = new Lang.Class({
deactivate: function(animate) { deactivate: function(animate) {
this._hideLockScreen(animate, 0); this._hideLockScreen(animate, 0);
if (this._hasLockScreen)
this._clearLockScreen();
if (Main.sessionMode.currentMode == 'lock-screen') if (Main.sessionMode.currentMode == 'lock-screen')
Main.sessionMode.popMode('lock-screen'); Main.sessionMode.popMode('lock-screen');
if (Main.sessionMode.currentMode == 'unlock-dialog') if (Main.sessionMode.currentMode == 'unlock-dialog')
@@ -1131,9 +1137,6 @@ const ScreenShield = new Lang.Class({
}, },
_completeDeactivate: function() { _completeDeactivate: function() {
if (this._hasLockScreen)
this._clearLockScreen();
if (this._dialog && !this._isGreeter) { if (this._dialog && !this._isGreeter) {
this._dialog.destroy(); this._dialog.destroy();
this._dialog = null; this._dialog = null;
@@ -1200,6 +1203,12 @@ const ScreenShield = new Lang.Class({
return; 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._isLocked = true;
this.activate(animate); this.activate(animate);

140
js/ui/screencast.js Normal file
View 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]));
}
});

View File

@@ -16,6 +16,7 @@ const _modes = {
'restrictive': { 'restrictive': {
parentMode: null, parentMode: null,
stylesheetName: 'gnome-shell.css', stylesheetName: 'gnome-shell.css',
overridesSchema: 'org.gnome.shell.overrides',
hasOverview: false, hasOverview: false,
showCalendarEvents: false, showCalendarEvents: false,
allowSettings: false, allowSettings: false,
@@ -45,7 +46,7 @@ const _modes = {
unlockDialog: imports.gdm.loginDialog.LoginDialog, unlockDialog: imports.gdm.loginDialog.LoginDialog,
components: ['polkitAgent'], components: ['polkitAgent'],
panel: { panel: {
left: ['logo'], left: [],
center: ['dateMenu'], center: ['dateMenu'],
right: ['a11yGreeter', 'display', 'keyboard', right: ['a11yGreeter', 'display', 'keyboard',
'volume', 'battery', 'powerMenu'] 'volume', 'battery', 'powerMenu']
@@ -84,7 +85,7 @@ const _modes = {
components: ['networkAgent', 'keyring'], components: ['networkAgent', 'keyring'],
panel: { panel: {
left: [], left: [],
center: [], center: ['dateMenu'],
right: ['a11yGreeter', 'keyboard', 'volume', 'battery'] right: ['a11yGreeter', 'keyboard', 'volume', 'battery']
} }
}, },
@@ -195,6 +196,10 @@ const SessionMode = new Lang.Class({
return this._modeStack[this._modeStack.length - 1]; return this._modeStack[this._modeStack.length - 1];
}, },
get allowScreencast() {
return this.components.indexOf('recorder') != -1;
},
_sync: function() { _sync: function() {
let params = this._modes[this.currentMode]; let params = this._modes[this.currentMode];
let defaults; let defaults;

View File

@@ -12,6 +12,7 @@ const ExtensionDownloader = imports.ui.extensionDownloader;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Hash = imports.misc.hash; const Hash = imports.misc.hash;
const Main = imports.ui.main; const Main = imports.ui.main;
const Screencast = imports.ui.screencast;
const Screenshot = imports.ui.screenshot; const Screenshot = imports.ui.screenshot;
const GnomeShellIface = <interface name="org.gnome.Shell"> 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="b" direction="out" name="success" />
<arg type="s" direction="out" name="result" /> <arg type="s" direction="out" name="result" />
</method> </method>
<method name="FocusSearch"/>
<method name="ShowOSD"> <method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/> <arg type="a{sv}" direction="in" name="params"/>
</method> </method>
@@ -70,6 +72,7 @@ const GnomeShell = new Lang.Class({
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
this._extensionsService = new GnomeShellExtensions(); this._extensionsService = new GnomeShellExtensions();
this._screencastService = new Screencast.ScreencastService();
this._screenshotService = new Screenshot.ScreenshotService(); this._screenshotService = new Screenshot.ScreenshotService();
this._grabbedAccelerators = new Hash.Map(); this._grabbedAccelerators = new Hash.Map();
@@ -114,6 +117,10 @@ const GnomeShell = new Lang.Class({
return [success, returnValue]; return [success, returnValue];
}, },
FocusSearch: function() {
Main.overview.focusSearch();
},
ShowOSD: function(params) { ShowOSD: function(params) {
for (let param in params) for (let param in params)
params[param] = params[param].deep_unpack(); params[param] = params[param].deep_unpack();

View File

@@ -14,9 +14,7 @@ const EntryMenu = new Lang.Class({
Name: 'ShellEntryMenu', Name: 'ShellEntryMenu',
Extends: PopupMenu.PopupMenu, Extends: PopupMenu.PopupMenu,
_init: function(entry, params) { _init: function(entry) {
params = Params.parse (params, { isPassword: false });
this.parent(entry, 0, St.Side.TOP); this.parent(entry, 0, St.Side.TOP);
this.actor.add_style_class_name('entry-context-menu'); this.actor.add_style_class_name('entry-context-menu');
@@ -37,8 +35,6 @@ const EntryMenu = new Lang.Class({
this._pasteItem = item; this._pasteItem = item;
this._passwordItem = null; this._passwordItem = null;
if (params.isPassword)
this._makePasswordItem();
Main.uiGroup.add_actor(this.actor); Main.uiGroup.add_actor(this.actor);
this.actor.hide(); this.actor.hide();
@@ -53,19 +49,21 @@ const EntryMenu = new Lang.Class({
}, },
get isPassword() { get isPassword() {
return this._passwordItem != null; return this._passwordItem != null;
}, },
set isPassword(v) { set isPassword(v) {
if (v == this.isPassword) if (v == this.isPassword)
return; return;
if (v) if (v) {
this._makePasswordItem(); this._makePasswordItem();
else { this._entry.input_purpose = Gtk.InputPurpose.PASSWORD;
this._passwordItem.destroy(); } else {
this._passwordItem = null; this._passwordItem.destroy();
} this._passwordItem = null;
this._entry.input_purpose = Gtk.InputPurpose.FREE_FORM;
}
}, },
open: function(animate) { open: function(animate) {
@@ -155,7 +153,10 @@ function addContextMenu(entry, params) {
if (entry.menu) if (entry.menu)
return; 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 = new PopupMenu.PopupMenuManager({ actor: entry });
entry._menuManager.addMenu(entry.menu); entry._menuManager.addMenu(entry.menu);

View File

@@ -33,6 +33,33 @@ const KEY_INPUT_SOURCES = 'sources';
const INPUT_SOURCE_TYPE_XKB = 'xkb'; const INPUT_SOURCE_TYPE_XKB = 'xkb';
const INPUT_SOURCE_TYPE_IBUS = 'ibus'; 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({ const IBusManager = new Lang.Class({
Name: 'IBusManager', Name: 'IBusManager',
@@ -45,26 +72,24 @@ const IBusManager = new Lang.Class({
this._readyCallback = readyCallback; this._readyCallback = readyCallback;
this._candidatePopup = new IBusCandidatePopup.CandidatePopup(); this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._ibus = null;
this._panelService = null; this._panelService = null;
this._engines = {}; this._engines = {};
this._ready = false; this._ready = false;
this._registerPropertiesId = 0; this._registerPropertiesId = 0;
this._currentEngineName = null; this._currentEngineName = null;
this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS, this._ibus = IBus.Bus.new_async();
Gio.BusNameWatcherFlags.NONE, this._ibus.connect('connected', Lang.bind(this, this._onConnected));
Lang.bind(this, this._onNameAppeared), this._ibus.connect('disconnected', Lang.bind(this, this._clear));
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() { _clear: function() {
if (this._panelService) if (this._panelService)
this._panelService.destroy(); this._panelService.destroy();
if (this._ibus)
this._ibus.destroy();
this._ibus = null;
this._panelService = null; this._panelService = null;
this._candidatePopup.setPanelService(null); this._candidatePopup.setPanelService(null);
this._engines = {}; this._engines = {};
@@ -76,18 +101,12 @@ const IBusManager = new Lang.Class({
this._readyCallback(false); this._readyCallback(false);
}, },
_onNameAppeared: function() {
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
},
_onConnected: function() { _onConnected: function() {
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines)); this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
this._ibus.request_name_async(IBus.SERVICE_PANEL, this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, IBus.BusNameFlag.REPLACE_EXISTING,
-1, null, -1, null,
Lang.bind(this, this._initPanelService)); Lang.bind(this, this._initPanelService));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
}, },
_initEngines: function(ibus, result) { _initEngines: function(ibus, result) {
@@ -109,9 +128,6 @@ const IBusManager = new Lang.Class({
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(), this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL }); object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService); 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)); this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
// If an engine is already active we need to get its properties // 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) { 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) { _engineChanged: function(bus, engineName) {
if (!this._ready)
return;
this._currentEngineName = engineName; this._currentEngineName = engineName;
if (this._registerPropertiesId != 0) if (this._registerPropertiesId != 0)
@@ -337,14 +356,14 @@ const InputSourceIndicator = new Lang.Class({
Main.wm.addKeybinding('switch-input-source', Main.wm.addKeybinding('switch-input-source',
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }), new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES, Meta.KeyBindingFlags.REVERSES,
Shell.KeyBindingMode.ALL & ~Shell.KeyBindingMode.MESSAGE_TRAY, Shell.KeyBindingMode.ALL,
Lang.bind(this, this._switchInputSource)); Lang.bind(this, this._switchInputSource));
this._keybindingActionBackward = this._keybindingActionBackward =
Main.wm.addKeybinding('switch-input-source-backward', Main.wm.addKeybinding('switch-input-source-backward',
new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }), new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES | Meta.KeyBindingFlags.REVERSES |
Meta.KeyBindingFlags.REVERSED, Meta.KeyBindingFlags.REVERSED,
Shell.KeyBindingMode.ALL & ~Shell.KeyBindingMode.MESSAGE_TRAY, Shell.KeyBindingMode.ALL,
Lang.bind(this, this._switchInputSource)); Lang.bind(this, this._switchInputSource));
this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA }); this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged)); this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
@@ -364,6 +383,15 @@ const InputSourceIndicator = new Lang.Class({
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated)); this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
this._inputSourcesChanged(); 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.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, this._showLayout)); this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, this._showLayout));
@@ -397,10 +425,43 @@ const InputSourceIndicator = new Lang.Class({
this._inputSourcesChanged(); 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) { _switchInputSource: function(display, screen, window, binding) {
if (this._mruSources.length < 2) if (this._mruSources.length < 2)
return; 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 popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward);
let modifiers = binding.get_modifiers(); let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
@@ -417,7 +478,7 @@ const InputSourceIndicator = new Lang.Class({
[oldSource, this._currentSource] = [this._currentSource, newSource]; [oldSource, this._currentSource] = [this._currentSource, newSource];
if (oldSource) { if (oldSource) {
oldSource.menuItem.setOrnament(PopupMenu.Ornament.NONE); oldSource.menuItem.setShowDot(false);
oldSource.indicatorLabel.hide(); oldSource.indicatorLabel.hide();
} }
@@ -435,7 +496,7 @@ const InputSourceIndicator = new Lang.Class({
this.actor.show(); this.actor.show();
newSource.menuItem.setOrnament(PopupMenu.Ornament.DOT); newSource.menuItem.setShowDot(true);
newSource.indicatorLabel.show(); newSource.indicatorLabel.show();
this._buildPropSection(newSource.properties); this._buildPropSection(newSource.properties);
@@ -488,10 +549,8 @@ const InputSourceIndicator = new Lang.Class({
let is = new InputSource(type, id, displayName, shortName, i); let is = new InputSource(type, id, displayName, shortName, i);
is.connect('activate', Lang.bind(this, function() { is.connect('activate', Lang.bind(this, function() {
if (this._currentSource && this._currentSource.index == is.index) holdKeyboard();
return; this._keyboardManager.SetInputSourceRemote(is.index, releaseKeyboard);
this._settings.set_value(KEY_CURRENT_INPUT_SOURCE,
GLib.Variant.new_uint32(is.index));
})); }));
if (!(is.shortName in inputSourcesByShortName)) if (!(is.shortName in inputSourcesByShortName))
@@ -661,8 +720,7 @@ const InputSourceIndicator = new Lang.Class({
item.prop = prop; item.prop = prop;
radioGroup.push(item); radioGroup.push(item);
item.radioGroup = radioGroup; item.radioGroup = radioGroup;
item.setOrnament(prop.get_state() == IBus.PropState.CHECKED ? item.setShowDot(prop.get_state() == IBus.PropState.CHECKED);
PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE);
item.connect('activate', Lang.bind(this, function() { item.connect('activate', Lang.bind(this, function() {
if (item.prop.get_state() == IBus.PropState.CHECKED) if (item.prop.get_state() == IBus.PropState.CHECKED)
return; return;
@@ -670,12 +728,12 @@ const InputSourceIndicator = new Lang.Class({
let group = item.radioGroup; let group = item.radioGroup;
for (let i = 0; i < group.length; ++i) { for (let i = 0; i < group.length; ++i) {
if (group[i] == item) { if (group[i] == item) {
item.setOrnament(PopupMenu.Ornament.DOT); item.setShowDot(true);
item.prop.set_state(IBus.PropState.CHECKED); item.prop.set_state(IBus.PropState.CHECKED);
this._ibusManager.activateProperty(item.prop.get_key(), this._ibusManager.activateProperty(item.prop.get_key(),
IBus.PropState.CHECKED); IBus.PropState.CHECKED);
} else { } else {
group[i].setOrnament(PopupMenu.Ornament.NONE); group[i].setShowDot(false);
group[i].prop.set_state(IBus.PropState.UNCHECKED); group[i].prop.set_state(IBus.PropState.UNCHECKED);
this._ibusManager.activateProperty(group[i].prop.get_key(), this._ibusManager.activateProperty(group[i].prop.get_key(),
IBus.PropState.UNCHECKED); IBus.PropState.UNCHECKED);

View File

@@ -5,10 +5,17 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const NetworkManager = imports.gi.NetworkManager; const NetworkManager = imports.gi.NetworkManager;
const NMClient = imports.gi.NMClient; const NMClient = imports.gi.NMClient;
const NMGtk = imports.gi.NMGtk;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; 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 Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
@@ -27,6 +34,7 @@ const NMConnectionCategory = {
}; };
const NMAccessPointSecurity = { const NMAccessPointSecurity = {
UNKNOWN: 0,
NONE: 1, NONE: 1,
WEP: 2, WEP: 2,
WPA_PSK: 3, WPA_PSK: 3,
@@ -44,6 +52,20 @@ const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags'];
// (the remaining are placed into More…) // (the remaining are placed into More…)
const NUM_VISIBLE_NETWORKS = 5; 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) { function ssidCompare(one, two) {
if (!one || !two) if (!one || !two)
return false; return false;
@@ -108,7 +130,8 @@ const NMNetworkMenuItem = new Lang.Class({
this._icons.add_actor(this._signalIcon); this._icons.add_actor(this._signalIcon);
this._secureIcon = new St.Icon({ style_class: 'popup-menu-icon' }); 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._secureIcon.icon_name = 'network-wireless-encrypted-symbolic';
this._icons.add_actor(this._secureIcon); this._icons.add_actor(this._secureIcon);
}, },
@@ -130,12 +153,18 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
Name: 'NMWirelessSectionTitleMenuItem', Name: 'NMWirelessSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem, Extends: PopupMenu.PopupSwitchMenuItem,
_init: function(client) { _init: function(client, property, title, params) {
this.parent(_("Wi-Fi"), false, { style_class: 'popup-subtitle-menu-item' }); params = params || { };
params.style_class = 'popup-subtitle-menu-item';
this.parent(title, false, params);
this._client = client; this._client = client;
this._client.connect('notify::wireless-enabled', Lang.bind(this, this._propertyChanged)); this._property = property + '_enabled';
this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._propertyChanged)); 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(); this._propertyChanged();
}, },
@@ -157,12 +186,12 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
activate: function(event) { activate: function(event) {
this.parent(event); this.parent(event);
this._client.wireless_set_enabled(this._switch.state); this._client[this._setEnabledFunc](this._switch.state);
}, },
_propertyChanged: function() { _propertyChanged: function() {
this._softwareEnabled = this._client.wireless_enabled; this._softwareEnabled = this._client[this._property];
this._hardwareEnabled = this._client.wireless_hardware_enabled; this._hardwareEnabled = this._client[this._propertyHardware];
let enabled = this._softwareEnabled && this._hardwareEnabled; let enabled = this._softwareEnabled && this._hardwareEnabled;
this.setToggleState(enabled); this.setToggleState(enabled);
@@ -286,6 +315,7 @@ const NMDevice = new Lang.Class({
this._activeConnection = null; this._activeConnection = null;
this._activeConnectionItem = null; this._activeConnectionItem = null;
this._autoConnectionItem = null;
this._overflowItem = null; this._overflowItem = null;
this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected, { style_class: 'popup-subtitle-menu-item' }); this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected, { style_class: 'popup-subtitle-menu-item' });
@@ -372,9 +402,13 @@ const NMDevice = new Lang.Class({
}, },
_activateAutomaticConnection: function() { _activateAutomaticConnection: function() {
let connection = new NetworkManager.Connection(); let connection = this._createAutomaticConnection();
this._client.add_and_activate_connection(connection, this.device, null, null); if (connection) {
return true; this._client.add_and_activate_connection(connection, this.device, null, null);
return true;
}
return false;
}, },
get connected() { get connected() {
@@ -468,6 +502,11 @@ const NMDevice = new Lang.Class({
this.statusItem.label.text = this.device._description; this.statusItem.label.text = this.device._description;
}, },
// protected
_createAutomaticConnection: function() {
throw new TypeError('Invoking pure virtual function NMDevice.createAutomaticConnection');
},
_queueCreateSection: function() { _queueCreateSection: function() {
if (this._deferredWorkId) { if (this._deferredWorkId) {
this._clearSection(); this._clearSection();
@@ -478,6 +517,7 @@ const NMDevice = new Lang.Class({
_clearSection: function() { _clearSection: function() {
// Clear everything // Clear everything
this.section.removeAll(); this.section.removeAll();
this._autoConnectionItem = null;
this._activeConnectionItem = null; this._activeConnectionItem = null;
this._overflowItem = null; this._overflowItem = null;
for (let i = 0; i < this._connections.length; i++) { for (let i = 0; i < this._connections.length; i++) {
@@ -516,6 +556,14 @@ const NMDevice = new Lang.Class({
} else } else
this.section.addMenuItem(obj.item); 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)"); title = _("Connected (private)");
} }
this._activeConnectionItem = new PopupMenu.PopupMenuItem(title, { reactive: false }); this._activeConnectionItem = new PopupMenu.PopupMenuItem(title, { reactive: false });
this._activeConnectionItem.setOrnament(PopupMenu.Ornament.DOT); this._activeConnectionItem.setShowDot(true);
}, },
_deviceStateChanged: function(device, newstate, oldstate, reason) { _deviceStateChanged: function(device, newstate, oldstate, reason) {
@@ -617,10 +665,24 @@ const NMDeviceWired = new Lang.Class({
_init: function(client, device, connections) { _init: function(client, device, connections) {
device._description = _("Wired"); device._description = _("Wired");
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED; this.category = NMConnectionCategory.WIRED;
this.parent(client, device, connections); 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({ const NMDeviceModem = new Lang.Class({
@@ -661,10 +723,13 @@ const NMDeviceModem = new Lang.Class({
this._connectionType = NetworkManager.SETTING_GSM_SETTING_NAME; this._connectionType = NetworkManager.SETTING_GSM_SETTING_NAME;
} }
if (is_wwan) if (is_wwan) {
this.category = NMConnectionCategory.WWAN; this.category = NMConnectionCategory.WWAN;
else this._autoConnectionName = _("Auto broadband");
} else {
this.category = NMConnectionCategory.WIRED; this.category = NMConnectionCategory.WIRED;
this._autoConnectionName = _("Auto dial-up");
}
if (this.mobileDevice) { if (this.mobileDevice) {
this._operatorNameId = this.mobileDevice.connect('notify::operator-name', Lang.bind(this, function() { 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) { _init: function(client, device, connections) {
device._description = _("Bluetooth"); device._description = _("Bluetooth");
this._autoConnectionName = this._makeConnectionName(device);
device.connect('notify::name', Lang.bind(this, this._updateAutoConnectionName));
this.category = NMConnectionCategory.WWAN; this.category = NMConnectionCategory.WWAN;
this.parent(client, device, connections); 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() { _activateAutomaticConnection: function() {
// FIXME: DUN devices are configured like modems, so // 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 // but the network panel doesn't support bluetooth at the moment
// so we just create an empty connection and hope // so we just create an empty connection and hope
// that this phone supports PAN // that this phone supports PAN
return this.parent(); 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 pos = this._findNetwork(ap);
let network; let obj;
if (pos != -1) { if (pos != -1) {
network = this._networks[pos]; obj = this._networks[pos];
network.accessPoints.push(ap); obj.accessPoints.push(ap);
} else { } else {
network = { ssid: ap.get_ssid(), obj = { ssid: ap.get_ssid(),
mode: ap.mode, mode: ap.mode,
security: this._getApSecurityType(ap), security: this._getApSecurityType(ap),
connections: [ ], connections: [ ],
item: null, item: null,
accessPoints: [ ap ] accessPoints: [ ap ]
}; };
network.ssidText = ssidToLabel(network.ssid); obj.ssidText = ssidToLabel(obj.ssid);
this._networks.push(network); this._networks.push(obj);
} }
ap._updateId = ap.connect('notify::strength', Lang.bind(this, this._onApStrengthChanged)); 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++) { for (let j = 0; j < validConnections.length; j++) {
let connection = validConnections[j]; let connection = validConnections[j];
if (ap.connection_valid(connection) && if (ap.connection_valid(connection) &&
network.connections.indexOf(connection) == -1) { obj.connections.indexOf(connection) == -1) {
network.connections.push(connection); obj.connections.push(connection);
} }
} }
} }
@@ -839,7 +934,16 @@ const NMDeviceWireless = new Lang.Class({
for (let i = 0; i < this._networks.length; i++) for (let i = 0; i < this._networks.length; i++)
sortAccessPoints(this._networks[i].accessPoints); 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._networks.sort(this._networkSortFunction);
this._apChangedId = device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged)); 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) { _findExistingNetwork: function(accessPoint) {
for (let i = 0; i < this._networks.length; i++) { for (let i = 0; i < this._networks.length; i++) {
let network = this._networks[i]; let apObj = this._networks[i];
for (let j = 0; j < network.accessPoints.length; j++) { for (let j = 0; j < apObj.accessPoints.length; j++) {
if (network.accessPoints[j] == accessPoint) if (apObj.accessPoints[j] == accessPoint)
return { network: i, ap: j }; return { network: i, ap: j };
} }
} }
@@ -1036,30 +1140,30 @@ const NMDeviceWireless = new Lang.Class({
} }
let pos = this._findNetwork(accessPoint); let pos = this._findNetwork(accessPoint);
let network; let apObj;
let needsupdate = false; let needsupdate = false;
if (pos != -1) { if (pos != -1) {
network = this._networks[pos]; apObj = this._networks[pos];
if (network.accessPoints.indexOf(accessPoint) != -1) { if (apObj.accessPoints.indexOf(accessPoint) != -1) {
log('Access point was already seen, not adding again'); log('Access point was already seen, not adding again');
return; return;
} }
Util.insertSorted(network.accessPoints, accessPoint, function(one, two) { Util.insertSorted(apObj.accessPoints, accessPoint, function(one, two) {
return two.strength - one.strength; return two.strength - one.strength;
}); });
if (network.item) if (apObj.item)
network.item.updateBestAP(network.accessPoints[0]); apObj.item.updateBestAP(apObj.accessPoints[0]);
} else { } else {
network = { ssid: accessPoint.get_ssid(), apObj = { ssid: accessPoint.get_ssid(),
mode: accessPoint.mode, mode: accessPoint.mode,
security: this._getApSecurityType(accessPoint), security: this._getApSecurityType(accessPoint),
connections: [ ], connections: [ ],
item: null, item: null,
accessPoints: [ accessPoint ] accessPoints: [ accessPoint ]
}; };
network.ssidText = ssidToLabel(network.ssid); apObj.ssidText = ssidToLabel(apObj.ssid);
} }
accessPoint._updateId = accessPoint.connect('notify::strength', Lang.bind(this, this._onApStrengthChanged)); 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++) { for (let i = 0; i < this._connections.length; i++) {
let connection = this._connections[i].connection; let connection = this._connections[i].connection;
if (accessPoint.connection_valid(connection) && if (accessPoint.connection_valid(connection) &&
network.connections.indexOf(connection) == -1) { apObj.connections.indexOf(connection) == -1) {
network.connections.push(connection); apObj.connections.push(connection);
} }
} }
if (pos != -1) if (pos != -1)
this._networks.splice(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 // Queue an update of the UI if we changed the order
if (newPos != pos) if (newPos != pos)
@@ -1094,28 +1198,28 @@ const NMDeviceWireless = new Lang.Class({
return; return;
} }
let network = this._networks[res.network]; let apObj = this._networks[res.network];
network.accessPoints.splice(res.ap, 1); apObj.accessPoints.splice(res.ap, 1);
if (network.accessPoints.length == 0) { if (apObj.accessPoints.length == 0) {
if (this._activeNetwork == network) if (this._activeNetwork == apObj)
this._activeNetwork = null; this._activeNetwork = null;
if (network.item) if (apObj.item)
network.item.destroy(); apObj.item.destroy();
if (this._overflowItem) { if (this._overflowItem) {
if (!network.isMore) { if (!apObj.isMore) {
// we removed an item in the main menu, and we have a more submenu // 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 // we need to extract the first item in more and move it to the submenu
let item = this._overflowItem.menu.firstMenuItem; let item = this._overflowItem.menu.firstMenuItem;
if (item && item._network) { if (item && item._apObj) {
item.destroy(); item.destroy();
// clear the cycle, and allow the construction of the new item // 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 { } else {
log('The more... menu was existing and empty! This should not happen'); 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; let okPrev = true, okNext = true;
if (res.network > 0) 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) 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) if (!okPrev || !okNext)
this._queueCreateSection(); this._queueCreateSection();
else if (network.item) else if (apObj.item)
network.item.updateBestAP(network.accessPoints[0]); apObj.item.updateBestAP(apObj.accessPoints[0]);
} }
}, },
@@ -1180,20 +1284,20 @@ const NMDeviceWireless = new Lang.Class({
let forceupdate = false; let forceupdate = false;
for (let i = 0; i < this._networks.length; i++) { for (let i = 0; i < this._networks.length; i++) {
let network = this._networks[i]; let apObj = this._networks[i];
let connections = network.connections; let connections = apObj.connections;
for (let k = 0; k < connections.length; k++) { for (let k = 0; k < connections.length; k++) {
if (connections[k].get_uuid() == connection.get_uuid()) { if (connections[k].get_uuid() == connection.get_uuid()) {
// remove the connection from the access point group // remove the connection from the access point group
connections.splice(k, 1); connections.splice(k);
forceupdate = forceupdate || connections.length == 0; forceupdate = forceupdate || connections.length == 0;
if (forceupdate) if (forceupdate)
break; break;
if (network.item) { if (apObj.item) {
if (network.item instanceof PopupMenu.PopupSubMenuMenuItem) { if (apObj.item instanceof PopupMenu.PopupSubMenuMenuItem) {
let items = network.item.menu._getMenuItems(); let items = apObj.item.menu._getMenuItems();
if (items.length == 2) { if (items.length == 2) {
// we need to update the connection list to convert this to a normal item // we need to update the connection list to convert this to a normal item
forceupdate = true; forceupdate = true;
@@ -1206,8 +1310,8 @@ const NMDeviceWireless = new Lang.Class({
} }
} }
} else { } else {
network.item.destroy(); apObj.item.destroy();
network.item = null; apObj.item = null;
} }
} }
break; break;
@@ -1233,13 +1337,13 @@ const NMDeviceWireless = new Lang.Class({
// find an appropriate access point // find an appropriate access point
let forceupdate = false; let forceupdate = false;
for (let i = 0; i < this._networks.length; i++) { 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 // Check if connection is valid for any of these access points
for (let k = 0; k < network.accessPoints.length; k++) { for (let k = 0; k < apObj.accessPoints.length; k++) {
let ap = network.accessPoints[k]; let ap = apObj.accessPoints[k];
if (ap.connection_valid(connection)) { if (ap.connection_valid(connection)) {
network.connections.push(connection); apObj.connections.push(connection);
// this potentially changes the sorting order // this potentially changes the sorting order
forceupdate = true; forceupdate = true;
break; break;
@@ -1260,30 +1364,55 @@ const NMDeviceWireless = new Lang.Class({
else else
title = _("Connected (private)"); title = _("Connected (private)");
this._activeConnectionItem = new NMNetworkMenuItem(this.device.active_access_point, undefined, if (this._activeNetwork)
{ reactive: false }); this._activeConnectionItem = new NMNetworkMenuItem(this.device.active_access_point, undefined,
this._activeConnectionItem.setOrnament(PopupMenu.Ornament.DOT); { reactive: false });
else
this._activeConnectionItem = new PopupMenu.PopupImageMenuItem(title,
'network-wireless-connected-symbolic',
{ reactive: false });
this._activeConnectionItem.setShowDot(true);
}, },
_createNetworkItem: function(network, position) { _createAutomaticConnection: function(apObj) {
if(!network.accessPoints || network.accessPoints.length == 0) { 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 // this should not happen, but I have no idea why it happens
return; return;
} }
if(network.connections.length > 0) { if(apObj.connections.length > 0) {
if (network.connections.length == 1) { if (apObj.connections.length == 1) {
network.item = this._createAPItem(network.connections[0], network, false); apObj.item = this._createAPItem(apObj.connections[0], apObj, false);
} else { } else {
let title = network.ssidText; let title = apObj.ssidText;
network.item = new PopupMenu.PopupSubMenuMenuItem(title); apObj.item = new PopupMenu.PopupSubMenuMenuItem(title);
for (let i = 0; i < network.connections.length; i++) for (let i = 0; i < apObj.connections.length; i++)
network.item.menu.addMenuItem(this._createAPItem(network.connections[i], network, true)); apObj.item.menu.addMenuItem(this._createAPItem(apObj.connections[i], apObj, true));
} }
} else { } else {
network.item = new NMNetworkMenuItem(network.accessPoints[0]); apObj.item = new NMNetworkMenuItem(apObj.accessPoints[0]);
network.item.connect('activate', Lang.bind(this, function() { apObj.item.connect('activate', Lang.bind(this, function() {
let accessPoints = network.accessPoints; let accessPoints = apObj.accessPoints;
if ( (accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT) if ( (accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) { || (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
// 802.1x-enabled APs require further configuration, so they're // 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', Util.spawn(['gnome-control-center', 'network', 'connect-8021x-wifi',
this.device.get_path(), accessPoints[0].dbus_path]); this.device.get_path(), accessPoints[0].dbus_path]);
} else { } 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) 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) { if (position < NUM_VISIBLE_NETWORKS) {
network.isMore = false; apObj.isMore = false;
this.section.addMenuItem(network.item, position); this.section.addMenuItem(apObj.item, position);
} else { } else {
if (!this._overflowItem) { if (!this._overflowItem) {
this._overflowItem = new PopupMenu.PopupSubMenuMenuItem(_("More…")); this._overflowItem = new PopupMenu.PopupSubMenuMenuItem(_("More…"));
this.section.addMenuItem(this._overflowItem); this.section.addMenuItem(this._overflowItem);
} }
this._overflowItem.menu.addMenuItem(network.item, position - NUM_VISIBLE_NETWORKS); this._overflowItem.menu.addMenuItem(apObj.item, position - NUM_VISIBLE_NETWORKS);
network.isMore = true; apObj.isMore = true;
} }
}, },
@@ -1323,13 +1452,13 @@ const NMDeviceWireless = new Lang.Class({
let activeOffset = this._activeConnectionItem ? 1 : 0; let activeOffset = this._activeConnectionItem ? 1 : 0;
for(let j = 0; j < this._networks.length; j++) { for(let j = 0; j < this._networks.length; j++) {
let network = this._networks[j]; let apObj = this._networks[j];
if (network == this._activeNetwork) { if (apObj == this._activeNetwork) {
activeOffset--; activeOffset--;
continue; continue;
} }
this._createNetworkItem(network, j + activeOffset); this._createNetworkItem(apObj, j + activeOffset);
} }
}, },
}); });
@@ -1551,9 +1680,11 @@ const NMApplet = new Lang.Class({
// Virtual device types // Virtual device types
this._vtypes = { }; this._vtypes = { };
this._vtypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMDeviceVirtual; if (NMGtk) {
this._vtypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMDeviceVirtual; this._vtypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMDeviceVirtual;
this._vtypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMDeviceVirtual; this._vtypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMDeviceVirtual;
this._vtypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMDeviceVirtual;
}
// Connection types // Connection types
this._ctypes = { }; this._ctypes = { };
@@ -1565,9 +1696,11 @@ const NMApplet = new Lang.Class({
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN; this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN; this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED; this._ctypes[NetworkManager.SETTING_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED;
this._ctypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMConnectionCategory.VIRTUAL; if (NMGtk) {
this._ctypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMConnectionCategory.VIRTUAL; this._ctypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
this._ctypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMConnectionCategory.VIRTUAL; this._ctypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
this._ctypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
}
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN; this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
NMClient.Client.new_async(null, Lang.bind(this, this._clientGot)); NMClient.Client.new_async(null, Lang.bind(this, this._clientGot));
@@ -1635,7 +1768,7 @@ const NMApplet = new Lang.Class({
this._devices.wireless = { this._devices.wireless = {
section: new PopupMenu.PopupMenuSection(), section: new PopupMenu.PopupMenuSection(),
devices: [ ], devices: [ ],
item: this._makeWirelessToggle() item: this._makeToggleItem('wireless', _("Wi-Fi"))
}; };
this._devices.wireless.section.addMenuItem(this._devices.wireless.item); this._devices.wireless.section.addMenuItem(this._devices.wireless.item);
this._devices.wireless.section.actor.hide(); this._devices.wireless.section.actor.hide();
@@ -1682,14 +1815,14 @@ const NMApplet = new Lang.Class({
} }
}, },
_makeWirelessToggle: function() { _makeToggleItem: function(type, title) {
let item = new NMWirelessSectionTitleMenuItem(this._client); let item = new NMWirelessSectionTitleMenuItem(this._client, type, title);
item.connect('enabled-changed', Lang.bind(this, function(item, enabled) { 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) { devices.forEach(function(dev) {
dev.setEnabled(enabled); dev.setEnabled(enabled);
}); });
this._syncSectionTitle('wireless'); this._syncSectionTitle(type);
})); }));
return item; return item;
}, },
@@ -1767,12 +1900,19 @@ const NMApplet = new Lang.Class({
}, },
_syncDeviceNames: function() { _syncDeviceNames: function() {
let names = NMGtk.utils_disambiguate_device_names(this._nmDevices); if (NMGtk) {
for (let i = 0; i < this._nmDevices.length; i++) { let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
let device = this._nmDevices[i]; for (let i = 0; i < this._nmDevices.length; i++) {
device._description = names[i]; let device = this._nmDevices[i];
if (device._delegate) 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(); device._delegate.syncDescription();
}
} }
}, },
@@ -1808,6 +1948,11 @@ const NMApplet = new Lang.Class({
wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) { wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
this._syncSectionTitle(dev.category); 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; let section = this._devices[wrapper.category].section;
section.addMenuItem(wrapper.statusItem); section.addMenuItem(wrapper.statusItem);
@@ -1839,8 +1984,6 @@ const NMApplet = new Lang.Class({
}, },
_removeDeviceWrapper: function(wrapper) { _removeDeviceWrapper: function(wrapper) {
wrapper.disconnect(wrapper._activationFailedId);
wrapper.disconnect(wrapper._deviceStateChangedId);
wrapper.destroy(); wrapper.destroy();
let devices = this._devices[wrapper.category].devices; let devices = this._devices[wrapper.category].devices;
@@ -1904,6 +2047,7 @@ const NMApplet = new Lang.Class({
let default_ip4 = null; let default_ip4 = null;
let default_ip6 = null; let default_ip6 = null;
let active_vpn = null; let active_vpn = null;
let active_any = null;
for (let i = 0; i < this._activeConnections.length; i++) { for (let i = 0; i < this._activeConnections.length; i++) {
let a = this._activeConnections[i]; let a = this._activeConnections[i];
@@ -1934,10 +2078,15 @@ const NMApplet = new Lang.Class({
if (a.default6) if (a.default6)
default_ip6 = a; default_ip6 = a;
if (a._type == 'vpn') if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING)
active_vpn = a;
else if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING)
activating = a; 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._primaryDevice) {
if (a._type != NetworkManager.SETTING_VPN_SETTING_NAME) { 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; this._vpnConnection = active_vpn;
}, },
@@ -1991,7 +2140,25 @@ const NMApplet = new Lang.Class({
return false; 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)) if (this._ignoreConnection(connection))
return; return;
if (connection._updatedId) { if (connection._updatedId) {
@@ -2004,22 +2171,14 @@ const NMApplet = new Lang.Class({
this._updateConnection(connection); this._updateConnection(connection);
this._connections.push(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(); this._updateIcon();
}, },
_connectionRemoved: function(connection) { _connectionRemoved: function(connection) {
let pos = this._connections.indexOf(connection); let pos = this._connections.indexOf(connection);
if (pos != -1) if (pos != -1)
this._connections.splice(connection, 1); this._connections.splice(connection);
let section = connection._section; let section = connection._section;

View File

@@ -307,7 +307,7 @@ const Indicator = new Lang.Class({
this._headphoneIcon.visible = value; 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._headphoneIcon.visible = false;
this.menu.addMenuItem(this._volumeMenu); this.menu.addMenuItem(this._volumeMenu);

View File

@@ -91,10 +91,6 @@ const UnlockDialog = new Lang.Class({
this._promptLoginHint.hide(); this._promptLoginHint.hide();
this.contentLayout.add_actor(this._promptLoginHint); 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.allowCancel = false;
this.buttonLayout.visible = true; this.buttonLayout.visible = true;
this.addButton({ label: _("Cancel"), this.addButton({ label: _("Cancel"),
@@ -105,12 +101,11 @@ const UnlockDialog = new Lang.Class({
y_fill: false, y_fill: false,
x_align: St.Align.START, x_align: St.Align.START,
y_align: St.Align.MIDDLE }); y_align: St.Align.MIDDLE });
this.buttonLayout.add(this._workSpinner.actor, this.placeSpinner({ expand: false,
{ expand: false, x_fill: false,
x_fill: false, y_fill: false,
y_fill: false, x_align: St.Align.END,
x_align: St.Align.END, y_align: St.Align.MIDDLE });
y_align: St.Align.MIDDLE });
this._okButton = this.addButton({ label: _("Unlock"), this._okButton = this.addButton({ label: _("Unlock"),
action: Lang.bind(this, this._doUnlock), action: Lang.bind(this, this._doUnlock),
default: true }, default: true },
@@ -164,28 +159,6 @@ const UnlockDialog = new Lang.Class({
this._okButton.can_focus = sensitive; this._okButton.can_focus = sensitive;
}, },
_setWorking: function(working) {
if (working) {
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: LoginDialog.WORK_SPINNER_ANIMATION_DELAY,
time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
this._workSpinner.stop();
}
});
}
},
_showMessage: function(userVerifier, message, styleClass) { _showMessage: function(userVerifier, message, styleClass) {
if (message) { if (message) {
this._promptMessage.text = message; this._promptMessage.text = message;
@@ -216,7 +189,7 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = serviceName; this._currentQuery = serviceName;
this._updateSensitivity(true); this._updateSensitivity(true);
this._setWorking(false); this.setWorking(false);
}, },
_showLoginHint: function(verifier, message) { _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 // the actual reply to GDM will be sent as soon as asked
this._firstQuestionAnswer = this._promptEntry.text; this._firstQuestionAnswer = this._promptEntry.text;
this._updateSensitivity(false); this._updateSensitivity(false);
this._setWorking(true); this.setWorking(true);
return; return;
} }
@@ -246,7 +219,7 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = null; this._currentQuery = null;
this._updateSensitivity(false); this._updateSensitivity(false);
this._setWorking(true); this.setWorking(true);
this._userVerifier.answerQuery(query, this._promptEntry.text); this._userVerifier.answerQuery(query, this._promptEntry.text);
}, },
@@ -286,7 +259,7 @@ const UnlockDialog = new Lang.Class({
this._promptEntry.menu.isPassword = true; this._promptEntry.menu.isPassword = true;
this._updateSensitivity(false); this._updateSensitivity(false);
this._setWorking(false); this.setWorking(false);
}, },
_escape: function() { _escape: function() {

View File

@@ -16,6 +16,7 @@ const UserWidget = new Lang.Class({
this.actor = new St.BoxLayout({ style_class: 'user-widget', this.actor = new St.BoxLayout({ style_class: 'user-widget',
vertical: false }); vertical: false });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._avatar = new UserMenu.UserAvatarWidget(user); this._avatar = new UserMenu.UserAvatarWidget(user);
this.actor.add(this._avatar.actor, this.actor.add(this._avatar.actor,
@@ -36,7 +37,7 @@ const UserWidget = new Lang.Class({
this._updateUser(); this._updateUser();
}, },
destroy: function() { _onDestroy: function() {
if (this._userLoadedId != 0) { if (this._userLoadedId != 0) {
this._user.disconnect(this._userLoadedId); this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0; this._userLoadedId = 0;
@@ -46,8 +47,6 @@ const UserWidget = new Lang.Class({
this._user.disconnect(this._userChangedId); this._user.disconnect(this._userChangedId);
this._userChangedId = 0; this._userChangedId = 0;
} }
this.actor.destroy();
}, },
_updateUser: function() { _updateUser: function() {

View File

@@ -150,14 +150,6 @@ const ViewSelector = new Lang.Class({
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._toggleAppsPage)); 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() { _toggleAppsPage: function() {
@@ -186,10 +178,6 @@ const ViewSelector = new Lang.Class({
Main.overview.fadeInDesktop(); Main.overview.fadeInDesktop();
}, },
setWorkspacesFullGeometry: function(geom) {
this._workspacesDisplay.setWorkspacesFullGeometry(geom);
},
hide: function() { hide: function() {
this._workspacesDisplay.hide(); this._workspacesDisplay.hide();
}, },

View File

@@ -136,6 +136,42 @@ const WindowManager = new Lang.Class({
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher)); 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', this.setCustomKeybindingHandler('switch-applications',
Shell.KeyBindingMode.NORMAL, Shell.KeyBindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));

View File

@@ -753,6 +753,13 @@ const LayoutStrategy = new Lang.Class({
layout.space = space; 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) { computeWindowSlots: function(layout, area) {
this._computeRowSizes(layout); this._computeRowSizes(layout);
@@ -760,36 +767,28 @@ const LayoutStrategy = new Lang.Class({
let slots = []; 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; let y = 0;
for (let i = 0; i < rows.length; i++) { for (let i = 0; i < rows.length; i++) {
let row = rows[i]; let row = rows[i];
row.x = area.x + (area.width - row.width) / 2;
// If this window layout row doesn't fit in the actual row.y = area.y + y;
// 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;
y += row.height + this._rowSpacing; 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++) { for (let i = 0; i < rows.length; i++) {
let row = rows[i]; let row = rows[i];
row.y += baseY;
let x = row.x; let x = row.x;
for (let j = 0; j < row.windows.length; j++) { for (let j = 0; j < row.windows.length; j++) {
let window = row.windows[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 cellWidth = window.actor.width * s;
let cellHeight = window.actor.height * s; let cellHeight = window.actor.height * s;
@@ -833,13 +832,6 @@ const UnalignedLayoutStrategy = new Lang.Class({
return false; 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) { computeLayout: function(windows, layout) {
let numRows = layout.numRows; let numRows = layout.numRows;
@@ -870,7 +862,6 @@ const UnalignedLayoutStrategy = new Lang.Class({
row.windows.push(window); row.windows.push(window);
row.fullWidth += width; row.fullWidth += width;
} else { } else {
this._sortRow(row);
break; 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 * @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. // When dragging a window, we use this slot for reserve space.
this._reservedSlot = null; this._reservedSlot = null;
this.metaWorkspace = metaWorkspace; this.metaWorkspace = metaWorkspace;
this._x = 0;
// The full geometry is the geometry we should try and position this._y = 0;
// windows for. The actual geometry we allocate may be less than this._width = 0;
// this, like if the workspace switcher is slid out. this._height = 0;
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.monitorIndex = monitorIndex; this.monitorIndex = monitorIndex;
this._monitor = Main.layoutManager.monitors[this.monitorIndex]; this._monitor = Main.layoutManager.monitors[this.monitorIndex];
@@ -973,22 +947,23 @@ const Workspace = new Lang.Class({
this._positionWindowsFlags = 0; this._positionWindowsFlags = 0;
this._positionWindowsId = 0; this._positionWindowsId = 0;
this._currentLayout = null;
}, },
setFullGeometry: function(geom) { setGeometry: function(x, y, width, height) {
this._fullGeometry = geom; this._x = x;
this._recalculateWindowPositions(WindowPositionFlags.NONE); this._y = y;
}, this._width = width;
this._height = height;
setActualGeometry: function(geom) {
this._actualGeometry = geom;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._dropRect.set_position(geom.x, geom.y); this._dropRect.set_position(x, y);
this._dropRect.set_size(geom.width, geom.height); this._dropRect.set_size(width, height);
this._updateWindowPositions(WindowPositionFlags.NONE);
return false; return false;
})); }));
this.positionWindows(WindowPositionFlags.NONE);
}, },
_lookupIndex: function (metaWindow) { _lookupIndex: function (metaWindow) {
@@ -1016,32 +991,37 @@ const Workspace = new Lang.Class({
clone = null; clone = null;
this._reservedSlot = clone; 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; this._positionWindowsFlags |= flags;
if (this._positionWindowsId > 0) if (this._positionWindowsId > 0)
return; return;
this._positionWindowsId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { 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._positionWindowsFlags = 0;
this._positionWindowsId = 0; this._positionWindowsId = 0;
return false; return false;
})); }));
}, },
_realRecalculateWindowPositions: function(flags) { _realPositionWindows : function(flags) {
if (this._repositionWindowsId > 0) { if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId); Mainloop.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0; this._repositionWindowsId = 0;
} }
let clones = this._windows.slice(); let clones = this._windows.slice();
if (clones.length == 0)
return;
clones.sort(function(a, b) { clones.sort(function(a, b) {
return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence(); return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence();
@@ -1050,25 +1030,11 @@ const Workspace = new Lang.Class({
if (this._reservedSlot) if (this._reservedSlot)
clones.push(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 initialPositioning = flags & WindowPositionFlags.INITIAL;
let animate = flags & WindowPositionFlags.ANIMATE; let animate = flags & WindowPositionFlags.ANIMATE;
let layout = this._currentLayout; // Start the animations
let strategy = layout.strategy; let slots = this._computeAllWindowSlots(clones);
let [, , padding] = this._getSpacingAndPadding();
let area = padArea(this._actualGeometry, padding);
let slots = strategy.computeWindowSlots(layout, area);
let currentWorkspace = global.screen.get_active_workspace(); let currentWorkspace = global.screen.get_active_workspace();
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace; let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
@@ -1128,6 +1094,7 @@ const Workspace = new Lang.Class({
Tweener.removeTweens(clone.actor); Tweener.removeTweens(clone.actor);
clone.actor.set_position(x, y); clone.actor.set_position(x, y);
clone.actor.set_scale(scale, scale); clone.actor.set_scale(scale, scale);
clone.actor.set_opacity(255);
clone.overlay.relayout(false); clone.overlay.relayout(false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
} }
@@ -1182,8 +1149,8 @@ const Workspace = new Lang.Class({
let [x, y, mask] = global.get_pointer(); let [x, y, mask] = global.get_pointer();
let pointerHasMoved = (this._cursorX != x && this._cursorY != y); let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
let inWorkspace = (this._fullGeometry.x < x && x < this._fullGeometry.x + this._fullGeometry.width && let inWorkspace = (this._x < x && x < this._x + this._width &&
this._fullGeometry.y < y && y < this._fullGeometry.y + this._fullGeometry.height); this._y < y && y < this._y + this._height);
if (pointerHasMoved && inWorkspace) { if (pointerHasMoved && inWorkspace) {
// store current cursor position // store current cursor position
@@ -1198,7 +1165,7 @@ const Workspace = new Lang.Class({
return true; return true;
} }
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); this.positionWindows(WindowPositionFlags.ANIMATE);
return false; return false;
}, },
@@ -1303,7 +1270,7 @@ const Workspace = new Lang.Class({
} }
this._currentLayout = null; this._currentLayout = null;
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); this.positionWindows(WindowPositionFlags.ANIMATE);
}, },
_windowAdded : function(metaWorkspace, metaWin) { _windowAdded : function(metaWorkspace, metaWin) {
@@ -1340,8 +1307,13 @@ const Workspace = new Lang.Class({
// Animate the full-screen to Overview transition. // Animate the full-screen to Overview transition.
zoomToOverview : function() { zoomToOverview : function() {
this._currentLayout = null;
// Position and scale the windows. // 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 // Animates the return from Overview mode
@@ -1465,7 +1437,7 @@ const Workspace = new Lang.Class({
})); }));
clone.connect('size-changed', clone.connect('size-changed',
Lang.bind(this, function() { Lang.bind(this, function() {
this._recalculateWindowPositions(WindowPositionFlags.NONE); this.positionWindows(0);
})); }));
this.actor.add_actor(clone.actor); 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 // We look for the largest scale that allows us to fit the
// largest row/tallest column on the workspace. // largest row/tallest column on the workspace.
let lastLayout = {}; let lastLayout = {};
let strategy = new UnalignedLayoutStrategy(this._monitor, rowSpacing, columnSpacing);
for (let numRows = 1; ; numRows++) { for (let numRows = 1; ; numRows++) {
let numColumns = Math.ceil(windows.length / numRows); let numColumns = Math.ceil(windows.length / numRows);
@@ -1531,6 +1501,8 @@ const Workspace = new Lang.Class({
if (numColumns == lastLayout.numColumns) if (numColumns == lastLayout.numColumns)
break; break;
let strategy = new UnalignedLayoutStrategy(this._monitor, rowSpacing, columnSpacing);
let layout = { area: area, strategy: strategy, numRows: numRows, numColumns: numColumns }; let layout = { area: area, strategy: strategy, numRows: numRows, numColumns: numColumns };
strategy.computeLayout(windows, layout); strategy.computeLayout(windows, layout);
strategy.computeScaleAndSpace(layout); strategy.computeScaleAndSpace(layout);
@@ -1544,7 +1516,18 @@ const Workspace = new Lang.Class({
return lastLayout; 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(); let node = this.actor.get_theme_node();
// Window grid spacing // Window grid spacing
@@ -1557,14 +1540,21 @@ const Workspace = new Lang.Class({
right: node.get_padding(St.Side.RIGHT), right: node.get_padding(St.Side.RIGHT),
}; };
if (!totalWindows)
return [];
let closeButtonHeight, captionHeight; let closeButtonHeight, captionHeight;
let leftBorder, rightBorder; let leftBorder, rightBorder;
if (this._windowOverlays.length) {
// All of the overlays have the same chrome sizes, // All of the overlays have the same chrome sizes,
// so just pick the first one. // so just pick the first one.
let overlay = this._windowOverlays[0]; let overlay = this._windowOverlays[0];
[closeButtonHeight, captionHeight] = overlay.chromeHeights(); [closeButtonHeight, captionHeight] = overlay.chromeHeights();
[leftBorder, rightBorder] = overlay.chromeWidths(); [leftBorder, rightBorder] = overlay.chromeWidths();
} else {
[closeButtonHeight, captionHeight] = [0, 0];
[leftBorder, rightBorder] = [0, 0];
}
rowSpacing += captionHeight; rowSpacing += captionHeight;
columnSpacing += (rightBorder + leftBorder) / 2; columnSpacing += (rightBorder + leftBorder) / 2;
@@ -1573,13 +1563,25 @@ const Workspace = new Lang.Class({
padding.left += leftBorder; padding.left += leftBorder;
padding.right += rightBorder; 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) { if (!this._currentLayout)
let [rowSpacing, columnSpacing, padding] = this._getSpacingAndPadding(); this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing);
let area = padArea(this._fullGeometry, padding);
return this._getBestLayout(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) { _onCloneSelected : function (clone, time) {

View File

@@ -23,18 +23,6 @@ const MAX_WORKSPACES = 16;
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides'; 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({ const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView', Name: 'WorkspacesView',
@@ -55,9 +43,10 @@ const WorkspacesView = new Lang.Class({
this._updateWorkspaceActors(false); this._updateWorkspaceActors(false);
})); }));
this._fullGeometry = null; this._width = 0;
this._actualGeometry = null; this._height = 0;
this._x = 0;
this._y = 0;
this._spacing = 0; this._spacing = 0;
this._animating = false; // tweening this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling this._scrolling = false; // swipe-scrolling
@@ -96,8 +85,8 @@ const WorkspacesView = new Lang.Class({
this._overviewShownId = this._overviewShownId =
Main.overview.connect('shown', Main.overview.connect('shown',
Lang.bind(this, function() { Lang.bind(this, function() {
this.actor.set_clip(this._fullGeometry.x, this._fullGeometry.y, this.actor.set_clip(this._x, this._y,
this._fullGeometry.width, this._fullGeometry.height); this._width, this._height);
})); }));
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
@@ -135,8 +124,10 @@ const WorkspacesView = new Lang.Class({
continue; continue;
let ws = new Workspace.Workspace(null, i); let ws = new Workspace.Workspace(null, i);
ws.setFullGeometry(monitors[i]); ws.setGeometry(monitors[i].x,
ws.setActualGeometry(monitors[i]); monitors[i].y,
monitors[i].width,
monitors[i].height);
global.overlay_group.add_actor(ws.actor); global.overlay_group.add_actor(ws.actor);
this._extraWorkspaces.push(ws); this._extraWorkspaces.push(ws);
} }
@@ -148,24 +139,18 @@ const WorkspacesView = new Lang.Class({
this._extraWorkspaces = []; this._extraWorkspaces = [];
}, },
setFullGeometry: function(geom) { setGeometry: function(x, y, width, height) {
if (rectEqual(this._fullGeometry, geom)) if (this._x == x && this._y == y &&
return; 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++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setFullGeometry(geom); this._workspaces[i].setGeometry(x, y, width, height);
},
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);
}, },
_lookupWorkspaceForMetaWindow: function (metaWindow) { _lookupWorkspaceForMetaWindow: function (metaWindow) {
@@ -225,7 +210,7 @@ const WorkspacesView = new Lang.Class({
Tweener.removeTweens(workspace.actor); Tweener.removeTweens(workspace.actor);
let y = (w - active) * (this._fullGeometry.height + this._spacing); let y = (w - active) * (this._height + this._spacing);
if (showAnimation) { if (showAnimation) {
let params = { y: y, let params = { y: y,
@@ -296,9 +281,8 @@ const WorkspacesView = new Lang.Class({
if (newNumWorkspaces > oldNumWorkspaces) { if (newNumWorkspaces > oldNumWorkspaces) {
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) { for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
this._workspaces[w].setFullGeometry(this._fullGeometry); this._workspaces[w].setGeometry(this._x, this._y,
if (this._actualGeometry) this._width, this._height);
this._workspaces[w].setActualGeometry(this._actualGeometry);
this.actor.add_actor(this._workspaces[w].actor); this.actor.add_actor(this._workspaces[w].actor);
} }
@@ -446,7 +430,7 @@ const WorkspacesDisplay = new Lang.Class({
_init: function() { _init: function() {
this.actor = new St.Widget({ clip_to_allocation: true }); 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)); this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
let clickAction = new Clutter.ClickAction() let clickAction = new Clutter.ClickAction()
@@ -500,8 +484,6 @@ const WorkspacesDisplay = new Lang.Class({
this._notifyOpacityId = 0; this._notifyOpacityId = 0;
this._scrollEventId = 0; this._scrollEventId = 0;
this._fullGeometry = null;
}, },
_onPan: function(action) { _onPan: function(action) {
@@ -590,8 +572,7 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesViews.push(view); this._workspacesViews.push(view);
} }
this._updateWorkspacesFullGeometry(); this._updateWorkspacesGeometry();
this._updateWorkspacesActualGeometry();
for (let i = 0; i < this._workspacesViews.length; i++) for (let i = 0; i < this._workspacesViews.length; i++)
global.overlay_group.add_actor(this._workspacesViews[i].actor); 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 _updateWorkspacesGeometry: function() {
// 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() {
if (!this._workspacesViews.length) if (!this._workspacesViews.length)
return; return;
let monitors = Main.layoutManager.monitors; let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
let m = 0; let fullHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
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++;
}
}
},
_updateWorkspacesActualGeometry: function() { let width = fullWidth;
if (!this._workspacesViews.length) let height = fullHeight;
return;
let [x, y] = this.actor.get_transformed_position(); 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 rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
let geometry = { x: x, y: y, width: width, height: height };
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;
let m = 0; let m = 0;
for (let i = 0; i < monitors.length; i++) { for (let i = 0; i < monitors.length; i++) {
if (i == this._primaryIndex) { if (i == this._primaryIndex) {
this._workspacesViews[m].setActualGeometry(geometry); this._workspacesViews[m].setGeometry(x, y, width, height);
m++; m++;
} else if (!this._workspacesOnlyOnPrimary) { } 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++; m++;
} }
} }

View File

@@ -125,6 +125,12 @@
<listitem><para>List possible modes and exit</para></listitem> <listitem><para>List possible modes and exit</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--clutter-display=<replaceable>DISPLAY</replaceable></option></term>
<listitem><para>Clutter the option display (otherwise ignored)</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@@ -46,6 +46,7 @@ ms
nb nb
nl nl
nn nn
oc
or or
pa pa
pl pl

588
po/as.po

File diff suppressed because it is too large Load Diff

521
po/ca.po

File diff suppressed because it is too large Load Diff

577
po/cs.po

File diff suppressed because it is too large Load Diff

477
po/de.po

File diff suppressed because it is too large Load Diff

553
po/el.po

File diff suppressed because it is too large Load Diff

616
po/es.po

File diff suppressed because it is too large Load Diff

View File

@@ -1244,7 +1244,7 @@ msgstr "Ezezaguna"
#, c-format #, c-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
msgstr[0] "Mezu berri &d" msgstr[0] "Mezu berri %d"
msgstr[1] "%d mezu berri" msgstr[1] "%d mezu berri"
#: ../js/ui/overview.js:84 #: ../js/ui/overview.js:84

646
po/fi.po

File diff suppressed because it is too large Load Diff

523
po/fr.po

File diff suppressed because it is too large Load Diff

526
po/gl.po

File diff suppressed because it is too large Load Diff

688
po/gu.po

File diff suppressed because it is too large Load Diff

508
po/hu.po

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,10 @@
# #
msgid "" msgid ""
msgstr "" 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-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 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" "PO-Revision-Date: 2013-04-23 08:00+0400\n"
"Last-Translator: Nik Kalach <nikka@fedoraproject.org>\n" "Last-Translator: Nik Kalach <nikka@fedoraproject.org>\n"
"Language-Team: Interlingua <trans-ia@lists.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" msgstr "Mitter foco al notificationes active"
#: ../data/50-gnome-shell-system.xml.in.h:4 #: ../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" msgid "Show all applications"
msgstr "Monstrar tote le applicationes" 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" msgid "Open the application menu"
msgstr "Aperir le menu de applicationes" msgstr "Aperir le menu de applicationes"
@@ -226,52 +222,44 @@ msgstr ""
"panorama de activitates." "panorama de activitates."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25 #: ../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" msgid "Keybinding to toggle the visibility of the message tray"
msgstr "" msgstr ""
"Association de claves pro commutar le visibilitate del tiratorio de messages" "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." msgid "Keybinding to toggle the visibility of the message tray."
msgstr "" msgstr ""
"Association de claves pro commutar le visibilitate del tiratorio de messages." "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" msgid "Keybinding to focus the active notification"
msgstr "Association de claves pro mitter foco al notificationes active" 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." msgid "Keybinding to focus the active notification."
msgstr "Association de claves pro mitter foco al notificationes active." 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" msgid "Keybinding to toggle the screen recorder"
msgstr "Association de claves pro commutar le registrator de schermo" 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." msgid "Keybinding to start/stop the builtin screen recorder."
msgstr "Association de claves pro initiar/arrestar le registration de schermo." 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" msgid "Which keyboard to use"
msgstr "Que claviero usar" 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." msgid "The type of keyboard to use."
msgstr "Le typo de claviero a usar." 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." msgid "Framerate used for recording screencasts."
msgstr "Rata de quadros usate pro registrar le video de schermo." 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 "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
@@ -279,11 +267,11 @@ msgstr ""
"Le numero de imagines per secunda in le video de schermo registrate per le " "Le numero de imagines per secunda in le video de schermo registrate per le "
"registrator incorporate in GNOME Shell." "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" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "Le catena usante per gstreamer pro codificar video de schermo" 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 #, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@@ -309,11 +297,11 @@ msgstr ""
"queue ! webmmux' e registra in WEBM usante le codec VP8. %T designa le " "queue ! webmmux' e registra in WEBM usante le codec VP8. %T designa le "
"numero de filos optimal pro le systema." "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" msgid "File extension used for storing the screencast"
msgstr "Extension de file a usar pro slaveguardar le video de schermo" 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 "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
@@ -323,11 +311,11 @@ msgstr ""
"currente e iste extension. Illo deberea esser modificate si le formato de " "currente e iste extension. Illo deberea esser modificate si le formato de "
"container usate pro registar le video es differente." "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." msgid "The application icon mode."
msgstr "Le modo de icone in le selector de applicationes." 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 "" msgid ""
"Configures how the windows are shown in the switcher. Valid possibilities " "Configures how the windows are shown in the switcher. Valid possibilities "
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-" "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 " "fenestra), 'app-icon-only' (monstrar solmente un icone del application) o "
"'both' (monstrar tote le duo)." "'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" msgid "Attach modal dialog to the parent window"
msgstr "Attaccar le dialogo modal al fenestra parental" 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 "" msgid ""
"This key overrides the key in org.gnome.mutter when running GNOME Shell." "This key overrides the key in org.gnome.mutter when running GNOME Shell."
msgstr "" msgstr ""
"Iste clave supplanta le clave in org.gnome.mutter quando GNOME Shell es " "Iste clave supplanta le clave in org.gnome.mutter quando GNOME Shell es "
"lanceate." "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" msgid "Arrangement of buttons on the titlebar"
msgstr "Arrangiamento de buttones sur le barra de titulo" 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 "" msgid ""
"This key overrides the key in org.gnome.desktop.wm.preferences when running " "This key overrides the key in org.gnome.desktop.wm.preferences when running "
"GNOME Shell." "GNOME Shell."
@@ -361,15 +349,15 @@ msgstr ""
"Iste clave supplanta le clave in org.gnome.desktop.wm.preferences quando " "Iste clave supplanta le clave in org.gnome.desktop.wm.preferences quando "
"GNOME Shell es lanceate." "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" msgid "Enable edge tiling when dropping windows on screen edges"
msgstr "Activar le tegulage de fenestras depositate sur le bordos del schermo" 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" msgid "Workspaces are managed dynamically"
msgstr "Le spatios de travalio se gere dynamicamente" 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" msgid "Workspaces only on primary monitor"
msgstr "Le spatios de travalio es solmente sur le schermo principal" 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:" msgid "Execution of '%s' failed:"
msgstr "Falta al execution de '%s':" msgstr "Falta al execution de '%s':"
#: ../js/ui/appDisplay.js:351 #: ../js/ui/appDisplay.js:349
msgid "Frequent" msgid "Frequent"
msgstr "Frequente" msgstr "Frequente"
#: ../js/ui/appDisplay.js:358 #: ../js/ui/appDisplay.js:356
msgid "All" msgid "All"
msgstr "Tote" msgstr "Tote"
#: ../js/ui/appDisplay.js:916 #: ../js/ui/appDisplay.js:914
msgid "New Window" msgid "New Window"
msgstr "Nove fenestra" 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" msgid "Remove from Favorites"
msgstr "Remover del favoritos" msgstr "Remover del favoritos"
#: ../js/ui/appDisplay.js:920 #: ../js/ui/appDisplay.js:918
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Adder al favoritos" msgstr "Adder al favoritos"
@@ -1238,35 +1226,35 @@ msgstr "Expunger messages"
msgid "Notification Settings" msgid "Notification Settings"
msgstr "Parametros de notificationes" msgstr "Parametros de notificationes"
#: ../js/ui/messageTray.js:1710 #: ../js/ui/messageTray.js:1709
msgid "No Messages" msgid "No Messages"
msgstr "Necun message" msgstr "Necun message"
#: ../js/ui/messageTray.js:1783 #: ../js/ui/messageTray.js:1785
msgid "Message Tray" msgid "Message Tray"
msgstr "Tiratorio de messages" msgstr "Tiratorio de messages"
#: ../js/ui/messageTray.js:2801 #: ../js/ui/messageTray.js:2813
msgid "System Information" msgid "System Information"
msgstr "Information de systema" 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" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "Incognite" msgstr "Incognite"
#: ../js/ui/overviewControls.js:472 ../js/ui/screenShield.js:149 #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
#, c-format #, c-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
msgstr[0] "%d nove message" msgstr[0] "%d nove message"
msgstr[1] "%d nove messages" msgstr[1] "%d nove messages"
#: ../js/ui/overview.js:82 #: ../js/ui/overview.js:84
msgid "Undo" msgid "Undo"
msgstr "Disfacer" msgstr "Disfacer"
#: ../js/ui/overview.js:127 #: ../js/ui/overview.js:129
msgid "Overview" msgid "Overview"
msgstr "Panorama" msgstr "Panorama"
@@ -1274,21 +1262,21 @@ msgstr "Panorama"
#. in the search entry when no search is #. in the search entry when no search is
#. active; it should not exceed ~30 #. active; it should not exceed ~30
#. characters. #. characters.
#: ../js/ui/overview.js:260 #: ../js/ui/overview.js:271
msgid "Type to search…" msgid "Type to search…"
msgstr "Scribe pro cercar…" msgstr "Scribe pro cercar…"
#: ../js/ui/panel.js:641 #: ../js/ui/panel.js:633
msgid "Quit" msgid "Quit"
msgstr "Quitar" msgstr "Quitar"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:692 #: ../js/ui/panel.js:657
msgid "Activities" msgid "Activities"
msgstr "Activitates" msgstr "Activitates"
#: ../js/ui/panel.js:989 #: ../js/ui/panel.js:954
msgid "Top Bar" msgid "Top Bar"
msgstr "Barra superior" msgstr "Barra superior"
@@ -1297,7 +1285,7 @@ msgstr "Barra superior"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:718 #: ../js/ui/popupMenu.js:727
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" 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" msgid "List possible modes"
msgstr "Monstrar le lista del modos possibile" msgstr "Monstrar le lista del modos possibile"
#: ../src/shell-app.c:626 #: ../src/shell-app.c:622
#, c-format #, c-format
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "Impossibile de lancear '%s'" msgstr "Impossibile de lancear '%s'"

577
po/id.po

File diff suppressed because it is too large Load Diff

726
po/kn.po

File diff suppressed because it is too large Load Diff

273
po/lt.po
View File

@@ -11,9 +11,9 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-23 11:49+0000\n" "POT-Creation-Date: 2013-12-20 16:10+0000\n"
"PO-Revision-Date: 2013-03-26 22:43+0200\n" "PO-Revision-Date: 2013-12-21 16:31+0200\n"
"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n" "Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n" "Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n" "Language: lt\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -360,7 +360,7 @@ msgstr "Darbalaukiai tik pagrindiniame monitoriuje"
#: ../js/extensionPrefs/main.js:125 #: ../js/extensionPrefs/main.js:125
#, c-format #, c-format
msgid "There was an error loading the preferences dialog for %s:" 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 #: ../js/extensionPrefs/main.js:165
msgid "Extension" msgid "Extension"
@@ -370,43 +370,50 @@ msgstr "Plėtinys"
msgid "Select an extension to configure using the combobox above." msgid "Select an extension to configure using the combobox above."
msgstr "Išskleidžiamajame sąraše pasirinkite konfigūruotiną plėtinį." msgstr "Išskleidžiamajame sąraše pasirinkite konfigūruotiną plėtinį."
#: ../js/gdm/loginDialog.js:405 #: ../js/gdm/loginDialog.js:371
msgid "Session…" msgid "Session…"
msgstr "Seansas…" msgstr "Seansas…"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: ../js/gdm/loginDialog.js:630 #: ../js/gdm/loginDialog.js:601
msgid "Not listed?" msgid "Not listed?"
msgstr "Nėra sąraše?" msgstr "Nėra sąraše?"
#: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../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 #: ../js/ui/userMenu.js:938
msgid "Cancel" msgid "Cancel"
msgstr "Atsisakyti" msgstr "Atsisakyti"
#: ../js/gdm/loginDialog.js:802 #: ../js/gdm/loginDialog.js:791
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "Prisijungti" msgstr "Prisijungti"
#: ../js/gdm/loginDialog.js:802 #: ../js/gdm/loginDialog.js:791
msgid "Next" msgid "Next"
msgstr "Kitas" 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 #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (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 #: ../js/ui/components/networkAgent.js:278
msgid "Username: " msgid "Username: "
msgstr "Naudotojo vardas: " msgstr "Naudotojo vardas: "
#: ../js/gdm/loginDialog.js:1173 #: ../js/gdm/loginDialog.js:1158
msgid "Login Window" msgid "Login Window"
msgstr "Prisijungimo langas" msgstr "Prisijungimo langas"
@@ -429,21 +436,16 @@ msgstr "Paleisti iš naujo"
msgid "Power Off" msgid "Power Off"
msgstr "Išjungti" msgstr "Išjungti"
#: ../js/gdm/util.js:249 #: ../js/gdm/util.js:248
msgid "Authentication error" msgid "Authentication error"
msgstr "Tapatybės patvirtinimo klaida" msgstr "Tapatybės patvirtinimo klaida"
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:366 #: ../js/gdm/util.js:365
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(arba perbraukite pirštu)" 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 #: ../js/misc/util.js:97
msgid "Command not found" msgid "Command not found"
msgstr "Komanda nerasta" msgstr "Komanda nerasta"
@@ -459,23 +461,23 @@ msgstr "Nepavyko perskaityti komandos:"
msgid "Execution of '%s' failed:" msgid "Execution of '%s' failed:"
msgstr "Nepavyko įvykdyti „%s“:" msgstr "Nepavyko įvykdyti „%s“:"
#: ../js/ui/appDisplay.js:349 #: ../js/ui/appDisplay.js:392
msgid "Frequent" msgid "Frequent"
msgstr "Dažnai naudojamos" msgstr "Dažnai naudojamos"
#: ../js/ui/appDisplay.js:356 #: ../js/ui/appDisplay.js:399
msgid "All" msgid "All"
msgstr "Visos" msgstr "Visos"
#: ../js/ui/appDisplay.js:914 #: ../js/ui/appDisplay.js:977
msgid "New Window" msgid "New Window"
msgstr "Naujas langas" 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" msgid "Remove from Favorites"
msgstr "Pašalinti iš mėgstamų" msgstr "Pašalinti iš mėgstamų"
#: ../js/ui/appDisplay.js:918 #: ../js/ui/appDisplay.js:981
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Pridėti prie mėgstamų" msgstr "Pridėti prie mėgstamų"
@@ -512,7 +514,7 @@ msgctxt "event list time"
msgid "%H\\u2236%M" msgid "%H\\u2236%M"
msgstr "%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 #. \u2236 is a ratio character, similar to : and \u2009 is
#. a thin space #. a thin space
#: ../js/ui/calendar.js:77 #: ../js/ui/calendar.js:77
@@ -667,11 +669,11 @@ msgstr "Atverti su %s"
msgid "Eject" msgid "Eject"
msgstr "Išimti" 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:" msgid "Password:"
msgstr "Slaptažodis:" msgstr "Slaptažodis:"
#: ../js/ui/components/keyring.js:101 #: ../js/ui/components/keyring.js:107
msgid "Type again:" msgid "Type again:"
msgstr "Įveskite dar kartą:" 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'." msgid "A password is required to connect to '%s'."
msgstr "Būtinas slaptažodis norint prisijungti prie „%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" msgid "Authentication Required"
msgstr "Reikia patvirtinti tapatybę" msgstr "Reikia patvirtinti tapatybę"
#: ../js/ui/components/polkitAgent.js:93 #: ../js/ui/components/polkitAgent.js:92
msgid "Administrator" msgid "Administrator"
msgstr "Administratorius" msgstr "Administratorius"
#: ../js/ui/components/polkitAgent.js:165 #: ../js/ui/components/polkitAgent.js:170
msgid "Authenticate" msgid "Authenticate"
msgstr "Patvirtinti tapatybę" msgstr "Patvirtinti tapatybę"
@@ -767,12 +769,12 @@ msgstr "Patvirtinti tapatybę"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/components/polkitAgent.js: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." msgid "Sorry, that didn't work. Please try again."
msgstr "Atsiprašome, tai nesuveikė. Bandykite dar kartą." msgstr "Atsiprašome, tai nesuveikė. Bandykite dar kartą."
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/components/recorder.js:48 #: ../js/ui/components/recorder.js:47
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "Ekrano vaizdo įrašas iš %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 #. Translators: this is the other person changing their old IM name to their new
#. IM name. #. IM name.
#: ../js/ui/components/telepathyClient.js:985 #: ../js/ui/components/telepathyClient.js:986
#, c-format #, c-format
msgid "%s is now known as %s" msgid "%s is now known as %s"
msgstr "%s nuo šiol vadinasi %s" msgstr "%s nuo šiol vadinasi %s"
#. translators: argument is a room name like #. translators: argument is a room name like
#. * room@jabber.org for example. #. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1088 #: ../js/ui/components/telepathyClient.js:1089
#, c-format #, c-format
msgid "Invitation to %s" msgid "Invitation to %s"
msgstr "Kvietimas į %s" msgstr "Kvietimas į %s"
@@ -846,38 +848,38 @@ msgstr "Kvietimas į %s"
#. translators: first argument is the name of a contact and the second #. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org #. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example. #. * for example.
#: ../js/ui/components/telepathyClient.js:1096 #: ../js/ui/components/telepathyClient.js:1097
#, c-format #, c-format
msgid "%s is inviting you to join %s" msgid "%s is inviting you to join %s"
msgstr "%s jus kviečia prisijungti prie %s" msgstr "%s jus kviečia prisijungti prie %s"
#: ../js/ui/components/telepathyClient.js:1098 #: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1137 #: ../js/ui/components/telepathyClient.js:1138
#: ../js/ui/components/telepathyClient.js:1177 #: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1240 #: ../js/ui/components/telepathyClient.js:1241
msgid "Decline" msgid "Decline"
msgstr "Atmesti" msgstr "Atmesti"
#: ../js/ui/components/telepathyClient.js:1099 #: ../js/ui/components/telepathyClient.js:1100
#: ../js/ui/components/telepathyClient.js:1178 #: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1241 #: ../js/ui/components/telepathyClient.js:1242
msgid "Accept" msgid "Accept"
msgstr "Priimti" msgstr "Priimti"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1129 #: ../js/ui/components/telepathyClient.js:1130
#, c-format #, c-format
msgid "Video call from %s" msgid "Video call from %s"
msgstr "Vaizdo skambutis nuo %s" msgstr "Vaizdo skambutis nuo %s"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1132 #: ../js/ui/components/telepathyClient.js:1133
#, c-format #, c-format
msgid "Call from %s" msgid "Call from %s"
msgstr "Skambutis nuo %s" msgstr "Skambutis nuo %s"
#. translators: this is a button label (verb), not a noun #. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1139 #: ../js/ui/components/telepathyClient.js:1140
msgid "Answer" msgid "Answer"
msgstr "Atsiliepti" msgstr "Atsiliepti"
@@ -886,110 +888,110 @@ msgstr "Atsiliepti"
#. * file name. The string will be something #. * file name. The string will be something
#. * like: "Alice is sending you test.ogg" #. * like: "Alice is sending you test.ogg"
#. #.
#: ../js/ui/components/telepathyClient.js:1171 #: ../js/ui/components/telepathyClient.js:1172
#, c-format #, c-format
msgid "%s is sending you %s" msgid "%s is sending you %s"
msgstr "%s jums siunčia %s" msgstr "%s jums siunčia %s"
#. To translators: The parameter is the contact's alias #. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1206 #: ../js/ui/components/telepathyClient.js:1207
#, c-format #, c-format
msgid "%s would like permission to see when you are online" msgid "%s would like permission to see when you are online"
msgstr "%s pageidauja matyti, kai esate prisijungę prie interneto" msgstr "%s pageidauja matyti, kai esate prisijungę prie interneto"
#: ../js/ui/components/telepathyClient.js:1298 #: ../js/ui/components/telepathyClient.js:1299
msgid "Network error" msgid "Network error"
msgstr "Tinklo klaida" msgstr "Tinklo klaida"
#: ../js/ui/components/telepathyClient.js:1300 #: ../js/ui/components/telepathyClient.js:1301
msgid "Authentication failed" msgid "Authentication failed"
msgstr "Nepavyko patvirtinti tapatybės" msgstr "Nepavyko patvirtinti tapatybės"
#: ../js/ui/components/telepathyClient.js:1302 #: ../js/ui/components/telepathyClient.js:1303
msgid "Encryption error" msgid "Encryption error"
msgstr "Šifravimo klaida" msgstr "Šifravimo klaida"
#: ../js/ui/components/telepathyClient.js:1304 #: ../js/ui/components/telepathyClient.js:1305
msgid "Certificate not provided" msgid "Certificate not provided"
msgstr "Liudijimas nepateiktas" msgstr "Liudijimas nepateiktas"
#: ../js/ui/components/telepathyClient.js:1306 #: ../js/ui/components/telepathyClient.js:1307
msgid "Certificate untrusted" msgid "Certificate untrusted"
msgstr "Liudijimas nepatikimas" msgstr "Liudijimas nepatikimas"
#: ../js/ui/components/telepathyClient.js:1308 #: ../js/ui/components/telepathyClient.js:1309
msgid "Certificate expired" msgid "Certificate expired"
msgstr "Liudijimo galiojimas pasibaigęs" msgstr "Liudijimo galiojimas pasibaigęs"
#: ../js/ui/components/telepathyClient.js:1310 #: ../js/ui/components/telepathyClient.js:1311
msgid "Certificate not activated" msgid "Certificate not activated"
msgstr "Liudijimas neaktyvuotas" msgstr "Liudijimas neaktyvuotas"
#: ../js/ui/components/telepathyClient.js:1312 #: ../js/ui/components/telepathyClient.js:1313
msgid "Certificate hostname mismatch" msgid "Certificate hostname mismatch"
msgstr "Liudijimo serverio vardo nesutapimas" msgstr "Liudijimo serverio vardo nesutapimas"
#: ../js/ui/components/telepathyClient.js:1314 #: ../js/ui/components/telepathyClient.js:1315
msgid "Certificate fingerprint mismatch" msgid "Certificate fingerprint mismatch"
msgstr "Liudijimo piršto atspaudo nesutapimas" msgstr "Liudijimo piršto atspaudo nesutapimas"
#: ../js/ui/components/telepathyClient.js:1316 #: ../js/ui/components/telepathyClient.js:1317
msgid "Certificate self-signed" msgid "Certificate self-signed"
msgstr "Liudijimas pačių pasirašytas" msgstr "Liudijimas pačių pasirašytas"
#: ../js/ui/components/telepathyClient.js:1318 #: ../js/ui/components/telepathyClient.js:1319
msgid "Status is set to offline" msgid "Status is set to offline"
msgstr "Nustatyta atsijungimo būsena" msgstr "Nustatyta atsijungimo būsena"
#: ../js/ui/components/telepathyClient.js:1320 #: ../js/ui/components/telepathyClient.js:1321
msgid "Encryption is not available" msgid "Encryption is not available"
msgstr "Šifravimas negalimas" msgstr "Šifravimas negalimas"
#: ../js/ui/components/telepathyClient.js:1322 #: ../js/ui/components/telepathyClient.js:1323
msgid "Certificate is invalid" msgid "Certificate is invalid"
msgstr "Liudijimas netinkamas" msgstr "Liudijimas netinkamas"
#: ../js/ui/components/telepathyClient.js:1324 #: ../js/ui/components/telepathyClient.js:1325
msgid "Connection has been refused" msgid "Connection has been refused"
msgstr "Ryšys atmestas" msgstr "Ryšys atmestas"
#: ../js/ui/components/telepathyClient.js:1326 #: ../js/ui/components/telepathyClient.js:1327
msgid "Connection can't be established" msgid "Connection can't be established"
msgstr "Nepavyko užmegzti ryšio" msgstr "Nepavyko užmegzti ryšio"
#: ../js/ui/components/telepathyClient.js:1328 #: ../js/ui/components/telepathyClient.js:1329
msgid "Connection has been lost" msgid "Connection has been lost"
msgstr "Ryšys nutrūko" 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" msgid "This account is already connected to the server"
msgstr "Ši paskyra jau prijungta prie serverio" msgstr "Ši paskyra jau prijungta prie serverio"
#: ../js/ui/components/telepathyClient.js:1332 #: ../js/ui/components/telepathyClient.js:1333
msgid "" msgid ""
"Connection has been replaced by a new connection using the same resource" "Connection has been replaced by a new connection using the same resource"
msgstr "Ryšys pakeistas nauju ryšiu naudojant tą patį išteklių" 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" msgid "The account already exists on the server"
msgstr "Tokia paskyra serveryje jau yra" 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" msgid "Server is currently too busy to handle the connection"
msgstr "Šiuo metu serveris per daug užimtas šiai užklausai apdoroti" 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" msgid "Certificate has been revoked"
msgstr "Liudijimas atšauktas" msgstr "Liudijimas atšauktas"
#: ../js/ui/components/telepathyClient.js:1340 #: ../js/ui/components/telepathyClient.js:1341
msgid "" msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak" "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "" msgstr ""
"Liudijimui naudojamas nesaugus šifravimo algoritmas arba jis kriptografiškai " "Liudijimui naudojamas nesaugus šifravimo algoritmas arba jis kriptografiškai "
"silpnas" "silpnas"
#: ../js/ui/components/telepathyClient.js:1342 #: ../js/ui/components/telepathyClient.js:1343
msgid "" msgid ""
"The length of the server certificate, or the depth of the server certificate " "The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library" "chain, exceed the limits imposed by the cryptography library"
@@ -997,22 +999,22 @@ msgstr ""
"Serverio liudijimo ilgis arba liudijimų eilės dydis viršija kriptografijos " "Serverio liudijimo ilgis arba liudijimų eilės dydis viršija kriptografijos "
"bibliotekos apribojimus" "bibliotekos apribojimus"
#: ../js/ui/components/telepathyClient.js:1344 #: ../js/ui/components/telepathyClient.js:1345
msgid "Internal error" msgid "Internal error"
msgstr "Vidinė klaida" msgstr "Vidinė klaida"
#. translators: argument is the account name, like #. translators: argument is the account name, like
#. * name@jabber.org for example. #. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1354 #: ../js/ui/components/telepathyClient.js:1355
#, c-format #, c-format
msgid "Unable to connect to %s" msgid "Unable to connect to %s"
msgstr "Nepavyksta prisijungti prie %s" msgstr "Nepavyksta prisijungti prie %s"
#: ../js/ui/components/telepathyClient.js:1359 #: ../js/ui/components/telepathyClient.js:1360
msgid "View account" msgid "View account"
msgstr "Rodyti paskyrą" msgstr "Rodyti paskyrą"
#: ../js/ui/components/telepathyClient.js:1398 #: ../js/ui/components/telepathyClient.js:1399
msgid "Unknown reason" msgid "Unknown reason"
msgstr "Nežinoma priežastis" msgstr "Nežinoma priežastis"
@@ -1026,7 +1028,7 @@ msgstr "Paleisti programas"
#. Translators: this is the name of the dock/favorites area on #. Translators: this is the name of the dock/favorites area on
#. the left of the overview #. the left of the overview
#: ../js/ui/dash.js:435 #: ../js/ui/dash.js:445
msgid "Dash" msgid "Dash"
msgstr "Paleidimo sritis" msgstr "Paleidimo sritis"
@@ -1038,14 +1040,14 @@ msgstr "Atverti kalendorių"
msgid "Open Clocks" msgid "Open Clocks"
msgstr "Atverti laikrodžius" msgstr "Atverti laikrodžius"
#: ../js/ui/dateMenu.js:105 #: ../js/ui/dateMenu.js:104
msgid "Date & Time Settings" msgid "Date & Time Settings"
msgstr "Datos ir laiko nustatymai" msgstr "Datos ir laiko nustatymai"
#. Translators: This is the date format to use when the calendar popup is #. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). #. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. #.
#: ../js/ui/dateMenu.js:215 #: ../js/ui/dateMenu.js:216
msgid "%A %B %e, %Y" msgid "%A %B %e, %Y"
msgstr "%A, %Y m. %B %d d." msgstr "%A, %Y m. %B %d d."
@@ -1156,7 +1158,7 @@ msgstr "Įdiegti"
msgid "Download and install '%s' from extensions.gnome.org?" msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Atsiųsti ir įdiegti „%s“ iš 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 #: ../js/ui/status/power.js:211
msgid "Keyboard" msgid "Keyboard"
msgstr "Klaviatūra" msgstr "Klaviatūra"
@@ -1183,7 +1185,9 @@ msgstr "Rodyti klaidas"
msgid "Enabled" msgid "Enabled"
msgstr "Įjungta" 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" msgid "Disabled"
msgstr "Išjungta" msgstr "Išjungta"
@@ -1223,19 +1227,19 @@ msgstr "Išvalyti pranešimus"
msgid "Notification Settings" msgid "Notification Settings"
msgstr "Pranešimų nustatymai" msgstr "Pranešimų nustatymai"
#: ../js/ui/messageTray.js:1709 #: ../js/ui/messageTray.js:1707
msgid "No Messages" msgid "No Messages"
msgstr "Nėra pranešimų" msgstr "Nėra pranešimų"
#: ../js/ui/messageTray.js:1782 #: ../js/ui/messageTray.js:1783
msgid "Message Tray" msgid "Message Tray"
msgstr "Pranešimų juosta" msgstr "Pranešimų juosta"
#: ../js/ui/messageTray.js:2810 #: ../js/ui/messageTray.js:2822
msgid "System Information" msgid "System Information"
msgstr "Sistemos informacija" 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" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "Nežinoma" msgstr "Nežinoma"
@@ -1264,17 +1268,17 @@ msgstr "Apžvalga"
msgid "Type to search…" msgid "Type to search…"
msgstr "Rašykite, ko ieškote…" msgstr "Rašykite, ko ieškote…"
#: ../js/ui/panel.js:612 #: ../js/ui/panel.js:636
msgid "Quit" msgid "Quit"
msgstr "Užverti" msgstr "Užverti"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:636 #: ../js/ui/panel.js:687
msgid "Activities" msgid "Activities"
msgstr "Apžvalga" msgstr "Apžvalga"
#: ../js/ui/panel.js:933 #: ../js/ui/panel.js:983
msgid "Top Bar" msgid "Top Bar"
msgstr "Viršutinė juosta" msgstr "Viršutinė juosta"
@@ -1283,15 +1287,15 @@ msgstr "Viršutinė juosta"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:727 #: ../js/ui/popupMenu.js:740
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:73 #: ../js/ui/runDialog.js:74
msgid "Enter a Command" msgid "Enter a Command"
msgstr "Įveskite komandą" msgstr "Įveskite komandą"
#: ../js/ui/runDialog.js:109 #: ../js/ui/runDialog.js:110
msgid "Close" msgid "Close"
msgstr "Užverti" msgstr "Užverti"
@@ -1313,7 +1317,7 @@ msgstr[2] "%d naujų pranešimų"
msgid "Lock" msgid "Lock"
msgstr "Užrakinti" msgstr "Užrakinti"
#: ../js/ui/screenShield.js:637 #: ../js/ui/screenShield.js:642
msgid "GNOME needs to lock the screen" msgid "GNOME needs to lock the screen"
msgstr "GNOME aplinkai reikia užrakinti ekraną" 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 #. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs #. 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" msgid "Unable to lock"
msgstr "Nepavyksta užrakinti" 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" msgid "Lock was blocked by an application"
msgstr "Programa užblokavo užrakinimą" msgstr "Programa užblokavo užrakinimą"
@@ -1340,19 +1344,19 @@ msgstr "Ieškoma…"
msgid "No results." msgid "No results."
msgstr "Nerasta atitikmenų." msgstr "Nerasta atitikmenų."
#: ../js/ui/shellEntry.js:29 #: ../js/ui/shellEntry.js:27
msgid "Copy" msgid "Copy"
msgstr "Kopijuoti" msgstr "Kopijuoti"
#: ../js/ui/shellEntry.js:34 #: ../js/ui/shellEntry.js:32
msgid "Paste" msgid "Paste"
msgstr "Įdėti" msgstr "Įdėti"
#: ../js/ui/shellEntry.js:106 #: ../js/ui/shellEntry.js:99
msgid "Show Text" msgid "Show Text"
msgstr "Rodyti tekstą" msgstr "Rodyti tekstą"
#: ../js/ui/shellEntry.js:108 #: ../js/ui/shellEntry.js:101
msgid "Hide Text" msgid "Hide Text"
msgstr "Slėpti tekstą" msgstr "Slėpti tekstą"
@@ -1364,7 +1368,7 @@ msgstr "Slaptažodis"
msgid "Remember Password" msgid "Remember Password"
msgstr "Atsiminti slaptažodį" 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" msgid "Unlock"
msgstr "Atrakinti" msgstr "Atrakinti"
@@ -1533,11 +1537,12 @@ msgstr "Įveskite PIN, nurodytą įrenginyje."
msgid "OK" msgid "OK"
msgstr "Gerai" msgstr "Gerai"
#: ../js/ui/status/keyboard.js:368 #: ../js/ui/status/keyboard.js:396
msgid "Show Keyboard Layout" msgid "Show Keyboard Layout"
msgstr "Rodyti klaviatūros išdėstymą" 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" msgid "Region & Language Settings"
msgstr "Regiono ir kalbos nustatymai" msgstr "Regiono ir kalbos nustatymai"
@@ -1655,7 +1660,7 @@ msgstr "Nepavyko prisijungti"
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "Tinklo ryšio nepavyko aktyvuoti" msgstr "Tinklo ryšio nepavyko aktyvuoti"
#: ../js/ui/status/network.js:2276 #: ../js/ui/status/network.js:2282
msgid "Networking is disabled" msgid "Networking is disabled"
msgstr "Tinklas išjungtas" msgstr "Tinklas išjungtas"
@@ -1773,11 +1778,11 @@ msgstr "Garsumas"
msgid "Microphone" msgid "Microphone"
msgstr "Mikrofonas" msgstr "Mikrofonas"
#: ../js/ui/unlockDialog.js:124 #: ../js/ui/unlockDialog.js:120
msgid "Log in as another user" msgid "Log in as another user"
msgstr "Prisijungti kitu naudotoju" msgstr "Prisijungti kitu naudotoju"
#: ../js/ui/unlockDialog.js:145 #: ../js/ui/unlockDialog.js:141
msgid "Unlock Window" msgid "Unlock Window"
msgstr "Atrakinimo langas" msgstr "Atrakinimo langas"
@@ -1885,32 +1890,56 @@ msgstr "„%s“ yra pasirengusi"
msgid "Evolution Calendar" msgid "Evolution Calendar"
msgstr "Evolution kalendorius" 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" msgid "Print version"
msgstr "Išvesti versijos numerį" msgstr "Išvesti versijos numerį"
#: ../src/main.c:353 #: ../src/main.c:334
msgid "Mode used by GDM for login screen" msgid "Mode used by GDM for login screen"
msgstr "Veiksena, naudojama GDM prisijungimo ekrane" 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" msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "Naudoti konkrečią veikseną, pvz., „gdm“ prisijungimo ekranui" msgstr "Naudoti konkrečią veikseną, pvz., „gdm“ prisijungimo ekranui"
#: ../src/main.c:365 #: ../src/main.c:346
msgid "List possible modes" msgid "List possible modes"
msgstr "Išvardinti galimas veiksenas" msgstr "Išvardinti galimas veiksenas"
#: ../src/shell-app.c:622 #: ../src/shell-app.c:640
#, c-format #, c-format
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "Nepavyko paleisti „%s“" msgstr "Nepavyko paleisti „%s“"
#: ../src/shell-keyring-prompt.c:708 #: ../src/shell-keyring-prompt.c:714
msgid "Passwords do not match." msgid "Passwords do not match."
msgstr "Slaptažodžiai nesutampa." msgstr "Slaptažodžiai nesutampa."
#: ../src/shell-keyring-prompt.c:716 #: ../src/shell-keyring-prompt.c:722
msgid "Password cannot be blank" msgid "Password cannot be blank"
msgstr "Slaptažodis negali būti tuščias" 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" msgid "Authentication dialog was dismissed by the user"
msgstr "Naudotojas užvėrė tapatybės patvirtinimo dialogą" msgstr "Naudotojas užvėrė tapatybės patvirtinimo dialogą"
#~ msgid "%u Output" #~ msgctxt "event list time"
#~ msgid_plural "%u Outputs" #~ msgid "%H%M"
#~ msgstr[0] "%u išvestis" #~ msgstr "%H%M"
#~ msgstr[1] "%u išvestys"
#~ msgstr[2] "%u išvesčių"
#~ msgid "%u Input" #~ msgctxt "event list time"
#~ msgid_plural "%u Inputs" #~ msgid "%l%M%p"
#~ msgstr[0] "%u įvestis" #~ msgstr "%l%M"
#~ msgstr[1] "%u įvestys"
#~ msgstr[2] "%u įvesčių"
#~ msgid "System Sounds" #~ msgid "calendar:MY"
#~ msgstr "Sistemos garsai" #~ msgstr "calendar:YM"
#~| msgid "Network error"
#~ msgid "Network"
#~ msgstr "Tinklas"

320
po/ml.po
View File

@@ -10,9 +10,9 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-04-24 18:23+0000\n" "POT-Creation-Date: 2013-03-23 11:49+0000\n"
"PO-Revision-Date: 2013-04-25 00:32+0530\n" "PO-Revision-Date: 2013-03-25 14:57+0530\n"
"Last-Translator: Balasankar C <c.balasankar@gmail.com>\n" "Last-Translator: Ani Peter <peter.ani@gmail.com>\n"
"Language-Team: American English <kde-i18n-doc@kde.org>\n" "Language-Team: American English <kde-i18n-doc@kde.org>\n"
"Language: ml\n" "Language: ml\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -44,14 +44,10 @@ msgid "Focus the active notification"
msgstr "സജീവമായ അറിയിപ്പിനെ കേന്ദ്രീകരിക്കുക" msgstr "സജീവമായ അറിയിപ്പിനെ കേന്ദ്രീകരിക്കുക"
#: ../data/50-gnome-shell-system.xml.in.h:4 #: ../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" msgid "Show all applications"
msgstr "എല്ലാ പ്രയോഗങ്ങളും കാണിയ്ക്കുക" msgstr "എല്ലാ പ്രയോഗങ്ങളും കാണിയ്ക്കുക"
#: ../data/50-gnome-shell-system.xml.in.h:6 #: ../data/50-gnome-shell-system.xml.in.h:5
msgid "Open the application menu" msgid "Open the application menu"
msgstr "പ്രയോഗത്തിന്റെ മെനു തുറക്കുക" msgstr "പ്രയോഗത്തിന്റെ മെനു തുറക്കുക"
@@ -75,7 +71,8 @@ msgstr "ഗ്നോം ഷെല്‍ എക്സ്റ്റെന്‍ഷ
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1 #: ../data/org.gnome.shell.gschema.xml.in.in.h:1
msgid "Enable internal tools useful for developers and testers from Alt-F2" msgid "Enable internal tools useful for developers and testers from Alt-F2"
msgstr "" msgstr ""
"Alt-F2-ല്‍ ഡവലപ്പര്‍മാര്‍ക്കും ടെസ്റ്റേര്‍സിനും പ്രയോജനകരമായ ആന്തരിക പ്രയോഗങ്ങള്‍ പ്രവര്‍ത്തന " "Alt-F2-ല്‍ ഡവലപ്പര്‍മാര്‍ക്കും ടെസ്റ്റേര്‍സിനും പ്രയോജനകരമായ ആന്തരിക "
"പ്രയോഗങ്ങള്‍ പ്രവര്‍ത്തന "
"സജ്ജമാക്കുന്നു" "സജ്ജമാക്കുന്നു"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:2 #: ../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 " "Allows access to internal debugging and monitoring tools using the Alt-F2 "
"dialog." "dialog."
msgstr "" msgstr ""
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും പ്രവേശനം " "Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും "
"പ്രവേശനം "
"അനുവദിയ്ക്കുക." "അനുവദിയ്ക്കുക."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:3 #: ../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 " "list. You can also manipulate this list with the EnableExtension and "
"DisableExtension DBus methods on org.gnome.Shell." "DisableExtension DBus methods on org.gnome.Shell."
msgstr "" msgstr ""
"ഗ്നോം ഷെല്‍ എക്സ്റ്റെന്‍ഷനുകള്‍ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട എക്സ്റ്റെന്‍ഷനുകള്‍ ഈ കീ പട്ടിക " "ഗ്നോം ഷെല്‍ എക്സ്റ്റെന്‍ഷനുകള്‍ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട "
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്‍ഷനും ഈ പട്ടികയിലുണ്ടാവണം. org.gnome.Shell-ല്‍ " "എക്സ്റ്റെന്‍ഷനുകള്‍ ഈ കീ പട്ടിക "
"നിങ്ങള്‍ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ പട്ടിക " "ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്‍ഷനും ഈ പട്ടികയിലുണ്ടാവണം. "
"org.gnome.Shell-ല്‍ "
"നിങ്ങള്‍ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ "
"പട്ടിക "
"കൈകാര്യം ചെയ്യുവാനും സാധിയ്ക്കുന്നു." "കൈകാര്യം ചെയ്യുവാനും സാധിയ്ക്കുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5 #: ../data/org.gnome.shell.gschema.xml.in.in.h:5
msgid "Whether to collect stats about applications usage" msgid "Whether to collect stats about applications usage"
msgstr "പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള്‍ ശേഖരിയ്ക്കണമോ എന്നു്" msgstr ""
"പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള്‍ ശേഖരിയ്ക്കണമോ "
"എന്നു്"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:6 #: ../data/org.gnome.shell.gschema.xml.in.in.h:6
msgid "" msgid ""
@@ -113,9 +116,12 @@ msgid ""
"want to disable this for privacy reasons. Please note that doing so won't " "want to disable this for privacy reasons. Please note that doing so won't "
"remove already saved data." "remove already saved data."
msgstr "" msgstr ""
"ഏറ്റവും കൂടുതല്‍ തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള്‍ ലഭ്യമാക്കുന്നതിനായി ഷെല്‍ സാധാരണയായി സജീവമായ " "ഏറ്റവും കൂടുതല്‍ തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള്‍ ലഭ്യമാക്കുന്നതിനായി ഷെല്‍ "
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്‍സ്). ഈ ഡേറ്റാ സ്വകാര്യമായി " "സാധാരണയായി സജീവമായ "
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല്‍ ഇതു് പ്രവര്‍ത്തന രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് " "പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്‍സ്). ഈ ഡേറ്റാ "
"സ്വകാര്യമായി "
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല്‍ ഇതു് പ്രവര്‍ത്തന "
"രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
"നിങ്ങള്‍ സൂക്ഷിച്ച ഡേറ്റയെ ബാധിയ്ക്കുന്നതല്ല." "നിങ്ങള്‍ സൂക്ഷിച്ച ഡേറ്റയെ ബാധിയ്ക്കുന്നതല്ല."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7 #: ../data/org.gnome.shell.gschema.xml.in.in.h:7
@@ -126,7 +132,8 @@ msgstr "ഇഷ്ടമുള്ള പ്രയോഗങ്ങള്‍ക്
msgid "" msgid ""
"The applications corresponding to these identifiers will be displayed in the " "The applications corresponding to these identifiers will be displayed in the "
"favorites area." "favorites area."
msgstr "ഈ ഐഡന്റിഫയറുകള്‍ക്കുള്ള പ്രയോഗങ്ങള്‍ ഉചിതമായ സ്ഥലങ്ങളില്‍ കാണിയ്ക്കുന്നു." msgstr ""
"ഈ ഐഡന്റിഫയറുകള്‍ക്കുള്ള പ്രയോഗങ്ങള്‍ ഉചിതമായ സ്ഥലങ്ങളില്‍ കാണിയ്ക്കുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9 #: ../data/org.gnome.shell.gschema.xml.in.in.h:9
msgid "List of categories that should be displayed as folders" 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 " "Each category name in this list will be represented as folder in the "
"application view, rather than being displayed inline in the main view." "application view, rather than being displayed inline in the main view."
msgstr "" msgstr ""
"ഈ പട്ടികയിലുള്ള ഓരോ വിഭാഗത്തിന്റെ പേരും, പ്രധാന കാഴ്ചയില്‍ ഓരോ വരിയായി കാണിയ്ക്കുന്നതിനു് " "ഈ പട്ടികയിലുള്ള ഓരോ വിഭാഗത്തിന്റെ പേരും, പ്രധാന കാഴ്ചയില്‍ ഓരോ വരിയായി "
"പകരം പ്രയോഗങ്ങളുടെ കാഴ്ചയില്‍ ഫോള്‍ഡറായി കാണിയ്ക്കുന്നു. " "കാണിയ്ക്കുന്നതിനു് പകരം പ്രയോഗങ്ങളുടെ കാഴ്ചയില്‍ ഫോള്‍ഡറായി കാണിയ്ക്കുന്നു. "
#: ../data/org.gnome.shell.gschema.xml.in.in.h:11 #: ../data/org.gnome.shell.gschema.xml.in.in.h:11
msgid "History for command (Alt-F2) dialog" 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. " "Internally used to store the last IM presence explicitly set by the user. "
"The value here is from the TpConnectionPresenceType enumeration." "The value here is from the TpConnectionPresenceType enumeration."
msgstr "" msgstr ""
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം " "ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
"TpConnectionPresenceType തരത്തിലുള്ളതാകുന്നു." "TpConnectionPresenceType തരത്തിലുള്ളതാകുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14 #: ../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 " "Internally used to store the last session presence status for the user. The "
"value here is from the GsmPresenceStatus enumeration." "value here is from the GsmPresenceStatus enumeration."
msgstr "" msgstr ""
"ഉപയോക്താവിനുള്ള അവസാന സെഷന്‍ അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം " "ഉപയോക്താവിനുള്ള അവസാന സെഷന്‍ അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
"GsmPresenceStatus തരത്തിലുള്ളതാകുന്നു." "GsmPresenceStatus തരത്തിലുള്ളതാകുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15 #: ../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-" "This key overrides the automatic hiding of the 'Log out' menuitem in single-"
"user, single-session situations." "user, single-session situations."
msgstr "" msgstr ""
"സിംഗിള്‍ യൂസര്‍, സിംഗിള്‍ സെഷനില്‍ 'ലോഗൌട്ട്' മെനുവസ്തു അദൃശ്യമാക്കുന്നതിനായി ഈ കീ ഉപയോഗിയ്ക്കുന്നു" "സിംഗിള്‍ യൂസര്‍, സിംഗിള്‍ സെഷനില്‍ 'ലോഗൌട്ട്' മെനുവസ്തു അദൃശ്യമാക്കുന്നതിനായി "
"ഈ കീ ഉപയോഗിയ്ക്കുന്നു"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17 #: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid "" msgid ""
"Whether to remember password for mounting encrypted or remote filesystems" "Whether to remember password for mounting encrypted or remote filesystems"
msgstr "" msgstr ""
"എന്‍ക്രിപ്റ്റ് ചെയ്തതോ വിദൂരമോ ആയ ഫയല്‍സിസ്റ്റങ്ങള്‍ മൌണ്ട് ചെയ്യുമ്പോഴുള്ള രഹസ്യവാക്ക് ഓര്‍മ്മിക്കണോ എന്ന്" "എന്‍ക്രിപ്റ്റ് ചെയ്തതോ വിദൂരമോ ആയ ഫയല്‍സിസ്റ്റങ്ങള്‍ മൌണ്ട് ചെയ്യുമ്പോഴുള്ള "
"രഹസ്യവാക്ക് ഓര്‍മ്മിക്കണോ എന്ന്"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18 #: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid "" msgid ""
@@ -188,9 +199,10 @@ msgid ""
"'Remember Password' checkbox will be present. This key sets the default " "'Remember Password' checkbox will be present. This key sets the default "
"state of the checkbox." "state of the checkbox."
msgstr "" msgstr ""
"ഒരു എന്‍ക്രിപ്റ്റ് ചെയ്ത ഡിവൈസ് അല്ലെങ്കില്‍ വിദൂര ഫയല്‍സിസ്റ്റം മൌണ്ട് ചെയ്യുമ്പോള്‍ ഷെല്‍ ഒരു രഹസ്യവാക്ക് " "ഒരു എന്‍ക്രിപ്റ്റ് ചെയ്ത ഡിവൈസ് അല്ലെങ്കില്‍ വിദൂര ഫയല്‍സിസ്റ്റം മൌണ്ട് "
"ആവശ്യപ്പെടുന്നു. രഹസ്യവാക്ക് സൂക്ഷിയ്ക്കുവാന്‍ സാധ്യമെങ്കില്‍, 'രഹസ്യവാക്ക് ഓര്‍ത്തു്വയ്ക്കുക' ചെക്ക്ബോക്സ് " "ചെയ്യുമ്പോള്‍ ഷെല്‍ ഒരു രഹസ്യവാക്ക് ആവശ്യപ്പെടുന്നു. രഹസ്യവാക്ക് "
"കാണാം. ഈ കീ ചെക്ക്ബോക്സിന്റെ സ്വതവേയുള്ള അവസ്ഥ സജ്ജമാക്കുന്നു." "സൂക്ഷിയ്ക്കുവാന്‍ സാധ്യമെങ്കില്‍, 'രഹസ്യവാക്ക് ഓര്‍ത്തു്വയ്ക്കുക' "
"ചെക്ക്ബോക്സ് കാണാം. ഈ കീ ചെക്ക്ബോക്സിന്റെ സ്വതവേയുള്ള അവസ്ഥ സജ്ജമാക്കുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19 #: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
@@ -216,65 +228,61 @@ msgstr "\"പ്രയോഗങ്ങള്‍ കാണിയ്ക്കുക
msgid "" msgid ""
"Keybinding to open the \"Show Applications\" view of the Activities Overview." "Keybinding to open the \"Show Applications\" view of the Activities Overview."
msgstr "" msgstr ""
"പ്രവര്‍ത്തികളുടെ അവലോകനത്തിന്റെ \"പ്രയോഗങ്ങള്‍ കാണിയ്ക്കുക\" എന്ന കാഴ്ച തുറക്കുന്നതിനുള്ള കീബൈന്‍ഡിങ്" "പ്രവര്‍ത്തികളുടെ അവലോകനത്തിന്റെ \"പ്രയോഗങ്ങള്‍ കാണിയ്ക്കുക\" എന്ന കാഴ്ച "
"തുറക്കുന്നതിനുള്ള കീബൈന്‍ഡിങ്"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25 #: ../data/org.gnome.shell.gschema.xml.in.in.h: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" msgid "Keybinding to toggle the visibility of the message tray"
msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള്‍ ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം" msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള്‍ ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28 #: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid "Keybinding to toggle the visibility of the message tray." msgid "Keybinding to toggle the visibility of the message tray."
msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള്‍ ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം." msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള്‍ ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29 #: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "Keybinding to focus the active notification" msgid "Keybinding to focus the active notification"
msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്‍ഡിങ്" msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്‍ഡിങ്"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30 #: ../data/org.gnome.shell.gschema.xml.in.in.h:28
msgid "Keybinding to focus the active notification." msgid "Keybinding to focus the active notification."
msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്‍ഡിങ്." msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്‍ഡിങ്."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31 #: ../data/org.gnome.shell.gschema.xml.in.in.h:29
msgid "Keybinding to toggle the screen recorder" msgid "Keybinding to toggle the screen recorder"
msgstr "സ്ക്രീന്‍ റിക്കോര്‍ഡര്‍ ടൊഗ്ഗിള്‍ ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം" 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." 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" msgid "Which keyboard to use"
msgstr "ഏതു് കീബോര്‍ഡ് ഉപയോഗിയ്ക്കണം" 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." msgid "The type of keyboard to use."
msgstr "ഏതു് തരം കീബോര്‍ഡ് ഉപയോഗിയ്ക്കണം." 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." msgid "Framerate used for recording screencasts."
msgstr "സ്ക്രീന്‍കാസ്റ്റുകള്‍ റിക്കോര്‍ഡ് ചെയ്യുന്നതിനുള്ള ഫ്രെയിം റേറ്റ്." msgstr "സ്ക്രീന്‍കാസ്റ്റുകള്‍ റിക്കോര്‍ഡ് ചെയ്യുന്നതിനുള്ള ഫ്രെയിം റേറ്റ്."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36 #: ../data/org.gnome.shell.gschema.xml.in.in.h:34
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
msgstr "" 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" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "സ്ക്രീന്‍കാസ്റ്റ് എന്‍കോഡ് ചെയ്യുന്നതിനുള്ള gstreamer പൈപ്പ്‌ലൈന്‍" 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 #, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@@ -288,68 +296,78 @@ msgid ""
"threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is " "threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is "
"used as a placeholder for a guess at the optimal thread count on the system." "used as a placeholder for a guess at the optimal thread count on the system."
msgstr "" msgstr ""
"റിക്കോര്‍ഡിങുകള്‍ എന്‍കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന്‍ ഉപയോഗിയ്ക്കുന്നു. gst-launch-" "റിക്കോര്‍ഡിങുകള്‍ എന്‍കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന്‍ "
"നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള്‍ കാലിയാകുന്നു.ഇതു് നിലവില്‍ 'vp8enc " "ഉപയോഗിയ്ക്കുന്നു. gst-launch-"
"നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള്‍ "
"കാലിയാകുന്നു.ഇതു് നിലവില്‍ 'vp8enc "
"min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! " "min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! "
"queue ! webmmux' ആകുന്നുസ WEBM VP8 കോഡ് ഉപയോഗിച്ചു് റിക്കോര്‍ഡ് ചെയ്യുന്നു." "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" msgid "File extension used for storing the screencast"
msgstr "സ്ക്രീന്‍കാസ്റ്റ് സൂക്ഷിയ്ക്കുന്നതിനുള്ള ഫയല്‍ എക്സ്റ്റെന്‍ഷന്‍" msgstr "സ്ക്രീന്‍കാസ്റ്റ് സൂക്ഷിയ്ക്കുന്നതിനുള്ള ഫയല്‍ എക്സ്റ്റെന്‍ഷന്‍"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41 #: ../data/org.gnome.shell.gschema.xml.in.in.h:39
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
"a different container format." "a different container format."
msgstr "" 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." msgid "The application icon mode."
msgstr "പ്രയോഗത്തിന്റെ ഐക്കണ്‍ മോഡ്." msgstr "പ്രയോഗത്തിന്റെ ഐക്കണ്‍ മോഡ്."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43 #: ../data/org.gnome.shell.gschema.xml.in.in.h:41
msgid "" msgid ""
"Configures how the windows are shown in the switcher. Valid possibilities " "Configures how the windows are shown in the switcher. Valid possibilities "
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-" "are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
"only' (shows only the application icon) or 'both'." "only' (shows only the application icon) or 'both'."
msgstr "" msgstr ""
"സ്വിച്ചറില്‍ ജാലകങ്ങള്‍ എങ്ങനെ കാണിയ്ക്കുന്നു എന്നു് ക്രമീകരിയ്ക്കുന്നു. ശരിയായ സാധ്യതകള്‍: " "സ്വിച്ചറില്‍ ജാലകങ്ങള്‍ എങ്ങനെ കാണിയ്ക്കുന്നു എന്നു് ക്രമീകരിയ്ക്കുന്നു. "
"'thumbnail-only' (ജാലകത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു), 'app-icon-" "ശരിയായ "
"സാധ്യതകള്‍: 'thumbnail-only' (ജാലകത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു), "
"'app-icon-"
"only' (പ്രയോഗത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു) അല്ലെങ്കില്‍ 'both'." "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" msgid "Attach modal dialog to the parent window"
msgstr "പേരന്റ് ജാലകത്തിലേക്കു് ഡയലോഗ് ചേര്‍ക്കുക" msgstr "പേരന്റ് ജാലകത്തിലേക്കു് ഡയലോഗ് ചേര്‍ക്കുക"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:45 #: ../data/org.gnome.shell.gschema.xml.in.in.h:43
msgid "" msgid ""
"This key overrides the key in org.gnome.mutter when running GNOME Shell." "This key overrides the key in org.gnome.mutter when running GNOME Shell."
msgstr "ഗ്നോം ഷെല്‍ പ്രവര്‍ത്തിയ്ക്കുമ്പോള്‍ 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" msgid "Arrangement of buttons on the titlebar"
msgstr "തലക്കെട്ടിനുള്ള ബാറില്‍ ബട്ടണുകളുടെ ക്രമീകരണം" msgstr "തലക്കെട്ടിനുള്ള ബാറില്‍ ബട്ടണുകളുടെ ക്രമീകരണം"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:47 #: ../data/org.gnome.shell.gschema.xml.in.in.h:45
msgid "" msgid ""
"This key overrides the key in org.gnome.desktop.wm.preferences when running " "This key overrides the key in org.gnome.desktop.wm.preferences when running "
"GNOME Shell." "GNOME Shell."
msgstr "" 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" 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" msgid "Workspaces are managed dynamically"
msgstr "പണിയിടങ്ങള്‍ ഡയനാമിക്കായി കൈകാര്യം ചെയ്തിരിക്കുന്നു" 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" msgid "Workspaces only on primary monitor"
msgstr "പ്രധാന മോണിറ്ററില്‍ മാത്രം പണിയിടങ്ങള്‍" msgstr "പ്രധാന മോണിറ്ററില്‍ മാത്രം പണിയിടങ്ങള്‍"
@@ -364,9 +382,12 @@ msgstr "എക്സ്റ്റെന്‍ഷന്‍"
#: ../js/extensionPrefs/main.js:189 #: ../js/extensionPrefs/main.js:189
msgid "Select an extension to configure using the combobox above." msgid "Select an extension to configure using the combobox above."
msgstr "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു എക്സ്റ്റെന്‍ഷന്‍ തെര‍ഞ്ഞെടുക്കുക." msgstr ""
"മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു "
"എക്സ്റ്റെന്‍ഷന്‍ തെര‍ഞ്ഞെടുക്കുക."
#: ../js/gdm/loginDialog.js:405 #: ../js/gdm/loginDialog.js:405
#| msgid "Session..."
msgid "Session…" msgid "Session…"
msgstr "പ്രവര്‍ത്തനവേള..." msgstr "പ്രവര്‍ത്തനവേള..."
@@ -377,32 +398,32 @@ msgstr "പ്രവര്‍ത്തനവേള..."
msgid "Not listed?" msgid "Not listed?"
msgstr "ലഭ്യമല്ലേ?" msgstr "ലഭ്യമല്ലേ?"
#: ../js/gdm/loginDialog.js:787 ../js/ui/components/networkAgent.js:137 #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376 #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../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 #: ../js/ui/userMenu.js:938
msgid "Cancel" msgid "Cancel"
msgstr "വേണ്ട" msgstr "വേണ്ട"
#: ../js/gdm/loginDialog.js:803 #: ../js/gdm/loginDialog.js:802
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "അകത്തുകയറുക" msgstr "അകത്തുകയറുക"
#: ../js/gdm/loginDialog.js:803 #: ../js/gdm/loginDialog.js:802
msgid "Next" msgid "Next"
msgstr "അടുത്തത്" msgstr "അടുത്തത്"
#. TTLS and PEAP are actually much more complicated, but this complication #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (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 #: ../js/ui/components/networkAgent.js:278
msgid "Username: " msgid "Username: "
msgstr "ഉപയോക്തൃ നാമം: " msgstr "ഉപയോക്തൃ നാമം: "
#: ../js/gdm/loginDialog.js:1174 #: ../js/gdm/loginDialog.js:1173
msgid "Login Window" msgid "Login Window"
msgstr "പ്രവേശന ജാലകം" msgstr "പ്രവേശന ജാലകം"
@@ -455,23 +476,23 @@ msgstr "ആജ്ഞ പ്രാവര്‍ത്തികമാക്കാ
msgid "Execution of '%s' failed:" msgid "Execution of '%s' failed:"
msgstr "'%s' നടപ്പിലാക്കുന്നതില്‍ പരാജയപ്പെട്ടു:" msgstr "'%s' നടപ്പിലാക്കുന്നതില്‍ പരാജയപ്പെട്ടു:"
#: ../js/ui/appDisplay.js:351 #: ../js/ui/appDisplay.js:349
msgid "Frequent" msgid "Frequent"
msgstr "ഇടയ്ക്കിടെ" msgstr "ഇടയ്ക്കിടെ"
#: ../js/ui/appDisplay.js:358 #: ../js/ui/appDisplay.js:356
msgid "All" msgid "All"
msgstr "എല്ലാം" msgstr "എല്ലാം"
#: ../js/ui/appDisplay.js:916 #: ../js/ui/appDisplay.js:914
msgid "New Window" msgid "New Window"
msgstr "പുതിയ വിന്‍ഡോ" 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" msgid "Remove from Favorites"
msgstr "ഇഷ്ടപ്പെട്ടവയില്‍ നിന്നും നീക്കം ചെയ്യുക" msgstr "ഇഷ്ടപ്പെട്ടവയില്‍ നിന്നും നീക്കം ചെയ്യുക"
#: ../js/ui/appDisplay.js:920 #: ../js/ui/appDisplay.js:918
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "ഇഷ്ടപ്പെട്ടവയിലേക്ക് ചേര്‍ക്കുക" msgstr "ഇഷ്ടപ്പെട്ടവയിലേക്ക് ചേര്‍ക്കുക"
@@ -508,7 +529,7 @@ msgctxt "event list time"
msgid "%H\\u2236%M" msgid "%H\\u2236%M"
msgstr "%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 #. \u2236 is a ratio character, similar to : and \u2009 is
#. a thin space #. a thin space
#: ../js/ui/calendar.js:77 #: ../js/ui/calendar.js:77
@@ -711,7 +732,8 @@ msgid ""
"Passwords or encryption keys are required to access the wireless network " "Passwords or encryption keys are required to access the wireless network "
"'%s'." "'%s'."
msgstr "" msgstr ""
"വയര്‍ലെസ് നെറ്റ്‌വര്‍ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള്‍ അല്ലെങ്കില്‍ എന്‍ക്രിപ്ഷന്‍ കീകള്‍ " "വയര്‍ലെസ് നെറ്റ്‌വര്‍ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള്‍ "
"അല്ലെങ്കില്‍ എന്‍ക്രിപ്ഷന്‍ കീകള്‍ "
"ആവശ്യമുണ്ടു്." "ആവശ്യമുണ്ടു്."
#: ../js/ui/components/networkAgent.js:314 #: ../js/ui/components/networkAgent.js:314
@@ -768,7 +790,7 @@ msgid "Sorry, that didn't work. Please try again."
msgstr "ക്ഷമിക്കണം, അതു ശരിയല്ല. ദയവായി വീണ്ടും ശ്രമിക്കുക." msgstr "ക്ഷമിക്കണം, അതു ശരിയല്ല. ദയവായി വീണ്ടും ശ്രമിക്കുക."
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/components/recorder.js:47 #: ../js/ui/components/recorder.js:48
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "%d-ല്‍ നിന്നുള്ള സ്ക്രീന്‍കാസ്റ്റ്, %t-ല്‍" msgstr "%d-ല്‍ നിന്നുള്ള സ്ക്രീന്‍കാസ്റ്റ്, %t-ല്‍"
@@ -891,7 +913,8 @@ msgstr "%s നിങ്ങള്‍ക്കു് %s അയച്ചിരി
#: ../js/ui/components/telepathyClient.js:1206 #: ../js/ui/components/telepathyClient.js:1206
#, c-format #, c-format
msgid "%s would like permission to see when you are online" msgid "%s would like permission to see when you are online"
msgstr "നിങ്ങള്‍ ഓണ്‍ലൈന്‍ ആകുമ്പോള്‍ കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്" msgstr ""
"നിങ്ങള്‍ ഓണ്‍ലൈന്‍ ആകുമ്പോള്‍ കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
#: ../js/ui/components/telepathyClient.js:1298 #: ../js/ui/components/telepathyClient.js:1298
msgid "Network error" msgid "Network error"
@@ -964,7 +987,9 @@ msgstr "ഈ അക്കൌണ്ട് നിലവില്‍ സര്‍വ
#: ../js/ui/components/telepathyClient.js:1332 #: ../js/ui/components/telepathyClient.js:1332
msgid "" msgid ""
"Connection has been replaced by a new connection using the same resource" "Connection has been replaced by a new connection using the same resource"
msgstr "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന്‍ ഉപയോഗിച്ചു് ഈ കണക്ഷന്‍ മാറ്റിസ്ഥാപിയ്ക്കുന്നു" msgstr ""
"അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന്‍ ഉപയോഗിച്ചു് ഈ കണക്ഷന്‍ "
"മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
#: ../js/ui/components/telepathyClient.js:1334 #: ../js/ui/components/telepathyClient.js:1334
msgid "The account already exists on the server" msgid "The account already exists on the server"
@@ -981,14 +1006,17 @@ msgstr "സമ്മതപത്രം വീണ്ടും ആവശ്യപ
#: ../js/ui/components/telepathyClient.js:1340 #: ../js/ui/components/telepathyClient.js:1340
msgid "" msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak" "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര്‍ ആല്‍ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു അല്ലെങ്കില്‍ ഉചിതമല്ല" msgstr ""
"സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര്‍ ആല്‍ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു "
"അല്ലെങ്കില്‍ ഉചിതമല്ല"
#: ../js/ui/components/telepathyClient.js:1342 #: ../js/ui/components/telepathyClient.js:1342
msgid "" msgid ""
"The length of the server certificate, or the depth of the server certificate " "The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library" "chain, exceed the limits imposed by the cryptography library"
msgstr "" msgstr ""
"സര്‍വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില്‍ സര്‍വര്‍ സമ്മതപത്ര ചെയിന്റെ വ്യാപ്തി, എന്നിവ " "സര്‍വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില്‍ സര്‍വര്‍ സമ്മതപത്ര "
"ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
"പരിധിയില്‍ കൂടുന്നു" "പരിധിയില്‍ കൂടുന്നു"
#: ../js/ui/components/telepathyClient.js:1344 #: ../js/ui/components/telepathyClient.js:1344
@@ -1057,7 +1085,8 @@ msgstr "പുറത്ത് കടക്കുക"
#: ../js/ui/endSessionDialog.js:65 #: ../js/ui/endSessionDialog.js:65
msgid "Click Log Out to quit these applications and log out of the system." msgid "Click Log Out to quit these applications and log out of the system."
msgstr "" msgstr ""
"ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് ചെയ്തു് സിസ്റ്റത്തില്‍ നിന്നും " "ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് "
"ചെയ്തു് സിസ്റ്റത്തില്‍ നിന്നും "
"പുറത്തു് കടക്കുക." "പുറത്തു് കടക്കുക."
#: ../js/ui/endSessionDialog.js:67 #: ../js/ui/endSessionDialog.js:67
@@ -1091,7 +1120,8 @@ msgstr "നിര്‍ത്തുക"
#: ../js/ui/endSessionDialog.js:84 #: ../js/ui/endSessionDialog.js:84
msgid "Click Power Off to quit these applications and power off the system." msgid "Click Power Off to quit these applications and power off the system."
msgstr "" msgstr ""
"ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര്‍ ഓഫ് ചെയ്യുക ക്ലിക്ക് ചെയ്തു സിസ്റ്റിന്റെ പവര്‍ " "ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര്‍ ഓഫ് ചെയ്യുക ക്ലിക്ക് "
"ചെയ്തു സിസ്റ്റിന്റെ പവര്‍ "
"ഓഫ് ചെയ്യുക." "ഓഫ് ചെയ്യുക."
#: ../js/ui/endSessionDialog.js:86 #: ../js/ui/endSessionDialog.js:86
@@ -1122,7 +1152,8 @@ msgstr "പുനരാരംഭിക്കുക"
#: ../js/ui/endSessionDialog.js:101 #: ../js/ui/endSessionDialog.js:101
msgid "Click Restart to quit these applications and restart the system." msgid "Click Restart to quit these applications and restart the system."
msgstr "ഈ പ്രയോഗങ്ങള്‍ നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന്‍ പുനരാരംഭിക്കൂ അമര്‍ത്തുക" msgstr ""
"ഈ പ്രയോഗങ്ങള്‍ നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന്‍ പുനരാരംഭിക്കൂ അമര്‍ത്തുക"
#: ../js/ui/endSessionDialog.js:103 #: ../js/ui/endSessionDialog.js:103
#, c-format #, c-format
@@ -1142,7 +1173,9 @@ msgstr "ഇന്‍സ്റ്റോള്‍"
#: ../js/ui/extensionDownloader.js:204 #: ../js/ui/extensionDownloader.js:204
#, c-format #, c-format
msgid "Download and install '%s' from extensions.gnome.org?" 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/keyboard.js:619 ../js/ui/status/keyboard.js:314
#: ../js/ui/status/power.js:211 #: ../js/ui/status/power.js:211
@@ -1171,9 +1204,7 @@ msgstr "പിശകുകള്‍ കാണിക്കുക"
msgid "Enabled" msgid "Enabled"
msgstr "പ്രവര്‍ത്തനക്ഷമമാക്കി" msgstr "പ്രവര്‍ത്തനക്ഷമമാക്കി"
#. translators: #: ../js/ui/lookingGlass.js:769
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled" msgid "Disabled"
msgstr "പ്രവര്‍ത്തനരഹിതമാക്കി" msgstr "പ്രവര്‍ത്തനരഹിതമാക്കി"
@@ -1206,6 +1237,7 @@ msgid "Remove"
msgstr "നീക്കം ചെയ്യുക" msgstr "നീക്കം ചെയ്യുക"
#: ../js/ui/messageTray.js:1501 #: ../js/ui/messageTray.js:1501
#| msgid "No Messages"
msgid "Clear Messages" msgid "Clear Messages"
msgstr "സന്ദേശങ്ങള്‍ വെടിപ്പാക്കുക" msgstr "സന്ദേശങ്ങള്‍ വെടിപ്പാക്കുക"
@@ -1213,35 +1245,35 @@ msgstr "സന്ദേശങ്ങള്‍ വെടിപ്പാക്ക
msgid "Notification Settings" msgid "Notification Settings"
msgstr "അറിയിപ്പു് ക്രമീകരണങ്ങള്‍" msgstr "അറിയിപ്പു് ക്രമീകരണങ്ങള്‍"
#: ../js/ui/messageTray.js:1710 #: ../js/ui/messageTray.js:1709
msgid "No Messages" msgid "No Messages"
msgstr "സന്ദേശങ്ങളില്ല" msgstr "സന്ദേശങ്ങളില്ല"
#: ../js/ui/messageTray.js:1783 #: ../js/ui/messageTray.js:1782
msgid "Message Tray" msgid "Message Tray"
msgstr "സന്ദേശത്തിന്റെ ട്രേ" msgstr "സന്ദേശത്തിന്റെ ട്രേ"
#: ../js/ui/messageTray.js:2801 #: ../js/ui/messageTray.js:2810
msgid "System Information" msgid "System Information"
msgstr "സിസ്റ്റത്തെക്കുറിച്ചുള്ള വിവരം" msgstr "സിസ്റ്റത്തെക്കുറിച്ചുള്ള വിവരം"
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:378 #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374
msgctxt "program" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "അജ്ഞാതം" msgstr "അജ്ഞാതം"
#: ../js/ui/overviewControls.js:472 ../js/ui/screenShield.js:149 #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
#, c-format #, c-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
msgstr[0] "%d പുതിയ സന്ദേശം" msgstr[0] "%d പുതിയ സന്ദേശം"
msgstr[1] "%d പുതിയ സന്ദേശങ്ങള്‍" msgstr[1] "%d പുതിയ സന്ദേശങ്ങള്‍"
#: ../js/ui/overview.js:82 #: ../js/ui/overview.js:84
msgid "Undo" msgid "Undo"
msgstr "വേണ്ട" msgstr "വേണ്ട"
#: ../js/ui/overview.js:127 #: ../js/ui/overview.js:129
msgid "Overview" msgid "Overview"
msgstr "അവലോകനം" msgstr "അവലോകനം"
@@ -1249,21 +1281,22 @@ msgstr "അവലോകനം"
#. in the search entry when no search is #. in the search entry when no search is
#. active; it should not exceed ~30 #. active; it should not exceed ~30
#. characters. #. characters.
#: ../js/ui/overview.js:260 #: ../js/ui/overview.js:271
#| msgid "Type to search..."
msgid "Type to search…" msgid "Type to search…"
msgstr "തെരയുന്നതിനായി ടൈപ്പ് ചെയ്യുക..." msgstr "തെരയുന്നതിനായി ടൈപ്പ് ചെയ്യുക..."
#: ../js/ui/panel.js:641 #: ../js/ui/panel.js:612
msgid "Quit" msgid "Quit"
msgstr "നിര്‍ത്തുക" msgstr "നിര്‍ത്തുക"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:692 #: ../js/ui/panel.js:636
msgid "Activities" msgid "Activities"
msgstr "പ്രവര്‍ത്തനങ്ങള്‍" msgstr "പ്രവര്‍ത്തനങ്ങള്‍"
#: ../js/ui/panel.js:989 #: ../js/ui/panel.js:933
msgid "Top Bar" msgid "Top Bar"
msgstr "മുകളിലുള്ള ബാര്‍" msgstr "മുകളിലുള്ള ബാര്‍"
@@ -1272,15 +1305,15 @@ msgstr "മുകളിലുള്ള ബാര്‍"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:718 #: ../js/ui/popupMenu.js:727
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-us" msgstr "toggle-switch-us"
#: ../js/ui/runDialog.js:74 #: ../js/ui/runDialog.js:73
msgid "Enter a Command" msgid "Enter a Command"
msgstr "ഒരു കമാന്‍ഡ് നല്‍കുക" msgstr "ഒരു കമാന്‍ഡ് നല്‍കുക"
#: ../js/ui/runDialog.js:110 #: ../js/ui/runDialog.js:109
msgid "Close" msgid "Close"
msgstr "അടക്കുക" msgstr "അടക്കുക"
@@ -1301,7 +1334,7 @@ msgstr[1] "%d പുതിയ അറിയിപ്പുകള്‍"
msgid "Lock" msgid "Lock"
msgstr "പൂട്ടുക" msgstr "പൂട്ടുക"
#: ../js/ui/screenShield.js:641 #: ../js/ui/screenShield.js:637
msgid "GNOME needs to lock the screen" msgid "GNOME needs to lock the screen"
msgstr "ഗ്നോമിന് സ്ക്രീന്‍ പൂട്ടണം" msgstr "ഗ്നോമിന് സ്ക്രീന്‍ പൂട്ടണം"
@@ -1312,15 +1345,17 @@ msgstr "ഗ്നോമിന് സ്ക്രീന്‍ പൂട്ടണ
#. #.
#. XXX: another option is to kick the user into the gdm login #. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs #. 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" msgid "Unable to lock"
msgstr "പൂട്ടുവാന്‍ സാധ്യമല്ല" 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" msgid "Lock was blocked by an application"
msgstr "പൂട്ടുന്ന സംവിധാനം ഒരു പ്രയോഗം തടസ്സപ്പെടുത്തിയിരിയ്ക്കുന്നു" msgstr "പൂട്ടുന്ന സംവിധാനം ഒരു പ്രയോഗം തടസ്സപ്പെടുത്തിയിരിയ്ക്കുന്നു"
#: ../js/ui/searchDisplay.js:453 #: ../js/ui/searchDisplay.js:453
#| msgid "Searching..."
msgid "Searching…" msgid "Searching…"
msgstr "തെരയുന്നു..." msgstr "തെരയുന്നു..."
@@ -1336,11 +1371,11 @@ msgstr "പകര്‍ത്തുക"
msgid "Paste" msgid "Paste"
msgstr "ഒട്ടിയ്ക്കുക" msgstr "ഒട്ടിയ്ക്കുക"
#: ../js/ui/shellEntry.js:101 #: ../js/ui/shellEntry.js:106
msgid "Show Text" msgid "Show Text"
msgstr "പദാവലി കാണിക്കുക" msgstr "പദാവലി കാണിക്കുക"
#: ../js/ui/shellEntry.js:103 #: ../js/ui/shellEntry.js:108
msgid "Hide Text" msgid "Hide Text"
msgstr "പദാവലി മറക്കുക" msgstr "പദാവലി മറക്കുക"
@@ -1352,7 +1387,7 @@ msgstr "രഹസ്യവാക്ക്"
msgid "Remember Password" msgid "Remember Password"
msgstr "രഹസ്യവാക്ക് ഓര്‍ത്തു് വയ്ക്കുക" msgstr "രഹസ്യവാക്ക് ഓര്‍ത്തു് വയ്ക്കുക"
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:114 #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113
msgid "Unlock" msgid "Unlock"
msgstr "പൂട്ട് തുറക്കുക" msgstr "പൂട്ട് തുറക്കുക"
@@ -1416,10 +1451,12 @@ msgid "Visibility"
msgstr "കാഴ്ച" msgstr "കാഴ്ച"
#: ../js/ui/status/bluetooth.js:59 #: ../js/ui/status/bluetooth.js:59
#| msgid "Send Files to Device..."
msgid "Send Files to Device…" msgid "Send Files to Device…"
msgstr "ഡിവൈസിലേക്കു് ഫയലുകള്‍ അയയ്ക്കുക..." msgstr "ഡിവൈസിലേക്കു് ഫയലുകള്‍ അയയ്ക്കുക..."
#: ../js/ui/status/bluetooth.js:60 #: ../js/ui/status/bluetooth.js:60
#| msgid "Set Up a New Device..."
msgid "Set Up a New Device…" msgid "Set Up a New Device…"
msgstr "പുതിയൊരു ഡിവൈസ് സജ്ജമാക്കുക..." msgstr "പുതിയൊരു ഡിവൈസ് സജ്ജമാക്കുക..."
@@ -1446,6 +1483,7 @@ msgid "connecting..."
msgstr "ബന്ധിപ്പിയ്ക്കുന്നു...." msgstr "ബന്ധിപ്പിയ്ക്കുന്നു...."
#: ../js/ui/status/bluetooth.js:239 #: ../js/ui/status/bluetooth.js:239
#| msgid "Send Files..."
msgid "Send Files…" msgid "Send Files…"
msgstr "ഫയലുകള്‍ അയയ്ക്കുക..." msgstr "ഫയലുകള്‍ അയയ്ക്കുക..."
@@ -1658,6 +1696,7 @@ msgstr "ഊര്‍ജ്ജ ക്രമീകരണങ്ങള്‍"
#. 0 is reported when UPower does not have enough data #. 0 is reported when UPower does not have enough data
#. to estimate battery life #. to estimate battery life
#: ../js/ui/status/power.js:99 #: ../js/ui/status/power.js:99
#| msgid "Estimating..."
msgid "Estimating…" msgid "Estimating…"
msgstr "കണക്കുകൂട്ടുന്നു..." msgstr "കണക്കുകൂട്ടുന്നു..."
@@ -1757,11 +1796,11 @@ msgstr "ഒച്ച"
msgid "Microphone" msgid "Microphone"
msgstr "മൈക്രോഫോണ്‍" msgstr "മൈക്രോഫോണ്‍"
#: ../js/ui/unlockDialog.js:125 #: ../js/ui/unlockDialog.js:124
msgid "Log in as another user" msgid "Log in as another user"
msgstr "മറ്റൊരു ഉപയോക്താവായി പ്രവേശിയ്ക്കുക" msgstr "മറ്റൊരു ഉപയോക്താവായി പ്രവേശിയ്ക്കുക"
#: ../js/ui/unlockDialog.js:146 #: ../js/ui/unlockDialog.js:145
msgid "Unlock Window" msgid "Unlock Window"
msgstr "ജാലകത്തിന്റെ പൂട്ടു തുറക്കുക" msgstr "ജാലകത്തിന്റെ പൂട്ടു തുറക്കുക"
@@ -1814,8 +1853,10 @@ msgid ""
"Notifications are now disabled, including chat messages. Your online status " "Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages." "has been adjusted to let others know that you might not see their messages."
msgstr "" msgstr ""
"ചാറ്റ് സന്ദേശങ്ങള്‍ എന്ന പോലെ അറിയിപ്പുകള്‍ പ്രവര്‍ത്തന രഹിതമാക്കുന്നു. മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള്‍ " "ചാറ്റ് സന്ദേശങ്ങള്‍ എന്ന പോലെ അറിയിപ്പുകള്‍ പ്രവര്‍ത്തന രഹിതമാക്കുന്നു. "
"നിങ്ങള്‍ക്കു് കാണുവാന്‍ സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്‍ലൈന്‍ അവസ്ഥയില്‍ വ്യക്തമാക്കുന്നു." "മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള്‍ "
"നിങ്ങള്‍ക്കു് കാണുവാന്‍ സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്‍ലൈന്‍ അവസ്ഥയില്‍ "
"വ്യക്തമാക്കുന്നു."
#: ../js/ui/userMenu.js:888 #: ../js/ui/userMenu.js:888
msgid "Other users are logged in." msgid "Other users are logged in."
@@ -1868,28 +1909,6 @@ msgstr "'%s' തയ്യാറാണ്"
msgid "Evolution Calendar" msgid "Evolution Calendar"
msgstr "ഇവല്യൂഷന്‍ കലണ്ടര്‍" 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 #: ../src/main.c:347
msgid "Print version" msgid "Print version"
msgstr "പ്രിന്റ് ചെയ്യുവാന്‍ സാധിയ്ക്കുന്ന പതിപ്പു്" msgstr "പ്രിന്റ് ചെയ്യുവാന്‍ സാധിയ്ക്കുന്ന പതിപ്പു്"
@@ -1906,7 +1925,7 @@ msgstr "ഒരു പ്രത്യേക മോഡ് ഉപയോഗിയ്
msgid "List possible modes" msgid "List possible modes"
msgstr "സാധ്യമായ മോഡുകള്‍ ലഭ്യമാക്കുക" msgstr "സാധ്യമായ മോഡുകള്‍ ലഭ്യമാക്കുക"
#: ../src/shell-app.c:626 #: ../src/shell-app.c:622
#, c-format #, c-format
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "'%s' ലഭ്യമാക്കുന്നതില്‍ പരാജയം" msgstr "'%s' ലഭ്യമാക്കുന്നതില്‍ പരാജയം"
@@ -1936,6 +1955,19 @@ msgstr "ഉപയോക്താവു് ആധികാരികത ഉറപ
#~ msgid "More..." #~ msgid "More..."
#~ msgstr "കൂടുതല്‍..." #~ msgstr "കൂടുതല്‍..."
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "%u ഔട്ട്പുട്ട്"
#~ msgstr[1] "%u ഔട്ട്പുട്ടുകള്‍"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "%u ഇന്‍പുട്ട്"
#~ msgstr[1] "%u ഇന്‍പുട്ടുകള്‍"
#~ msgid "System Sounds"
#~ msgstr "സിസ്റ്റം ശബ്ദങ്ങള്‍"
#~ msgctxt "event list time" #~ msgctxt "event list time"
#~ msgid "%H:%M" #~ msgid "%H:%M"
#~ msgstr "%H:%M" #~ msgstr "%H:%M"

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell 3.8.x\n" "Project-Id-Version: gnome-shell 3.8.x\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: 2013-04-03 13:31+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n" "Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\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." msgid "Select an extension to configure using the combobox above."
msgstr "Velg en utvidelse som skal konfigureres med komboboksen over." msgstr "Velg en utvidelse som skal konfigureres med komboboksen over."
#: ../js/gdm/loginDialog.js:405 #: ../js/gdm/loginDialog.js:371
msgid "Session…" msgid "Session…"
msgstr "Økt …" msgstr "Økt …"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: ../js/gdm/loginDialog.js:630 #: ../js/gdm/loginDialog.js:601
msgid "Not listed?" msgid "Not listed?"
msgstr "Ikke listet?" msgstr "Ikke listet?"
#: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../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 #: ../js/ui/userMenu.js:938
msgid "Cancel" msgid "Cancel"
msgstr "Avbryt" msgstr "Avbryt"
#: ../js/gdm/loginDialog.js:802 #: ../js/gdm/loginDialog.js:791
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "Logg inn" msgstr "Logg inn"
#: ../js/gdm/loginDialog.js:802 #: ../js/gdm/loginDialog.js:791
msgid "Next" msgid "Next"
msgstr "Neste" 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 #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (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 #: ../js/ui/components/networkAgent.js:278
msgid "Username: " msgid "Username: "
msgstr "Brukernavn: " msgstr "Brukernavn: "
#: ../js/gdm/loginDialog.js:1173 #: ../js/gdm/loginDialog.js:1158
msgid "Login Window" msgid "Login Window"
msgstr "Innloggingsvindu" msgstr "Innloggingsvindu"
@@ -394,21 +401,16 @@ msgstr "Start på nytt"
msgid "Power Off" msgid "Power Off"
msgstr "Slå av" msgstr "Slå av"
#: ../js/gdm/util.js:249 #: ../js/gdm/util.js:247
msgid "Authentication error" msgid "Authentication error"
msgstr "Autentiseringsfeil" msgstr "Autentiseringsfeil"
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:366 #: ../js/gdm/util.js:364
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(eller dra 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 #: ../js/misc/util.js:97
msgid "Command not found" msgid "Command not found"
msgstr "Kommando ikke funnet" msgstr "Kommando ikke funnet"
@@ -632,11 +634,11 @@ msgstr "Åpne med %s"
msgid "Eject" msgid "Eject"
msgstr "Løs ut" 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:" msgid "Password:"
msgstr "Passord:" msgstr "Passord:"
#: ../js/ui/components/keyring.js:101 #: ../js/ui/components/keyring.js:107
msgid "Type again:" msgid "Type again:"
msgstr "Skriv på nytt:" msgstr "Skriv på nytt:"
@@ -724,7 +726,7 @@ msgstr "Autentisering kreves"
msgid "Administrator" msgid "Administrator"
msgstr "Administrator" msgstr "Administrator"
#: ../js/ui/components/polkitAgent.js:165 #: ../js/ui/components/polkitAgent.js:171
msgid "Authenticate" msgid "Authenticate"
msgstr "Autentiser" msgstr "Autentiser"
@@ -732,12 +734,12 @@ msgstr "Autentiser"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/components/polkitAgent.js: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." msgid "Sorry, that didn't work. Please try again."
msgstr "Beklager, det virket ikke. Vennligst prøv igjen." msgstr "Beklager, det virket ikke. Vennligst prøv igjen."
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/components/recorder.js:48 #: ../js/ui/components/recorder.js:47
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "Skjermvideo fra %d %t" msgstr "Skjermvideo fra %d %t"
@@ -1003,14 +1005,14 @@ msgstr "Åpne kalender"
msgid "Open Clocks" msgid "Open Clocks"
msgstr "Åpne Klokker" msgstr "Åpne Klokker"
#: ../js/ui/dateMenu.js:105 #: ../js/ui/dateMenu.js:104
msgid "Date & Time Settings" msgid "Date & Time Settings"
msgstr "Innstillinger for dato og klokkeslett" msgstr "Innstillinger for dato og klokkeslett"
#. Translators: This is the date format to use when the calendar popup is #. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). #. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. #.
#: ../js/ui/dateMenu.js:215 #: ../js/ui/dateMenu.js:216
msgid "%A %B %e, %Y" msgid "%A %B %e, %Y"
msgstr "%a %e %B, %Y" msgstr "%a %e %B, %Y"
@@ -1188,11 +1190,11 @@ msgstr "Innstillinger for varsling"
msgid "No Messages" msgid "No Messages"
msgstr "Ingen meldinger" msgstr "Ingen meldinger"
#: ../js/ui/messageTray.js:1782 #: ../js/ui/messageTray.js:1785
msgid "Message Tray" msgid "Message Tray"
msgstr "Meldingstrau" msgstr "Meldingstrau"
#: ../js/ui/messageTray.js:2810 #: ../js/ui/messageTray.js:2813
msgid "System Information" msgid "System Information"
msgstr "Systeminformasjon" msgstr "Systeminformasjon"
@@ -1224,17 +1226,17 @@ msgstr "Oversikt"
msgid "Type to search…" msgid "Type to search…"
msgstr "Skriv for å søke …" msgstr "Skriv for å søke …"
#: ../js/ui/panel.js:612 #: ../js/ui/panel.js:635
msgid "Quit" msgid "Quit"
msgstr "Avslutt" msgstr "Avslutt"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:636 #: ../js/ui/panel.js:686
msgid "Activities" msgid "Activities"
msgstr "Aktiviteter" msgstr "Aktiviteter"
#: ../js/ui/panel.js:933 #: ../js/ui/panel.js:982
msgid "Top Bar" msgid "Top Bar"
msgstr "Topp-panel" msgstr "Topp-panel"
@@ -1247,11 +1249,11 @@ msgstr "Topp-panel"
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:73 #: ../js/ui/runDialog.js:74
msgid "Enter a Command" msgid "Enter a Command"
msgstr "Oppgi en kommando" msgstr "Oppgi en kommando"
#: ../js/ui/runDialog.js:109 #: ../js/ui/runDialog.js:110
msgid "Close" msgid "Close"
msgstr "Lukk" msgstr "Lukk"
@@ -1272,7 +1274,7 @@ msgstr[1] "%d nye varslinger"
msgid "Lock" msgid "Lock"
msgstr "Lås" msgstr "Lås"
#: ../js/ui/screenShield.js:640 #: ../js/ui/screenShield.js:641
msgid "GNOME needs to lock the screen" msgid "GNOME needs to lock the screen"
msgstr "GNOME må låse skjermen" 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 #. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs #. 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" msgid "Unable to lock"
msgstr "Kan ikke låse" 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" msgid "Lock was blocked by an application"
msgstr "Låsing ble stoppet av et program" msgstr "Låsing ble stoppet av et program"
@@ -1307,11 +1309,11 @@ msgstr "Kopier"
msgid "Paste" msgid "Paste"
msgstr "Lim inn" msgstr "Lim inn"
#: ../js/ui/shellEntry.js:106 #: ../js/ui/shellEntry.js:101
msgid "Show Text" msgid "Show Text"
msgstr "Vis tekst" msgstr "Vis tekst"
#: ../js/ui/shellEntry.js:108 #: ../js/ui/shellEntry.js:103
msgid "Hide Text" msgid "Hide Text"
msgstr "Skjul tekst" msgstr "Skjul tekst"
@@ -1323,7 +1325,7 @@ msgstr "Passord"
msgid "Remember Password" msgid "Remember Password"
msgstr "Husk passord" 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" msgid "Unlock"
msgstr "Lås opp" msgstr "Lås opp"
@@ -1614,7 +1616,7 @@ msgstr "Tilkobling feilet"
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "Aktivering av nettverkstilkobling feilet" msgstr "Aktivering av nettverkstilkobling feilet"
#: ../js/ui/status/network.js:2276 #: ../js/ui/status/network.js:2282
msgid "Networking is disabled" msgid "Networking is disabled"
msgstr "Nettverk er slått av" msgstr "Nettverk er slått av"
@@ -1728,11 +1730,11 @@ msgstr "Volum"
msgid "Microphone" msgid "Microphone"
msgstr "Mikrofon" msgstr "Mikrofon"
#: ../js/ui/unlockDialog.js:124 #: ../js/ui/unlockDialog.js:120
msgid "Log in as another user" msgid "Log in as another user"
msgstr "Logg inn som en annen bruker" msgstr "Logg inn som en annen bruker"
#: ../js/ui/unlockDialog.js:145 #: ../js/ui/unlockDialog.js:141
msgid "Unlock Window" msgid "Unlock Window"
msgstr "Lås opp vindu" msgstr "Lås opp vindu"
@@ -1885,11 +1887,11 @@ msgstr "Vis mulige modi"
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "Klarte ikke å starte «%s»" msgstr "Klarte ikke å starte «%s»"
#: ../src/shell-keyring-prompt.c:708 #: ../src/shell-keyring-prompt.c:714
msgid "Passwords do not match." msgid "Passwords do not match."
msgstr "Passordene er ikke like." msgstr "Passordene er ikke like."
#: ../src/shell-keyring-prompt.c:716 #: ../src/shell-keyring-prompt.c:722
msgid "Password cannot be blank" msgid "Password cannot be blank"
msgstr "Passordet kan ikke være tomt" msgstr "Passordet kan ikke være tomt"

2487
po/oc.po Normal file

File diff suppressed because it is too large Load Diff

603
po/pa.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

532
po/ru.po

File diff suppressed because it is too large Load Diff

528
po/sl.po

File diff suppressed because it is too large Load Diff

522
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

958
po/ta.po

File diff suppressed because it is too large Load Diff

566
po/tr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -9,15 +9,16 @@ msgstr ""
"Project-Id-Version: gnome-shell 3.3.90\n" "Project-Id-Version: gnome-shell 3.3.90\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-04 08:38+0000\n" "POT-Creation-Date: 2013-05-31 18:55+0000\n"
"PO-Revision-Date: 2013-03-06 19:06+0800\n" "PO-Revision-Date: 2013-06-04 21:50+0800\n"
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n" "Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n"
"Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n" "Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\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 #: ../data/50-gnome-shell-screenshot.xml.in.h:1
msgid "Screenshots" msgid "Screenshots"
@@ -313,44 +314,50 @@ msgstr "擴充功能"
msgid "Select an extension to configure using the combobox above." msgid "Select an extension to configure using the combobox above."
msgstr "使用上面的組合方塊選擇要設定的擴充功能。" msgstr "使用上面的組合方塊選擇要設定的擴充功能。"
#: ../js/gdm/loginDialog.js:405 #: ../js/gdm/loginDialog.js:371
#| msgid "Session..."
msgid "Session…" msgid "Session…"
msgstr "作業階段…" msgstr "作業階段…"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: ../js/gdm/loginDialog.js:629 #: ../js/gdm/loginDialog.js:601
msgid "Not listed?" msgid "Not listed?"
msgstr "沒有列出來?" msgstr "沒有列出來?"
#: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
#: ../js/ui/userMenu.js:934 #: ../js/ui/userMenu.js:938
msgid "Cancel" msgid "Cancel"
msgstr "取消" msgstr "取消"
#: ../js/gdm/loginDialog.js:799 #: ../js/gdm/loginDialog.js:791
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "登入" msgstr "登入"
#: ../js/gdm/loginDialog.js:799 #: ../js/gdm/loginDialog.js:791
msgid "Next" msgid "Next"
msgstr "下一個" 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 #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (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 #: ../js/ui/components/networkAgent.js:278
msgid "Username: " msgid "Username: "
msgstr "使用者名稱:" msgstr "使用者名稱:"
#: ../js/gdm/loginDialog.js:1157 #: ../js/gdm/loginDialog.js:1158
msgid "Login Window" msgid "Login Window"
msgstr "登入視窗" msgstr "登入視窗"
@@ -359,8 +366,8 @@ msgstr "登入視窗"
msgid "Power" msgid "Power"
msgstr "電源" msgstr "電源"
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699 #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700
#: ../js/ui/userMenu.js:815 #: ../js/ui/userMenu.js:816
msgid "Suspend" msgid "Suspend"
msgstr "暫停" msgstr "暫停"
@@ -368,58 +375,53 @@ msgstr "暫停"
msgid "Restart" msgid "Restart"
msgstr "重新啟動" msgstr "重新啟動"
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:697 #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698
#: ../js/ui/userMenu.js:699 ../js/ui/userMenu.js:814 ../js/ui/userMenu.js:938 #: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942
msgid "Power Off" msgid "Power Off"
msgstr "關閉電源" msgstr "關閉電源"
#: ../js/gdm/util.js:182 #: ../js/gdm/util.js:247
msgid "Authentication error" msgid "Authentication error"
msgstr "驗證錯誤" msgstr "驗證錯誤"
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:299 #: ../js/gdm/util.js:364
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(或是滑過手指)" msgstr "(或是滑過手指)"
#: ../js/gdm/util.js:324 #: ../js/misc/util.js:97
#, c-format
msgid "(e.g., user or %s)"
msgstr "(例如: user 或 %s)"
#: ../js/misc/util.js:94
msgid "Command not found" msgid "Command not found"
msgstr "找不到指令" msgstr "找不到指令"
#. Replace "Error invoking GLib.shell_parse_argv: " with #. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer #. something nicer
#: ../js/misc/util.js:127 #: ../js/misc/util.js:130
msgid "Could not parse command:" msgid "Could not parse command:"
msgstr "無法分析指令:" msgstr "無法分析指令:"
#: ../js/misc/util.js:135 #: ../js/misc/util.js:138
#, c-format #, c-format
msgid "Execution of '%s' failed:" msgid "Execution of '%s' failed:"
msgstr "執行「%s」失敗" msgstr "執行「%s」失敗"
#: ../js/ui/appDisplay.js:348 #: ../js/ui/appDisplay.js:356
msgid "Frequent" msgid "Frequent"
msgstr "頻率" msgstr "常用"
#: ../js/ui/appDisplay.js:355 #: ../js/ui/appDisplay.js:363
msgid "All" msgid "All"
msgstr "全部" msgstr "全部"
#: ../js/ui/appDisplay.js:913 #: ../js/ui/appDisplay.js:941
msgid "New Window" msgid "New Window"
msgstr "新視窗" 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" msgid "Remove from Favorites"
msgstr "自喜好中移除" msgstr "自喜好中移除"
#: ../js/ui/appDisplay.js:917 #: ../js/ui/appDisplay.js:945
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "加入喜好" msgstr "加入喜好"
@@ -433,7 +435,7 @@ msgstr "%s 已加入你的喜好中。"
msgid "%s has been removed from your favorites." msgid "%s has been removed from your favorites."
msgstr "%s 已經從你的喜好中移除。" msgstr "%s 已經從你的喜好中移除。"
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788 #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789
msgid "Settings" msgid "Settings"
msgstr "設定值" msgstr "設定值"
@@ -456,7 +458,7 @@ msgctxt "event list time"
msgid "%H\\u2236%M" msgid "%H\\u2236%M"
msgstr "%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 #. \u2236 is a ratio character, similar to : and \u2009 is
#. a thin space #. a thin space
#: ../js/ui/calendar.js:77 #: ../js/ui/calendar.js:77
@@ -558,35 +560,35 @@ msgid "S"
msgstr "六" msgstr "六"
#. Translators: Text to show if there are no events #. Translators: Text to show if there are no events
#: ../js/ui/calendar.js:692 #: ../js/ui/calendar.js:720
msgid "Nothing Scheduled" msgid "Nothing Scheduled"
msgstr "沒有預訂行程" msgstr "沒有預訂行程"
#. Translators: Shown on calendar heading when selected day occurs on current year #. 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" msgctxt "calendar heading"
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%m月%d日%A" msgstr "%m月%d日%A"
#. Translators: Shown on calendar heading when selected day occurs on different year #. 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" msgctxt "calendar heading"
msgid "%A, %B %d, %Y" msgid "%A, %B %d, %Y"
msgstr "%Y年%m月%d日%A" msgstr "%Y年%m月%d日%A"
#: ../js/ui/calendar.js:721 #: ../js/ui/calendar.js:749
msgid "Today" msgid "Today"
msgstr "今天" msgstr "今天"
#: ../js/ui/calendar.js:725 #: ../js/ui/calendar.js:753
msgid "Tomorrow" msgid "Tomorrow"
msgstr "明天" msgstr "明天"
#: ../js/ui/calendar.js:736 #: ../js/ui/calendar.js:764
msgid "This week" msgid "This week"
msgstr "本週" msgstr "本週"
#: ../js/ui/calendar.js:744 #: ../js/ui/calendar.js:772
msgid "Next week" msgid "Next week"
msgstr "下週" msgstr "下週"
@@ -602,20 +604,20 @@ msgstr "外部裝置已拔除"
msgid "Removable Devices" msgid "Removable Devices"
msgstr "可移除式裝置" msgstr "可移除式裝置"
#: ../js/ui/components/autorunManager.js:593 #: ../js/ui/components/autorunManager.js:594
#, c-format #, c-format
msgid "Open with %s" msgid "Open with %s"
msgstr "用 %s 開啟" msgstr "用 %s 開啟"
#: ../js/ui/components/autorunManager.js:619 #: ../js/ui/components/autorunManager.js:620
msgid "Eject" msgid "Eject"
msgstr "退出" 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:" msgid "Password:"
msgstr "密碼: " msgstr "密碼: "
#: ../js/ui/components/keyring.js:101 #: ../js/ui/components/keyring.js:107
msgid "Type again:" msgid "Type again:"
msgstr "再輸入一次:" msgstr "再輸入一次:"
@@ -693,15 +695,15 @@ msgstr "流動寬頻網絡密碼"
msgid "A password is required to connect to '%s'." msgid "A password is required to connect to '%s'."
msgstr "連線至「%s」需要密碼。" msgstr "連線至「%s」需要密碼。"
#: ../js/ui/components/polkitAgent.js:55 #: ../js/ui/components/polkitAgent.js:54
msgid "Authentication Required" msgid "Authentication Required"
msgstr "要求驗證" msgstr "要求驗證"
#: ../js/ui/components/polkitAgent.js:93 #: ../js/ui/components/polkitAgent.js:92
msgid "Administrator" msgid "Administrator"
msgstr "系統管理員" msgstr "系統管理員"
#: ../js/ui/components/polkitAgent.js:165 #: ../js/ui/components/polkitAgent.js:170
msgid "Authenticate" msgid "Authenticate"
msgstr "驗證" msgstr "驗證"
@@ -709,12 +711,12 @@ msgstr "驗證"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/components/polkitAgent.js: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." msgid "Sorry, that didn't work. Please try again."
msgstr "抱歉,那樣無法運作。請再試一次。" msgstr "抱歉,那樣無法運作。請再試一次。"
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/components/recorder.js:48 #: ../js/ui/components/recorder.js:47
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "Screencast from %d %t" msgstr "Screencast from %d %t"
@@ -976,14 +978,14 @@ msgstr "開啟行事曆"
msgid "Open Clocks" msgid "Open Clocks"
msgstr "開啟時鐘" msgstr "開啟時鐘"
#: ../js/ui/dateMenu.js:105 #: ../js/ui/dateMenu.js:104
msgid "Date & Time Settings" msgid "Date & Time Settings"
msgstr "日期與時刻設定值" msgstr "日期與時刻設定值"
#. Translators: This is the date format to use when the calendar popup is #. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). #. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. #.
#: ../js/ui/dateMenu.js:205 #: ../js/ui/dateMenu.js:216
msgid "%A %B %e, %Y" msgid "%A %B %e, %Y"
msgstr "%Y年%m月%e日%A" msgstr "%Y年%m月%e日%A"
@@ -1080,7 +1082,7 @@ msgstr "安裝"
msgid "Download and install '%s' from extensions.gnome.org?" 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/keyboard.js:619 ../js/ui/status/keyboard.js:333
#: ../js/ui/status/power.js:211 #: ../js/ui/status/power.js:211
msgid "Keyboard" msgid "Keyboard"
msgstr "鍵盤" msgstr "鍵盤"
@@ -1142,7 +1144,6 @@ msgid "Remove"
msgstr "移除" msgstr "移除"
#: ../js/ui/messageTray.js:1501 #: ../js/ui/messageTray.js:1501
#| msgid "No Messages"
msgid "Clear Messages" msgid "Clear Messages"
msgstr "清除訊息" msgstr "清除訊息"
@@ -1150,15 +1151,15 @@ msgstr "清除訊息"
msgid "Notification Settings" msgid "Notification Settings"
msgstr "通知設定值" msgstr "通知設定值"
#: ../js/ui/messageTray.js:1707 #: ../js/ui/messageTray.js:1709
msgid "No Messages" msgid "No Messages"
msgstr "沒有訊息" msgstr "沒有訊息"
#: ../js/ui/messageTray.js:1787 #: ../js/ui/messageTray.js:1785
msgid "Message Tray" msgid "Message Tray"
msgstr "訊息匣" msgstr "訊息匣"
#: ../js/ui/messageTray.js:2864 #: ../js/ui/messageTray.js:2818
msgid "System Information" msgid "System Information"
msgstr "系統資訊" msgstr "系統資訊"
@@ -1167,13 +1168,13 @@ msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "不明" msgstr "不明"
#: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
#, c-format #, c-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
msgstr[0] "%d 個新訊息" msgstr[0] "%d 個新訊息"
#: ../js/ui/overview.js:82 #: ../js/ui/overview.js:84
msgid "Undo" msgid "Undo"
msgstr "復原" msgstr "復原"
@@ -1185,22 +1186,21 @@ msgstr "概覽"
#. in the search entry when no search is #. in the search entry when no search is
#. active; it should not exceed ~30 #. active; it should not exceed ~30
#. characters. #. characters.
#: ../js/ui/overview.js:284 #: ../js/ui/overview.js:271
#| msgid "Type to search..."
msgid "Type to search…" msgid "Type to search…"
msgstr "輸入以搜尋…" msgstr "輸入以搜尋…"
#: ../js/ui/panel.js:613 #: ../js/ui/panel.js:635
msgid "Quit" msgid "Quit"
msgstr "結束" msgstr "結束"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:642 #: ../js/ui/panel.js:686
msgid "Activities" msgid "Activities"
msgstr "概覽 " msgstr "概覽 "
#: ../js/ui/panel.js:983 #: ../js/ui/panel.js:982
msgid "Top Bar" msgid "Top Bar"
msgstr "頂端列" msgstr "頂端列"
@@ -1209,35 +1209,35 @@ msgstr "頂端列"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:727 #: ../js/ui/popupMenu.js:740
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-us" msgstr "toggle-switch-us"
#: ../js/ui/runDialog.js:205 #: ../js/ui/runDialog.js:74
msgid "Enter a Command" msgid "Enter a Command"
msgstr "請輸入指令" msgstr "請輸入指令"
#: ../js/ui/runDialog.js:241 #: ../js/ui/runDialog.js:110
msgid "Close" msgid "Close"
msgstr "關閉" msgstr "關閉"
#. Translators: This is a time format for a date in #. Translators: This is a time format for a date in
#. long format #. long format
#: ../js/ui/screenShield.js:90 #: ../js/ui/screenShield.js:86
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%m月%d日%A" msgstr "%m月%d日%A"
#: ../js/ui/screenShield.js:155 #: ../js/ui/screenShield.js:151
#, c-format #, c-format
msgid "%d new notification" msgid "%d new notification"
msgid_plural "%d new notifications" msgid_plural "%d new notifications"
msgstr[0] "%d 個新通知" 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" msgid "Lock"
msgstr "鎖定" msgstr "鎖定"
#: ../js/ui/screenShield.js:639 #: ../js/ui/screenShield.js:641
msgid "GNOME needs to lock the screen" msgid "GNOME needs to lock the screen"
msgstr "GNOME 需要鎖定螢幕" msgstr "GNOME 需要鎖定螢幕"
@@ -1248,37 +1248,35 @@ msgstr "GNOME 需要鎖定螢幕"
#. #.
#. XXX: another option is to kick the user into the gdm login #. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs #. screen, where we're not affected by grabs
#: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
#| msgid "Unable to connect to %s"
msgid "Unable to lock" msgid "Unable to lock"
msgstr "無法鎖定" 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" msgid "Lock was blocked by an application"
msgstr "鎖定被應用程式阻擋" msgstr "鎖定被應用程式阻擋"
#: ../js/ui/searchDisplay.js:431 #: ../js/ui/searchDisplay.js:453
#| msgid "Searching..."
msgid "Searching…" msgid "Searching…"
msgstr "搜尋…" msgstr "搜尋…"
#: ../js/ui/searchDisplay.js:475 #: ../js/ui/searchDisplay.js:497
msgid "No results." msgid "No results."
msgstr "沒有結果。" msgstr "沒有結果。"
#: ../js/ui/shellEntry.js:29 #: ../js/ui/shellEntry.js:27
msgid "Copy" msgid "Copy"
msgstr "複製" msgstr "複製"
#: ../js/ui/shellEntry.js:34 #: ../js/ui/shellEntry.js:32
msgid "Paste" msgid "Paste"
msgstr "貼上" msgstr "貼上"
#: ../js/ui/shellEntry.js:105 #: ../js/ui/shellEntry.js:99
msgid "Show Text" msgid "Show Text"
msgstr "顯示文字" msgstr "顯示文字"
#: ../js/ui/shellEntry.js:107 #: ../js/ui/shellEntry.js:101
msgid "Hide Text" msgid "Hide Text"
msgstr "隱藏文字" msgstr "隱藏文字"
@@ -1290,7 +1288,7 @@ msgstr "密碼"
msgid "Remember Password" msgid "Remember Password"
msgstr "記住密碼" msgstr "記住密碼"
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
msgid "Unlock" msgid "Unlock"
msgstr "解鎖" msgstr "解鎖"
@@ -1354,12 +1352,10 @@ msgid "Visibility"
msgstr "顯示狀態" msgstr "顯示狀態"
#: ../js/ui/status/bluetooth.js:59 #: ../js/ui/status/bluetooth.js:59
#| msgid "Send Files to Device..."
msgid "Send Files to Device…" msgid "Send Files to Device…"
msgstr "傳送檔案到裝置…" msgstr "傳送檔案到裝置…"
#: ../js/ui/status/bluetooth.js:60 #: ../js/ui/status/bluetooth.js:60
#| msgid "Set Up a New Device..."
msgid "Set Up a New Device…" msgid "Set Up a New Device…"
msgstr "設定新的裝置…" msgstr "設定新的裝置…"
@@ -1386,7 +1382,6 @@ msgid "connecting..."
msgstr "連線中…" msgstr "連線中…"
#: ../js/ui/status/bluetooth.js:239 #: ../js/ui/status/bluetooth.js:239
#| msgid "Send Files..."
msgid "Send Files…" msgid "Send Files…"
msgstr "傳送檔案…" msgstr "傳送檔案…"
@@ -1462,11 +1457,11 @@ msgstr "請輸入裝置所提及的 PIN。"
msgid "OK" msgid "OK"
msgstr "確定" msgstr "確定"
#: ../js/ui/status/keyboard.js:368 #: ../js/ui/status/keyboard.js:396
msgid "Show Keyboard Layout" msgid "Show Keyboard Layout"
msgstr "顯示鍵盤配置" msgstr "顯示鍵盤配置"
#: ../js/ui/status/keyboard.js:373 #: ../js/ui/status/keyboard.js:401
msgid "Region & Language Settings" msgid "Region & Language Settings"
msgstr "地區和語言設定值" msgstr "地區和語言設定值"
@@ -1584,7 +1579,7 @@ msgstr "連線失敗"
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "啟動網絡連線失敗" msgstr "啟動網絡連線失敗"
#: ../js/ui/status/network.js:2276 #: ../js/ui/status/network.js:2282
msgid "Networking is disabled" msgid "Networking is disabled"
msgstr "網絡已停用" msgstr "網絡已停用"
@@ -1599,7 +1594,6 @@ msgstr "電源設定值"
#. 0 is reported when UPower does not have enough data #. 0 is reported when UPower does not have enough data
#. to estimate battery life #. to estimate battery life
#: ../js/ui/status/power.js:99 #: ../js/ui/status/power.js:99
#| msgid "Estimating..."
msgid "Estimating…" msgid "Estimating…"
msgstr "評估中…" msgstr "評估中…"
@@ -1695,11 +1689,11 @@ msgstr "音量"
msgid "Microphone" msgid "Microphone"
msgstr "麥克風" msgstr "麥克風"
#: ../js/ui/unlockDialog.js:151 #: ../js/ui/unlockDialog.js:120
msgid "Log in as another user" msgid "Log in as another user"
msgstr "以另一個使用者身分登入" msgstr "以另一個使用者身分登入"
#: ../js/ui/unlockDialog.js:177 #: ../js/ui/unlockDialog.js:141
msgid "Unlock Window" msgid "Unlock Window"
msgstr "解鎖視窗" msgstr "解鎖視窗"
@@ -1727,46 +1721,48 @@ msgstr "閒置"
msgid "Offline" msgid "Offline"
msgstr "離線" msgstr "離線"
#: ../js/ui/userMenu.js:780 #: ../js/ui/userMenu.js:781
msgid "Notifications" msgid "Notifications"
msgstr "通知" msgstr "通知"
#: ../js/ui/userMenu.js:796 #: ../js/ui/userMenu.js:797
msgid "Switch User" msgid "Switch User"
msgstr "切換使用者" msgstr "切換使用者"
#: ../js/ui/userMenu.js:801 #: ../js/ui/userMenu.js:802
msgid "Log Out" msgid "Log Out"
msgstr "登出" msgstr "登出"
#: ../js/ui/userMenu.js:821 #: ../js/ui/userMenu.js:822
msgid "Install Updates & Restart" msgid "Install Updates & Restart"
msgstr "安裝更新 & 重新啟動" msgstr "安裝更新 & 重新啟動"
#: ../js/ui/userMenu.js:839 #: ../js/ui/userMenu.js:840
msgid "Your chat status will be set to busy" msgid "Your chat status will be set to busy"
msgstr "你的聊天狀態會設為忙碌" msgstr "你的聊天狀態會設為忙碌"
#: ../js/ui/userMenu.js:840 #: ../js/ui/userMenu.js:841
msgid "" msgid ""
"Notifications are now disabled, including chat messages. Your online status " "Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages." "has been adjusted to let others know that you might not see their messages."
msgstr "通知現在已被停用,包含聊天訊息。你的上線狀態也調整為讓其他人知道你沒時間看他們的訊息。" msgstr "通知現在已被停用,包含聊天訊息。你的上線狀態也調整為讓其他人知道你沒時間看他們的訊息。"
#: ../js/ui/userMenu.js:886 #: ../js/ui/userMenu.js:888
msgid "Other users are logged in." msgid "Other users are logged in."
msgstr "其他使用者已登入。" msgstr "其他使用者已登入。"
#: ../js/ui/userMenu.js:891 #: ../js/ui/userMenu.js:893
msgid "Shutting down might cause them to lose unsaved work." msgid "Shutting down might cause them to lose unsaved work."
msgstr "關機可能使它們失去未儲存的工作。" 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 #, c-format
msgid "%s (remote)" msgid "%s (remote)"
msgstr "%s (遠端)" 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 #, c-format
msgid "%s (console)" msgid "%s (console)"
msgstr "%s (主控臺)" msgstr "%s (主控臺)"
@@ -1779,7 +1775,7 @@ msgstr "應用程式"
msgid "Search" msgid "Search"
msgstr "搜尋" msgstr "搜尋"
#: ../js/ui/wanda.js:92 #: ../js/ui/wanda.js:77
#, c-format #, c-format
msgid "" msgid ""
"Sorry, no wisdom for you today:\n" "Sorry, no wisdom for you today:\n"
@@ -1788,7 +1784,7 @@ msgstr ""
"抱歉,今天可能有些問題:\n" "抱歉,今天可能有些問題:\n"
"%s" "%s"
#: ../js/ui/wanda.js:96 #: ../js/ui/wanda.js:81
#, c-format #, c-format
msgid "%s the Oracle says" msgid "%s the Oracle says"
msgstr "%s Oracle 說:" msgstr "%s Oracle 說:"
@@ -1818,7 +1814,7 @@ msgid "%u Input"
msgid_plural "%u Inputs" msgid_plural "%u Inputs"
msgstr[0] "%u 輸入" msgstr[0] "%u 輸入"
#: ../src/gvc/gvc-mixer-control.c:2371 #: ../src/gvc/gvc-mixer-control.c:2373
msgid "System Sounds" msgid "System Sounds"
msgstr "系統音效" msgstr "系統音效"
@@ -1843,11 +1839,11 @@ msgstr "列出可能的模式"
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "無法啟動「%s」" msgstr "無法啟動「%s」"
#: ../src/shell-keyring-prompt.c:708 #: ../src/shell-keyring-prompt.c:714
msgid "Passwords do not match." msgid "Passwords do not match."
msgstr "密碼不相符。" msgstr "密碼不相符。"
#: ../src/shell-keyring-prompt.c:716 #: ../src/shell-keyring-prompt.c:722
msgid "Password cannot be blank" msgid "Password cannot be blank"
msgstr "密碼不能為空白" msgstr "密碼不能為空白"

View File

@@ -9,15 +9,16 @@ msgstr ""
"Project-Id-Version: gnome-shell 3.3.90\n" "Project-Id-Version: gnome-shell 3.3.90\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-04 08:38+0000\n" "POT-Creation-Date: 2013-05-31 18:55+0000\n"
"PO-Revision-Date: 2013-03-05 19:49+0800\n" "PO-Revision-Date: 2013-04-27 00:04+0800\n"
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n" "Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n"
"Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n" "Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\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 #: ../data/50-gnome-shell-screenshot.xml.in.h:1
msgid "Screenshots" msgid "Screenshots"
@@ -343,44 +344,50 @@ msgstr "擴充功能"
msgid "Select an extension to configure using the combobox above." msgid "Select an extension to configure using the combobox above."
msgstr "使用上面的組合方塊選擇要設定的擴充功能。" msgstr "使用上面的組合方塊選擇要設定的擴充功能。"
#: ../js/gdm/loginDialog.js:405 #: ../js/gdm/loginDialog.js:371
#| msgid "Session..."
msgid "Session…" msgid "Session…"
msgstr "作業階段…" msgstr "作業階段…"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: ../js/gdm/loginDialog.js:629 #: ../js/gdm/loginDialog.js:601
msgid "Not listed?" msgid "Not listed?"
msgstr "沒有列出來?" msgstr "沒有列出來?"
#: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
#: ../js/ui/userMenu.js:934 #: ../js/ui/userMenu.js:938
msgid "Cancel" msgid "Cancel"
msgstr "取消" msgstr "取消"
#: ../js/gdm/loginDialog.js:799 #: ../js/gdm/loginDialog.js:791
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "登入" msgstr "登入"
#: ../js/gdm/loginDialog.js:799 #: ../js/gdm/loginDialog.js:791
msgid "Next" msgid "Next"
msgstr "下一個" 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 #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (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 #: ../js/ui/components/networkAgent.js:278
msgid "Username: " msgid "Username: "
msgstr "使用者名稱:" msgstr "使用者名稱:"
#: ../js/gdm/loginDialog.js:1157 #: ../js/gdm/loginDialog.js:1158
msgid "Login Window" msgid "Login Window"
msgstr "登入視窗" msgstr "登入視窗"
@@ -389,8 +396,8 @@ msgstr "登入視窗"
msgid "Power" msgid "Power"
msgstr "電源" msgstr "電源"
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699 #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700
#: ../js/ui/userMenu.js:815 #: ../js/ui/userMenu.js:816
msgid "Suspend" msgid "Suspend"
msgstr "暫停" msgstr "暫停"
@@ -398,58 +405,53 @@ msgstr "暫停"
msgid "Restart" msgid "Restart"
msgstr "重新啟動" msgstr "重新啟動"
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:697 #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698
#: ../js/ui/userMenu.js:699 ../js/ui/userMenu.js:814 ../js/ui/userMenu.js:938 #: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942
msgid "Power Off" msgid "Power Off"
msgstr "關閉電源" msgstr "關閉電源"
#: ../js/gdm/util.js:182 #: ../js/gdm/util.js:247
msgid "Authentication error" msgid "Authentication error"
msgstr "驗證錯誤" msgstr "驗證錯誤"
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:299 #: ../js/gdm/util.js:364
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(或是滑過手指)" msgstr "(或是滑過手指)"
#: ../js/gdm/util.js:324 #: ../js/misc/util.js:97
#, c-format
msgid "(e.g., user or %s)"
msgstr "(例如: user 或 %s)"
#: ../js/misc/util.js:94
msgid "Command not found" msgid "Command not found"
msgstr "找不到指令" msgstr "找不到指令"
#. Replace "Error invoking GLib.shell_parse_argv: " with #. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer #. something nicer
#: ../js/misc/util.js:127 #: ../js/misc/util.js:130
msgid "Could not parse command:" msgid "Could not parse command:"
msgstr "無法分析指令:" msgstr "無法分析指令:"
#: ../js/misc/util.js:135 #: ../js/misc/util.js:138
#, c-format #, c-format
msgid "Execution of '%s' failed:" msgid "Execution of '%s' failed:"
msgstr "執行「%s」失敗" msgstr "執行「%s」失敗"
#: ../js/ui/appDisplay.js:348 #: ../js/ui/appDisplay.js:356
msgid "Frequent" msgid "Frequent"
msgstr "頻率" msgstr "常用"
#: ../js/ui/appDisplay.js:355 #: ../js/ui/appDisplay.js:363
msgid "All" msgid "All"
msgstr "全部" msgstr "全部"
#: ../js/ui/appDisplay.js:913 #: ../js/ui/appDisplay.js:941
msgid "New Window" msgid "New Window"
msgstr "新視窗" 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" msgid "Remove from Favorites"
msgstr "自喜好中移除" msgstr "自喜好中移除"
#: ../js/ui/appDisplay.js:917 #: ../js/ui/appDisplay.js:945
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "加入喜好" msgstr "加入喜好"
@@ -463,7 +465,7 @@ msgstr "%s 已加入您的喜好中。"
msgid "%s has been removed from your favorites." msgid "%s has been removed from your favorites."
msgstr "%s 已經從您的喜好中移除。" msgstr "%s 已經從您的喜好中移除。"
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788 #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789
msgid "Settings" msgid "Settings"
msgstr "設定值" msgstr "設定值"
@@ -486,7 +488,7 @@ msgctxt "event list time"
msgid "%H\\u2236%M" msgid "%H\\u2236%M"
msgstr "%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 #. \u2236 is a ratio character, similar to : and \u2009 is
#. a thin space #. a thin space
#: ../js/ui/calendar.js:77 #: ../js/ui/calendar.js:77
@@ -588,35 +590,35 @@ msgid "S"
msgstr "六" msgstr "六"
#. Translators: Text to show if there are no events #. Translators: Text to show if there are no events
#: ../js/ui/calendar.js:692 #: ../js/ui/calendar.js:720
msgid "Nothing Scheduled" msgid "Nothing Scheduled"
msgstr "沒有預訂行程" msgstr "沒有預訂行程"
#. Translators: Shown on calendar heading when selected day occurs on current year #. 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" msgctxt "calendar heading"
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%m月%d日%A" msgstr "%m月%d日%A"
#. Translators: Shown on calendar heading when selected day occurs on different year #. 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" msgctxt "calendar heading"
msgid "%A, %B %d, %Y" msgid "%A, %B %d, %Y"
msgstr "%Y年%m月%d日%A" msgstr "%Y年%m月%d日%A"
#: ../js/ui/calendar.js:721 #: ../js/ui/calendar.js:749
msgid "Today" msgid "Today"
msgstr "今天" msgstr "今天"
#: ../js/ui/calendar.js:725 #: ../js/ui/calendar.js:753
msgid "Tomorrow" msgid "Tomorrow"
msgstr "明天" msgstr "明天"
#: ../js/ui/calendar.js:736 #: ../js/ui/calendar.js:764
msgid "This week" msgid "This week"
msgstr "本週" msgstr "本週"
#: ../js/ui/calendar.js:744 #: ../js/ui/calendar.js:772
msgid "Next week" msgid "Next week"
msgstr "下週" msgstr "下週"
@@ -632,20 +634,20 @@ msgstr "外部裝置已拔除"
msgid "Removable Devices" msgid "Removable Devices"
msgstr "可移除式裝置" msgstr "可移除式裝置"
#: ../js/ui/components/autorunManager.js:593 #: ../js/ui/components/autorunManager.js:594
#, c-format #, c-format
msgid "Open with %s" msgid "Open with %s"
msgstr "用 %s 開啟" msgstr "用 %s 開啟"
#: ../js/ui/components/autorunManager.js:619 #: ../js/ui/components/autorunManager.js:620
msgid "Eject" msgid "Eject"
msgstr "退出" 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:" msgid "Password:"
msgstr "密碼: " msgstr "密碼: "
#: ../js/ui/components/keyring.js:101 #: ../js/ui/components/keyring.js:107
msgid "Type again:" msgid "Type again:"
msgstr "再輸入一次:" msgstr "再輸入一次:"
@@ -723,15 +725,15 @@ msgstr "行動寬頻網路密碼"
msgid "A password is required to connect to '%s'." msgid "A password is required to connect to '%s'."
msgstr "連線至「%s」需要密碼。" msgstr "連線至「%s」需要密碼。"
#: ../js/ui/components/polkitAgent.js:55 #: ../js/ui/components/polkitAgent.js:54
msgid "Authentication Required" msgid "Authentication Required"
msgstr "要求驗證" msgstr "要求驗證"
#: ../js/ui/components/polkitAgent.js:93 #: ../js/ui/components/polkitAgent.js:92
msgid "Administrator" msgid "Administrator"
msgstr "系統管理員" msgstr "系統管理員"
#: ../js/ui/components/polkitAgent.js:165 #: ../js/ui/components/polkitAgent.js:170
msgid "Authenticate" msgid "Authenticate"
msgstr "驗證" msgstr "驗證"
@@ -739,12 +741,12 @@ msgstr "驗證"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/components/polkitAgent.js: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." msgid "Sorry, that didn't work. Please try again."
msgstr "抱歉,那樣無法運作。請再試一次。" msgstr "抱歉,那樣無法運作。請再試一次。"
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/components/recorder.js:48 #: ../js/ui/components/recorder.js:47
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "Screencast from %d %t" msgstr "Screencast from %d %t"
@@ -1006,14 +1008,14 @@ msgstr "開啟行事曆"
msgid "Open Clocks" msgid "Open Clocks"
msgstr "開啟時鐘" msgstr "開啟時鐘"
#: ../js/ui/dateMenu.js:105 #: ../js/ui/dateMenu.js:104
msgid "Date & Time Settings" msgid "Date & Time Settings"
msgstr "日期與時刻設定值" msgstr "日期與時刻設定值"
#. Translators: This is the date format to use when the calendar popup is #. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). #. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. #.
#: ../js/ui/dateMenu.js:205 #: ../js/ui/dateMenu.js:216
msgid "%A %B %e, %Y" msgid "%A %B %e, %Y"
msgstr "%Y年%m月%e日%A" msgstr "%Y年%m月%e日%A"
@@ -1110,7 +1112,7 @@ msgstr "安裝"
msgid "Download and install '%s' from extensions.gnome.org?" 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/keyboard.js:619 ../js/ui/status/keyboard.js:333
#: ../js/ui/status/power.js:211 #: ../js/ui/status/power.js:211
msgid "Keyboard" msgid "Keyboard"
msgstr "鍵盤" msgstr "鍵盤"
@@ -1172,7 +1174,6 @@ msgid "Remove"
msgstr "移除" msgstr "移除"
#: ../js/ui/messageTray.js:1501 #: ../js/ui/messageTray.js:1501
#| msgid "No Messages"
msgid "Clear Messages" msgid "Clear Messages"
msgstr "清除訊息" msgstr "清除訊息"
@@ -1180,15 +1181,15 @@ msgstr "清除訊息"
msgid "Notification Settings" msgid "Notification Settings"
msgstr "通知設定值" msgstr "通知設定值"
#: ../js/ui/messageTray.js:1707 #: ../js/ui/messageTray.js:1709
msgid "No Messages" msgid "No Messages"
msgstr "沒有訊息" msgstr "沒有訊息"
#: ../js/ui/messageTray.js:1787 #: ../js/ui/messageTray.js:1785
msgid "Message Tray" msgid "Message Tray"
msgstr "訊息匣" msgstr "訊息匣"
#: ../js/ui/messageTray.js:2864 #: ../js/ui/messageTray.js:2818
msgid "System Information" msgid "System Information"
msgstr "系統資訊" msgstr "系統資訊"
@@ -1197,13 +1198,13 @@ msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "不明" msgstr "不明"
#: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149
#, c-format #, c-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
msgstr[0] "%d 個新訊息" msgstr[0] "%d 個新訊息"
#: ../js/ui/overview.js:82 #: ../js/ui/overview.js:84
msgid "Undo" msgid "Undo"
msgstr "復原" msgstr "復原"
@@ -1215,22 +1216,21 @@ msgstr "概覽"
#. in the search entry when no search is #. in the search entry when no search is
#. active; it should not exceed ~30 #. active; it should not exceed ~30
#. characters. #. characters.
#: ../js/ui/overview.js:284 #: ../js/ui/overview.js:271
#| msgid "Type to search..."
msgid "Type to search…" msgid "Type to search…"
msgstr "輸入以搜尋…" msgstr "輸入以搜尋…"
#: ../js/ui/panel.js:613 #: ../js/ui/panel.js:635
msgid "Quit" msgid "Quit"
msgstr "結束" msgstr "結束"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:642 #: ../js/ui/panel.js:686
msgid "Activities" msgid "Activities"
msgstr "概覽 " msgstr "概覽 "
#: ../js/ui/panel.js:983 #: ../js/ui/panel.js:982
msgid "Top Bar" msgid "Top Bar"
msgstr "頂端列" msgstr "頂端列"
@@ -1239,35 +1239,35 @@ msgstr "頂端列"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:727 #: ../js/ui/popupMenu.js:740
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-us" msgstr "toggle-switch-us"
#: ../js/ui/runDialog.js:205 #: ../js/ui/runDialog.js:74
msgid "Enter a Command" msgid "Enter a Command"
msgstr "請輸入指令" msgstr "請輸入指令"
#: ../js/ui/runDialog.js:241 #: ../js/ui/runDialog.js:110
msgid "Close" msgid "Close"
msgstr "關閉" msgstr "關閉"
#. Translators: This is a time format for a date in #. Translators: This is a time format for a date in
#. long format #. long format
#: ../js/ui/screenShield.js:90 #: ../js/ui/screenShield.js:86
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%m月%d日%A" msgstr "%m月%d日%A"
#: ../js/ui/screenShield.js:155 #: ../js/ui/screenShield.js:151
#, c-format #, c-format
msgid "%d new notification" msgid "%d new notification"
msgid_plural "%d new notifications" msgid_plural "%d new notifications"
msgstr[0] "%d 個新通知" 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" msgid "Lock"
msgstr "鎖定" msgstr "鎖定"
#: ../js/ui/screenShield.js:639 #: ../js/ui/screenShield.js:641
msgid "GNOME needs to lock the screen" msgid "GNOME needs to lock the screen"
msgstr "GNOME 需要鎖定螢幕" msgstr "GNOME 需要鎖定螢幕"
@@ -1278,37 +1278,35 @@ msgstr "GNOME 需要鎖定螢幕"
#. #.
#. XXX: another option is to kick the user into the gdm login #. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs #. screen, where we're not affected by grabs
#: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198
#| msgid "Unable to connect to %s"
msgid "Unable to lock" msgid "Unable to lock"
msgstr "無法鎖定" 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" msgid "Lock was blocked by an application"
msgstr "鎖定被應用程式阻擋" msgstr "鎖定被應用程式阻擋"
#: ../js/ui/searchDisplay.js:431 #: ../js/ui/searchDisplay.js:453
#| msgid "Searching..."
msgid "Searching…" msgid "Searching…"
msgstr "搜尋…" msgstr "搜尋…"
#: ../js/ui/searchDisplay.js:475 #: ../js/ui/searchDisplay.js:497
msgid "No results." msgid "No results."
msgstr "沒有結果。" msgstr "沒有結果。"
#: ../js/ui/shellEntry.js:29 #: ../js/ui/shellEntry.js:27
msgid "Copy" msgid "Copy"
msgstr "複製" msgstr "複製"
#: ../js/ui/shellEntry.js:34 #: ../js/ui/shellEntry.js:32
msgid "Paste" msgid "Paste"
msgstr "貼上" msgstr "貼上"
#: ../js/ui/shellEntry.js:105 #: ../js/ui/shellEntry.js:99
msgid "Show Text" msgid "Show Text"
msgstr "顯示文字" msgstr "顯示文字"
#: ../js/ui/shellEntry.js:107 #: ../js/ui/shellEntry.js:101
msgid "Hide Text" msgid "Hide Text"
msgstr "隱藏文字" msgstr "隱藏文字"
@@ -1320,7 +1318,7 @@ msgstr "密碼"
msgid "Remember Password" msgid "Remember Password"
msgstr "記住密碼" msgstr "記住密碼"
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
msgid "Unlock" msgid "Unlock"
msgstr "解鎖" msgstr "解鎖"
@@ -1384,12 +1382,10 @@ msgid "Visibility"
msgstr "顯示狀態" msgstr "顯示狀態"
#: ../js/ui/status/bluetooth.js:59 #: ../js/ui/status/bluetooth.js:59
#| msgid "Send Files to Device..."
msgid "Send Files to Device…" msgid "Send Files to Device…"
msgstr "傳送檔案到裝置…" msgstr "傳送檔案到裝置…"
#: ../js/ui/status/bluetooth.js:60 #: ../js/ui/status/bluetooth.js:60
#| msgid "Set Up a New Device..."
msgid "Set Up a New Device…" msgid "Set Up a New Device…"
msgstr "設定新的裝置…" msgstr "設定新的裝置…"
@@ -1416,7 +1412,6 @@ msgid "connecting..."
msgstr "連線中…" msgstr "連線中…"
#: ../js/ui/status/bluetooth.js:239 #: ../js/ui/status/bluetooth.js:239
#| msgid "Send Files..."
msgid "Send Files…" msgid "Send Files…"
msgstr "傳送檔案…" msgstr "傳送檔案…"
@@ -1492,11 +1487,11 @@ msgstr "請輸入裝置所提及的 PIN。"
msgid "OK" msgid "OK"
msgstr "確定" msgstr "確定"
#: ../js/ui/status/keyboard.js:368 #: ../js/ui/status/keyboard.js:396
msgid "Show Keyboard Layout" msgid "Show Keyboard Layout"
msgstr "顯示鍵盤配置" msgstr "顯示鍵盤配置"
#: ../js/ui/status/keyboard.js:373 #: ../js/ui/status/keyboard.js:401
msgid "Region & Language Settings" msgid "Region & Language Settings"
msgstr "地區和語言設定值" msgstr "地區和語言設定值"
@@ -1614,7 +1609,7 @@ msgstr "連線失敗"
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "啟動網路連線失敗" msgstr "啟動網路連線失敗"
#: ../js/ui/status/network.js:2276 #: ../js/ui/status/network.js:2282
msgid "Networking is disabled" msgid "Networking is disabled"
msgstr "網路已停用" msgstr "網路已停用"
@@ -1629,7 +1624,6 @@ msgstr "電源設定值"
#. 0 is reported when UPower does not have enough data #. 0 is reported when UPower does not have enough data
#. to estimate battery life #. to estimate battery life
#: ../js/ui/status/power.js:99 #: ../js/ui/status/power.js:99
#| msgid "Estimating..."
msgid "Estimating…" msgid "Estimating…"
msgstr "評估中…" msgstr "評估中…"
@@ -1725,11 +1719,11 @@ msgstr "音量"
msgid "Microphone" msgid "Microphone"
msgstr "麥克風" msgstr "麥克風"
#: ../js/ui/unlockDialog.js:151 #: ../js/ui/unlockDialog.js:120
msgid "Log in as another user" msgid "Log in as another user"
msgstr "以另一個使用者身分登入" msgstr "以另一個使用者身分登入"
#: ../js/ui/unlockDialog.js:177 #: ../js/ui/unlockDialog.js:141
msgid "Unlock Window" msgid "Unlock Window"
msgstr "解鎖視窗" msgstr "解鎖視窗"
@@ -1757,27 +1751,27 @@ msgstr "閒置"
msgid "Offline" msgid "Offline"
msgstr "離線" msgstr "離線"
#: ../js/ui/userMenu.js:780 #: ../js/ui/userMenu.js:781
msgid "Notifications" msgid "Notifications"
msgstr "通知" msgstr "通知"
#: ../js/ui/userMenu.js:796 #: ../js/ui/userMenu.js:797
msgid "Switch User" msgid "Switch User"
msgstr "切換使用者" msgstr "切換使用者"
#: ../js/ui/userMenu.js:801 #: ../js/ui/userMenu.js:802
msgid "Log Out" msgid "Log Out"
msgstr "登出" msgstr "登出"
#: ../js/ui/userMenu.js:821 #: ../js/ui/userMenu.js:822
msgid "Install Updates & Restart" msgid "Install Updates & Restart"
msgstr "安裝更新 & 重新啟動" msgstr "安裝更新 & 重新啟動"
#: ../js/ui/userMenu.js:839 #: ../js/ui/userMenu.js:840
msgid "Your chat status will be set to busy" msgid "Your chat status will be set to busy"
msgstr "您的聊天狀態會設為忙碌" msgstr "您的聊天狀態會設為忙碌"
#: ../js/ui/userMenu.js:840 #: ../js/ui/userMenu.js:841
msgid "" msgid ""
"Notifications are now disabled, including chat messages. Your online status " "Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages." "has been adjusted to let others know that you might not see their messages."
@@ -1785,20 +1779,22 @@ msgstr ""
"通知現在已被停用,包含聊天訊息。您的上線狀態也調整為讓其他人知道您沒時間看他" "通知現在已被停用,包含聊天訊息。您的上線狀態也調整為讓其他人知道您沒時間看他"
"們的訊息。" "們的訊息。"
#: ../js/ui/userMenu.js:886 #: ../js/ui/userMenu.js:888
msgid "Other users are logged in." msgid "Other users are logged in."
msgstr "其他使用者已登入。" msgstr "其他使用者已登入。"
#: ../js/ui/userMenu.js:891 #: ../js/ui/userMenu.js:893
msgid "Shutting down might cause them to lose unsaved work." msgid "Shutting down might cause them to lose unsaved work."
msgstr "關機可能使它們失去未儲存的工作。" 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 #, c-format
msgid "%s (remote)" msgid "%s (remote)"
msgstr "%s (遠端)" 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 #, c-format
msgid "%s (console)" msgid "%s (console)"
msgstr "%s (主控臺)" msgstr "%s (主控臺)"
@@ -1811,7 +1807,7 @@ msgstr "應用程式"
msgid "Search" msgid "Search"
msgstr "搜尋" msgstr "搜尋"
#: ../js/ui/wanda.js:92 #: ../js/ui/wanda.js:77
#, c-format #, c-format
msgid "" msgid ""
"Sorry, no wisdom for you today:\n" "Sorry, no wisdom for you today:\n"
@@ -1820,7 +1816,7 @@ msgstr ""
"抱歉,今天可能有些問題:\n" "抱歉,今天可能有些問題:\n"
"%s" "%s"
#: ../js/ui/wanda.js:96 #: ../js/ui/wanda.js:81
#, c-format #, c-format
msgid "%s the Oracle says" msgid "%s the Oracle says"
msgstr "%s Oracle 說:" msgstr "%s Oracle 說:"
@@ -1850,7 +1846,7 @@ msgid "%u Input"
msgid_plural "%u Inputs" msgid_plural "%u Inputs"
msgstr[0] "%u 輸入" msgstr[0] "%u 輸入"
#: ../src/gvc/gvc-mixer-control.c:2371 #: ../src/gvc/gvc-mixer-control.c:2373
msgid "System Sounds" msgid "System Sounds"
msgstr "系統音效" msgstr "系統音效"
@@ -1875,11 +1871,11 @@ msgstr "列出可能的模式"
msgid "Failed to launch '%s'" msgid "Failed to launch '%s'"
msgstr "無法啟動「%s」" msgstr "無法啟動「%s」"
#: ../src/shell-keyring-prompt.c:708 #: ../src/shell-keyring-prompt.c:714
msgid "Passwords do not match." msgid "Passwords do not match."
msgstr "密碼不相符。" msgstr "密碼不相符。"
#: ../src/shell-keyring-prompt.c:716 #: ../src/shell-keyring-prompt.c:722
msgid "Password cannot be blank" msgid "Password cannot be blank"
msgstr "密碼不能為空白" msgstr "密碼不能為空白"

View File

@@ -135,10 +135,7 @@ shell_private_sources = \
gactionobservable.h \ gactionobservable.h \
gactionobservable.c \ gactionobservable.c \
gactionobserver.h \ gactionobserver.h \
gactionobserver.c \ gactionobserver.c
gtkmenutracker.c \
gtkmenutracker.h \
$(NULL)
libgnome_shell_la_SOURCES = \ libgnome_shell_la_SOURCES = \
$(shell_built_sources) \ $(shell_built_sources) \
@@ -161,8 +158,6 @@ libgnome_shell_la_SOURCES = \
shell-invert-lightness-effect.c \ shell-invert-lightness-effect.c \
shell-keyring-prompt.h \ shell-keyring-prompt.h \
shell-keyring-prompt.c \ shell-keyring-prompt.c \
shell-menu-tracker.c \
shell-menu-tracker.h \
shell-mount-operation.c \ shell-mount-operation.c \
shell-network-agent.c \ shell-network-agent.c \
shell-perf-log.c \ shell-perf-log.c \

View File

@@ -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 = &section->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, &section->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);
}

View File

@@ -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__ */

Submodule src/gvc updated: 03894efbcd...3d6aac673b

View File

@@ -36,8 +36,6 @@ extern GType gnome_shell_plugin_get_type (void);
#define SHELL_DBUS_SERVICE "org.gnome.Shell" #define SHELL_DBUS_SERVICE "org.gnome.Shell"
#define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier" #define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier"
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
#define WM_NAME "GNOME Shell" #define WM_NAME "GNOME Shell"
#define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell" #define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell"
@@ -166,23 +164,6 @@ shell_dbus_init (gboolean replace)
g_object_unref (session); 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 static void
shell_introspection_init (void) shell_introspection_init (void)
{ {
@@ -409,7 +390,6 @@ main (int argc, char **argv)
shell_dbus_init (meta_get_replace_current_wm ()); shell_dbus_init (meta_get_replace_current_wm ());
shell_a11y_init (); shell_a11y_init ();
shell_perf_log_init (); shell_perf_log_init ();
shell_prefs_init ();
shell_introspection_init (); shell_introspection_init ();
shell_fonts_init (); shell_fonts_init ();

View File

@@ -39,14 +39,10 @@ typedef struct {
/* Whether or not we need to resort the windows; this is done on demand */ /* Whether or not we need to resort the windows; this is done on demand */
gboolean window_sort_stale : 1; gboolean window_sort_stale : 1;
/* DBus property notification subscription */
guint properties_changed_id : 1;
/* See GApplication documentation */ /* See GApplication documentation */
GDBusMenuModel *remote_menu; GDBusMenuModel *remote_menu;
GActionMuxer *muxer; GActionMuxer *muxer;
char *unique_bus_name; char * unique_bus_name;
GDBusConnection *session;
} ShellAppRunningState; } ShellAppRunningState;
/** /**
@@ -214,6 +210,7 @@ shell_app_create_icon_texture (ShellApp *app,
typedef struct { typedef struct {
ShellApp *app; ShellApp *app;
int size; int size;
ClutterTextDirection direction;
} CreateFadedIconData; } CreateFadedIconData;
static CoglHandle static CoglHandle
@@ -231,7 +228,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
guint8 n_channels; guint8 n_channels;
gboolean have_alpha; gboolean have_alpha;
gint fade_start; gint fade_start;
gint fade_range; gint fade_end;
guint i, j; guint i, j;
guint pixbuf_byte_size; guint pixbuf_byte_size;
guint8 *orig_pixels; guint8 *orig_pixels;
@@ -283,14 +280,26 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
pixels = g_malloc0 (rowstride * height); pixels = g_malloc0 (rowstride * height);
memcpy (pixels, orig_pixels, pixbuf_byte_size); memcpy (pixels, orig_pixels, pixbuf_byte_size);
fade_start = width / 2; /* fade on the right side for LTR, left side for RTL */
fade_range = width - fade_start; if (data->direction == CLUTTER_TEXT_DIRECTION_LTR)
for (i = fade_start; i < width; i++) {
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++) for (j = 0; j < height; j++)
{ {
guchar *pixel = &pixels[j * rowstride + i * n_channels]; 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[0] = 0.5 + pixel[0] * fade;
pixel[1] = 0.5 + pixel[1] * fade; pixel[1] = 0.5 + pixel[1] * fade;
pixel[2] = 0.5 + pixel[2] * 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: * shell_app_get_faded_icon:
* @app: A #ShellApp * @app: A #ShellApp
* @size: Size in pixels * @size: Size in pixels
* @direction: Whether to fade on the left or right
* *
* Return an actor with a horizontally faded look. * Return an actor with a horizontally faded look.
* *
* Return value: (transfer none): A floating #ClutterActor, or %NULL if no icon * Return value: (transfer none): A floating #ClutterActor, or %NULL if no icon
*/ */
ClutterActor * ClutterActor *
shell_app_get_faded_icon (ShellApp *app, int size) shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection direction)
{ {
CoglHandle texture; CoglHandle texture;
ClutterActor *result; 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 /* Use icon: prefix so that we get evicted from the cache on
* icon theme changes. */ * 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.app = app;
data.size = size; data.size = size;
data.direction = direction;
texture = st_texture_cache_load (st_texture_cache_get_default (), texture = st_texture_cache_load (st_texture_cache_get_default (),
cache_key, cache_key,
ST_TEXTURE_CACHE_POLICY_FOREVER, 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"); actions = g_object_get_data (G_OBJECT (window), "actions");
if (actions == NULL) 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), meta_window_get_gtk_unique_bus_name (window),
object_path)); object_path));
g_object_set_data_full (G_OBJECT (window), "actions", actions, g_object_unref); 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); 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 void
_shell_app_add_window (ShellApp *app, _shell_app_add_window (ShellApp *app,
MetaWindow *window) 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); 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_update_app_menu (app, window);
shell_app_ensure_busy_watch (app);
if (app->state != SHELL_APP_STATE_STARTING) if (app->state != SHELL_APP_STATE_STARTING)
shell_app_state_transition (app, SHELL_APP_STATE_RUNNING); shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
@@ -1301,8 +1236,6 @@ create_running_state (ShellApp *app)
app->running_state->workspace_switch_id = app->running_state->workspace_switch_id =
g_signal_connect (screen, "workspace-switched", G_CALLBACK(shell_app_on_ws_switch), app); 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 (); 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 *application_object_path;
const gchar *app_menu_object_path; const gchar *app_menu_object_path;
GDBusConnection *session;
GDBusActionGroup *actions; GDBusActionGroup *actions;
application_object_path = meta_window_get_gtk_application_object_path (window); 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) if (application_object_path == NULL || app_menu_object_path == NULL || unique_bus_name == NULL)
return; 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); g_clear_pointer (&app->running_state->unique_bus_name, g_free);
app->running_state->unique_bus_name = g_strdup (unique_bus_name); app->running_state->unique_bus_name = g_strdup (unique_bus_name);
g_clear_object (&app->running_state->remote_menu); 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); app->running_state->remote_menu = g_dbus_menu_model_get (session, unique_bus_name, app_menu_object_path);
actions = g_dbus_action_group_get (app->running_state->session, unique_bus_name, application_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_action_muxer_insert (app->running_state->muxer, "app", G_ACTION_GROUP (actions));
g_object_unref (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 ()); screen = shell_global_get_screen (shell_global_get ());
g_signal_handler_disconnect (screen, state->workspace_switch_id); 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->remote_menu);
g_clear_object (&state->muxer); g_clear_object (&state->muxer);
g_clear_object (&state->session);
g_clear_pointer (&state->unique_bus_name, g_free); g_clear_pointer (&state->unique_bus_name, g_free);
g_clear_pointer (&state->remote_menu, g_free); g_clear_pointer (&state->remote_menu, g_free);

View File

@@ -31,8 +31,7 @@ struct _ShellAppClass
typedef enum { typedef enum {
SHELL_APP_STATE_STOPPED, SHELL_APP_STATE_STOPPED,
SHELL_APP_STATE_STARTING, SHELL_APP_STATE_STARTING,
SHELL_APP_STATE_RUNNING, SHELL_APP_STATE_RUNNING
SHELL_APP_STATE_BUSY
} ShellAppState; } ShellAppState;
GType shell_app_get_type (void) G_GNUC_CONST; 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); GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size); 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_name (ShellApp *app);
const char *shell_app_get_description (ShellApp *app); const char *shell_app_get_description (ShellApp *app);
gboolean shell_app_is_window_backed (ShellApp *app); gboolean shell_app_is_window_backed (ShellApp *app);

View File

@@ -1009,6 +1009,13 @@ shell_global_end_modal (ShellGlobal *global,
meta_plugin_end_modal (global->plugin, timestamp); 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. /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
* *
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering * Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering

View File

@@ -44,6 +44,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global,
MetaModalOptions options); MetaModalOptions options);
void shell_global_end_modal (ShellGlobal *global, void shell_global_end_modal (ShellGlobal *global,
guint32 timestamp); guint32 timestamp);
void shell_global_freeze_keyboard (ShellGlobal *global,
guint32 timestamp);
typedef enum { typedef enum {
SHELL_STAGE_INPUT_MODE_NONREACTIVE, SHELL_STAGE_INPUT_MODE_NONREACTIVE,

View File

@@ -106,6 +106,8 @@ shell_gtk_embed_window_created_cb (MetaDisplay *display,
0, 0 /* offset x/y */); 0, 0 /* offset x/y */);
cairo_region_destroy (empty_region); cairo_region_destroy (empty_region);
gdk_window_lower (gdk_window);
/* Now that we've found the window we don't need to listen for /* Now that we've found the window we don't need to listen for
new windows anymore */ new windows anymore */
g_signal_handler_disconnect (display, g_signal_handler_disconnect (display,

View File

@@ -100,7 +100,6 @@ G_DEFINE_TYPE_WITH_CODE (ShellKeyringPrompt, shell_keyring_prompt, G_TYPE_OBJECT
enum { enum {
SIGNAL_SHOW_PASSWORD, SIGNAL_SHOW_PASSWORD,
SIGNAL_SHOW_CONFIRM, SIGNAL_SHOW_CONFIRM,
SIGNAL_HIDE_PROMPT,
SIGNAL_LAST SIGNAL_LAST
}; };
@@ -258,10 +257,8 @@ shell_keyring_prompt_dispose (GObject *obj)
{ {
ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj); ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
if (self->shown) { if (self->shown)
self->shown = FALSE; gcr_prompt_close (GCR_PROMPT (self));
g_signal_emit (self, signals[SIGNAL_HIDE_PROMPT], 0);
}
if (self->async_result) if (self->async_result)
shell_keyring_prompt_cancel (self); shell_keyring_prompt_cancel (self);
@@ -384,11 +381,6 @@ shell_keyring_prompt_class_init (ShellKeyringPromptClass *klass)
0, 0, NULL, NULL, 0, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0); 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 static void
@@ -482,6 +474,19 @@ shell_keyring_prompt_confirm_finish (GcrPrompt *prompt,
return self->last_reply; 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 static void
shell_keyring_prompt_iface (GcrPromptIface *iface) 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_password_finish = shell_keyring_prompt_password_finish;
iface->prompt_confirm_async = shell_keyring_prompt_confirm_async; iface->prompt_confirm_async = shell_keyring_prompt_confirm_async;
iface->prompt_confirm_finish = shell_keyring_prompt_confirm_finish; 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; GSimpleAsyncResult *res;
g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self)); 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; self->last_reply = GCR_PROMPT_REPLY_CANCEL;
res = self->async_result; res = self->async_result;

View File

@@ -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)

View File

@@ -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__ */

View File

@@ -25,6 +25,9 @@
/* This is also hard-coded in mutter and GDK */ /* This is also hard-coded in mutter and GDK */
#define VIRTUAL_CORE_POINTER_ID 2 #define VIRTUAL_CORE_POINTER_ID 2
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
typedef enum { typedef enum {
RECORDER_STATE_CLOSED, RECORDER_STATE_CLOSED,
RECORDER_STATE_RECORDING RECORDER_STATE_RECORDING
@@ -50,6 +53,8 @@ struct _ShellRecorder {
RecorderState state; RecorderState state;
ClutterStage *stage; ClutterStage *stage;
gboolean custom_area;
cairo_rectangle_int_t area;
int stage_width; int stage_width;
int stage_height; int stage_height;
@@ -66,6 +71,8 @@ struct _ShellRecorder {
CoglHandle recording_icon; /* icon shown while playing */ CoglHandle recording_icon; /* icon shown while playing */
GSettings *a11y_settings;
gboolean draw_cursor;
cairo_surface_t *cursor_image; cairo_surface_t *cursor_image;
int cursor_hot_x; int cursor_hot_x;
int cursor_hot_y; int cursor_hot_y;
@@ -110,6 +117,8 @@ static void recorder_set_pipeline (ShellRecorder *recorder,
const char *pipeline); const char *pipeline);
static void recorder_set_file_template (ShellRecorder *recorder, static void recorder_set_file_template (ShellRecorder *recorder,
const char *file_template); 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_set_caps (RecorderPipeline *pipeline);
static void recorder_pipeline_closed (RecorderPipeline *pipeline); static void recorder_pipeline_closed (RecorderPipeline *pipeline);
@@ -119,7 +128,8 @@ enum {
PROP_STAGE, PROP_STAGE,
PROP_FRAMERATE, PROP_FRAMERATE,
PROP_PIPELINE, PROP_PIPELINE,
PROP_FILE_TEMPLATE PROP_FILE_TEMPLATE,
PROP_DRAW_CURSOR
}; };
G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT); 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->recording_icon = create_recording_icon ();
recorder->memory_target = get_memory_target(); recorder->memory_target = get_memory_target();
recorder->a11y_settings = g_settings_new (A11Y_APPS_SCHEMA);
recorder->state = RECORDER_STATE_CLOSED; recorder->state = RECORDER_STATE_CLOSED;
recorder->framerate = DEFAULT_FRAMES_PER_SECOND; recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
recorder->draw_cursor = TRUE;
} }
static void static void
@@ -292,6 +305,8 @@ shell_recorder_finalize (GObject *object)
cogl_handle_unref (recorder->recording_icon); cogl_handle_unref (recorder->recording_icon);
g_clear_object (&recorder->a11y_settings);
G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object); 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 /* 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 * means that sometimes we aren't going to draw a cursor even when
* there is a little bit overlapping within the stage */ * there is a little bit overlapping within the stage */
if (recorder->pointer_x < 0 || if (recorder->pointer_x < recorder->area.x ||
recorder->pointer_y < 0 || recorder->pointer_y < recorder->area.y ||
recorder->pointer_x >= recorder->stage_width || recorder->pointer_x >= recorder->area.x + recorder->area.width ||
recorder->pointer_y >= recorder->stage_height) recorder->pointer_y >= recorder->area.y + recorder->area.height)
return; return;
if (!recorder->cursor_image) if (!recorder->cursor_image)
@@ -444,15 +459,15 @@ recorder_draw_cursor (ShellRecorder *recorder,
gst_buffer_map (buffer, &info, GST_MAP_WRITE); gst_buffer_map (buffer, &info, GST_MAP_WRITE);
surface = cairo_image_surface_create_for_data (info.data, surface = cairo_image_surface_create_for_data (info.data,
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_ARGB32,
recorder->stage_width, recorder->area.width,
recorder->stage_height, recorder->area.height,
recorder->stage_width * 4); recorder->area.width * 4);
cr = cairo_create (surface); cr = cairo_create (surface);
cairo_set_source_surface (cr, cairo_set_source_surface (cr,
recorder->cursor_image, recorder->cursor_image,
recorder->pointer_x - recorder->cursor_hot_x, recorder->pointer_x - recorder->cursor_hot_x - recorder->area.x,
recorder->pointer_y - recorder->cursor_hot_y); recorder->pointer_y - recorder->cursor_hot_y - recorder->area.y);
cairo_paint (cr); cairo_paint (cr);
cairo_destroy (cr); cairo_destroy (cr);
@@ -470,7 +485,7 @@ recorder_draw_buffer_meter (ShellRecorder *recorder)
GdkRectangle primary_monitor; GdkRectangle primary_monitor;
float rects[16]; 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), gdk_screen_get_primary_monitor (recorder->gdk_screen),
&primary_monitor); &primary_monitor);
@@ -555,12 +570,13 @@ recorder_record_frame (ShellRecorder *recorder)
recorder->last_frame_time = now; 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); data = g_malloc (recorder->area.width * 4 * recorder->area.height);
cogl_read_pixels (0, 0, /* x/y */ cogl_read_pixels (recorder->area.x,
recorder->stage_width, recorder->area.y,
recorder->stage_height, recorder->area.width,
recorder->area.height,
COGL_READ_PIXELS_COLOR_BUFFER, COGL_READ_PIXELS_COLOR_BUFFER,
CLUTTER_CAIRO_FORMAT_ARGB32, CLUTTER_CAIRO_FORMAT_ARGB32,
data); data);
@@ -572,7 +588,9 @@ recorder_record_frame (ShellRecorder *recorder)
GST_BUFFER_PTS(buffer) = now - recorder->start_time; 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); shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
@@ -593,7 +611,7 @@ recorder_on_stage_paint (ClutterActor *actor,
{ {
GdkRectangle primary_monitor; 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), gdk_screen_get_primary_monitor (recorder->gdk_screen),
&primary_monitor); &primary_monitor);
if (!recorder->only_paint) if (!recorder->only_paint)
@@ -616,6 +634,14 @@ recorder_update_size (ShellRecorder *recorder)
clutter_actor_get_allocation_box (CLUTTER_ACTOR (recorder->stage), &allocation); clutter_actor_get_allocation_box (CLUTTER_ACTOR (recorder->stage), &allocation);
recorder->stage_width = (int)(0.5 + allocation.x2 - allocation.x1); recorder->stage_width = (int)(0.5 + allocation.x2 - allocation.x1);
recorder->stage_height = (int)(0.5 + allocation.y2 - allocation.y1); 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 static void
@@ -1006,6 +1032,18 @@ recorder_set_file_template (ShellRecorder *recorder,
g_object_notify (G_OBJECT (recorder), "file-template"); 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 static void
shell_recorder_set_property (GObject *object, shell_recorder_set_property (GObject *object,
guint prop_id, guint prop_id,
@@ -1028,6 +1066,9 @@ shell_recorder_set_property (GObject *object,
case PROP_FILE_TEMPLATE: case PROP_FILE_TEMPLATE:
recorder_set_file_template (recorder, g_value_get_string (value)); recorder_set_file_template (recorder, g_value_get_string (value));
break; break;
case PROP_DRAW_CURSOR:
recorder_set_draw_cursor (recorder, g_value_get_boolean (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -1056,6 +1097,9 @@ shell_recorder_get_property (GObject *object,
case PROP_FILE_TEMPLATE: case PROP_FILE_TEMPLATE:
g_value_set_string (value, recorder->file_template); g_value_set_string (value, recorder->file_template);
break; break;
case PROP_DRAW_CURSOR:
g_value_set_boolean (value, recorder->draw_cursor);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -1104,6 +1148,14 @@ shell_recorder_class_init (ShellRecorderClass *klass)
"The filename template to use for output files", "The filename template to use for output files",
NULL, NULL,
G_PARAM_READWRITE)); 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 /* 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, "bpp", G_TYPE_INT, 32,
"depth", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24,
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1, "framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
"width", G_TYPE_INT, pipeline->recorder->stage_width, "width", G_TYPE_INT, pipeline->recorder->area.width,
"height", G_TYPE_INT, pipeline->recorder->stage_height, "height", G_TYPE_INT, pipeline->recorder->area.height,
NULL); NULL);
g_object_set (pipeline->src, "caps", caps, NULL); g_object_set (pipeline->src, "caps", caps, NULL);
gst_caps_unref (caps); 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: * shell_recorder_set_pipeline:
* @recorder: the #ShellRecorder * @recorder: the #ShellRecorder
@@ -1705,9 +1766,35 @@ shell_recorder_set_pipeline (ShellRecorder *recorder,
recorder_set_pipeline (recorder, pipeline); 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: * shell_recorder_record:
* @recorder: the #ShellRecorder * @recorder: the #ShellRecorder
* @filename_used: (out) (allow-none): actual filename used for recording
* *
* Starts recording, Starting the recording may fail if the output file * Starts recording, Starting the recording may fail if the output file
* cannot be opened, or if the output stream cannot be created * 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 * Return value: %TRUE if recording was succesfully started
*/ */
gboolean 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 (SHELL_IS_RECORDER (recorder), FALSE);
g_return_val_if_fail (recorder->stage != NULL, FALSE); g_return_val_if_fail (recorder->stage != NULL, FALSE);
@@ -1733,6 +1821,9 @@ shell_recorder_record (ShellRecorder *recorder)
if (!recorder_open_pipeline (recorder)) if (!recorder_open_pipeline (recorder))
return FALSE; return FALSE;
if (filename_used)
*filename_used = g_strdup (recorder->current_pipeline->filename);
recorder_connect_stage_callbacks (recorder); recorder_connect_stage_callbacks (recorder);
recorder->start_time = get_wall_time(); recorder->start_time = get_wall_time();

View File

@@ -36,7 +36,15 @@ void shell_recorder_set_file_template (ShellRecorder *recorder,
const char *file_template); const char *file_template);
void shell_recorder_set_pipeline (ShellRecorder *recorder, void shell_recorder_set_pipeline (ShellRecorder *recorder,
const char *pipeline); 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_close (ShellRecorder *recorder);
void shell_recorder_pause (ShellRecorder *recorder); void shell_recorder_pause (ShellRecorder *recorder);
gboolean shell_recorder_is_recording (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