Compare commits

...

362 Commits

Author SHA1 Message Date
7d598b7725 Bump version to 3.7.3.1
Update NEWS.
2012-12-20 17:47:36 +01:00
9f890982b2 Revert "NetworkMenu: rework multiple NIC support"
This reverts commit 490206b5b2.

Conflicts:
	configure.ac
	src/gvc
2012-12-20 17:46:31 +01:00
2698d0db29 Bump version to 3.7.3
Update NEWS.
2012-12-18 18:28:42 +01:00
2fa7230133 gvc: Update git submodule
This fixes make distcheck.
2012-12-18 18:28:42 +01:00
658243eae4 build: Exclude .gitmodules from distribution 2012-12-18 18:28:42 +01:00
7282bc8859 build: Bump gsettings-desktop-schemas requirement 2012-12-18 18:28:42 +01:00
07511cb21a Handle 'switch-input-source' keybinding move
Moving this to gsettings-desktop-schemas instead so that
gnome-control-center doesn't have to grow a dependency on gnome-shell.

https://bugzilla.gnome.org/show_bug.cgi?id=690427
2012-12-18 16:13:13 +00:00
f71f767a3c [l10n] Updated Estonian translation 2012-12-18 17:34:09 +02:00
176daa1469 WorkspacesDisplay: clean up workspacesView lists
Rather than sometimes having a list and sometimes null, keep an array
always and check for its length.

https://bugzilla.gnome.org/show_bug.cgi?id=688234
2012-12-18 16:00:54 +01:00
5487f8cf93 WorkspacesView: don't use clutter_actor_reparent()
It's deprecated and in this case is not needed because at that point
the actor hasn't been parented yet.

https://bugzilla.gnome.org/show_bug.cgi?id=688234
2012-12-18 16:00:54 +01:00
944762ac83 WindowOverlay: fix title sizing
After the first time the title was placed, we were setting its width,
thus forcing get_preferred_width() to return that as the minimum and
natural width.
To workaround that, explicitly reset the width to -1, -1, causing
StLabel->get_preferred_width() to be called, which would give us a meaningful
value for minimum and natural width.

https://bugzilla.gnome.org/show_bug.cgi?id=688234
2012-12-18 16:00:54 +01:00
c66068c435 Workspace: fix window clone slot reporting
WindowOverlay was at times seeing bogus values reported as WindowClone
sizes. Fix that by storing and passing the value from the authoritative
source, that is, the LayoutStrategy.

https://bugzilla.gnome.org/show_bug.cgi?id=688234
2012-12-18 16:00:54 +01:00
d479c936b8 Workspace: miscellaneuous cleanups
Use a single GSettings object for all layout changes of window overlays,
and avoid quadratic behavior for window positioning.

https://bugzilla.gnome.org/show_bug.cgi?id=650843
2012-12-18 16:00:54 +01:00
c5a3f784dd theme: make the 'more results' emblem more legible on light icons 2012-12-18 15:40:23 +01:00
529d012865 LockScreenMenu: double the space between icons
Using the same spacing as secondary status icons causes the
three indicators to be too close to each other.

https://bugzilla.gnome.org/show_bug.cgi?id=687955
2012-12-17 17:25:29 +01:00
8a1b83417a network: add minimal support for InfiniBand
If present, InfiniBand devices show up with the ethernet devices (and
the presence of an InfiniBand connection will cause "Wired" to be
renamed to "Ethernet").

https://bugzilla.gnome.org/show_bug.cgi?id=677150
2012-12-17 08:11:36 -05:00
6c64c0873c workspaceThumbnail: unify restack handling
Both WorkspacesDisplay and ThumbnailsBox need to know when windows have been
restacked. Instead of each tracking changes on their own or trying to call
each other, have the overview keep track and do the calculations, emitting
a signal with the result.

https://bugzilla.gnome.org/show_bug.cgi?id=690175
2012-12-17 13:24:25 +01:00
d2c6149923 workspaceThumbnail: handle show/hide when entering/leaving the overview
Handle this internally, instead of having WorkspacesDisplay show/hide
us.

https://bugzilla.gnome.org/show_bug.cgi?id=690175
2012-12-17 13:24:25 +01:00
9f98f6f02d workspaceThumbnail: handle scroll-event internally
Instead of having WorkspacesDisplay calling us.

https://bugzilla.gnome.org/show_bug.cgi?id=690175
2012-12-17 13:24:25 +01:00
2f7c0b1985 workspaceThumbnail: make ThumbnailsBox track workspace changes itself
Instead of having WorkspacesDisplay calling us.

https://bugzilla.gnome.org/show_bug.cgi?id=690175
2012-12-17 13:24:25 +01:00
f61548234a status/keyboard: Add an Alt+Tab like input source switcher
https://bugzilla.gnome.org/show_bug.cgi?id=682315
2012-12-17 11:43:02 +00:00
6eef830ba4 status/keyboard: Keep a list of input sources in MRU order
This will allow us to provide an Alt+Tab like input source switcher.

https://bugzilla.gnome.org/show_bug.cgi?id=682315
2012-12-17 11:43:02 +00:00
88a9b7648c Add the new switch-input-source keybinding
https://bugzilla.gnome.org/show_bug.cgi?id=682315
2012-12-17 11:43:02 +00:00
b7678493f9 windowManager: Return the KeyBindingAction value from addKeybinding()
meta_display_add_keybinding() returns a keybinding action ID for
dynamically registered keybindings which can be used to match a
keycode/mask pair to the action it is bound to.

https://bugzilla.gnome.org/show_bug.cgi?id=682315
2012-12-17 11:43:01 +00:00
a9ec8a354a main: Initialize WindowManager earlier
This allows us to register keybindings from most other places that
might need to do so like the panel or any status indicator.

https://bugzilla.gnome.org/show_bug.cgi?id=682315
2012-12-17 11:43:01 +00:00
a42d35deab main: Add an ALL value to KeybindingMode
https://bugzilla.gnome.org/show_bug.cgi?id=682315
2012-12-17 11:43:01 +00:00
2008feb7da status/keyboard: Store IBus engine properties per InputSource object
Instead of storing them globally and having an hardcoded list of
engines which are allowed to change their indicator symbol when the
InputMode property changes.

https://bugzilla.gnome.org/show_bug.cgi?id=682318
2012-12-17 11:43:01 +00:00
c41424b57b status/keyboard: Make input sources be proper objects
Introduce an InputSource class which makes it easier to keep track of
all the data we have about them.

https://bugzilla.gnome.org/show_bug.cgi?id=682318
2012-12-17 11:43:01 +00:00
3bd5563a7e ctrlAltTab: Remove a "window" parameter leftover
Commit 1f46a0d removed support for the items "window" parameter but
there was an occurence left.

https://bugzilla.gnome.org/show_bug.cgi?id=690312
2012-12-16 23:03:34 +01:00
eff8ec00c4 Updated slovak translation 2012-12-16 22:50:06 +01:00
1256af7b9a WindowManager: scale windows to their monitor's corner on minimize
We previously scaled windows to (primary.x, 0), which is wrong if the
primary monitor is not at y == 0. At the same time, change the policy
to pick the hot corner on the monitor the window is on, because that's
closest to where it will appear in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=690241
2012-12-16 22:40:33 +01:00
b38ecaf925 LayoutManager: fix findMonitorForWindow to take a metaWindow
This makes the method usable in places where the associated window actor
might not have the right size (such as from window manager animations).
Also, make the method public from LayoutManager.

https://bugzilla.gnome.org/show_bug.cgi?id=690241
2012-12-16 22:40:33 +01:00
bd5d945fb2 Updated Spanish translation 2012-12-16 20:48:08 +01:00
15063ef3d5 WindowManager: clean up scale_y when overwrite the map animation
If we overwrite a map animation (for example because the actor is now destroyed),
we need to complete it first, otherwise it starts off from a random
middle point. This is the same treatment opacity gets for normal windows.

https://bugzilla.gnome.org/show_bug.cgi?id=690241
2012-12-16 20:45:43 +01:00
3b8a125732 WindowManager: clean up effects code
Use consistently shouldAnimateActor(), and try to have a uniform code flow
between the modal dialog and the normal case.

https://bugzilla.gnome.org/show_bug.cgi?id=690241
2012-12-16 20:45:43 +01:00
9860b1c677 St: fix regression from f7af96dbb2
A bad rebase caused the wrong patch to be pushed.

https://bugzilla.gnome.org/show_bug.cgi?id=687881
2012-12-16 20:45:43 +01:00
a0e340f06e workspaces-view: make sure to add spacing between view and controls
The thumbnail controls are not a separate actor in the overview group
yet, so we need to ensure a spacing between them and the workspaces
view.
Instead of exporting the overview spacing, just add a temporary style
class to the workspaces-view actor for it. It will be removed in the
future when we change the layout of overview elements.

https://bugzilla.gnome.org/show_bug.cgi?id=690174
2012-12-15 14:13:36 -05:00
57d3bec95c MessageTray: change notification and boxpointer background opacity to
make the text in it more clear.
2012-12-15 16:34:58 +01:00
be10f3c2b5 ViewSelector: remove unnecessary StBoxLayout
It was a remnant from the tabbed interface.

https://bugzilla.gnome.org/show_bug.cgi?id=690171
2012-12-15 15:23:21 +01:00
f7af96dbb2 St: avoid blocking IO to resolve relative urls
realpath() does a series of lstat() on each path component to resolve
symbolic links, but we just want to get an absolute path, and we don't
really care if it is physical or not. Going through a GFile does the
canonicalization we need, and is a lot faster.

https://bugzilla.gnome.org/show_bug.cgi?id=687881
2012-12-15 03:40:13 +01:00
468a855f04 make the window thumbnails bigger
Adjust the layout of the overview and window thumbnails to make them
bigger. Also, make the background shade darker to compensate for the
increased thumbnail density.

https://bugzilla.gnome.org/show_bug.cgi?id=689876
2012-12-14 12:58:43 +00:00
429f9e1d15 iconGrid: Only recreate icons when needed
Recreating icons on every style change -- like hover, can have
disasterous effects. Not only is the quick creation/destruction of
the actors bad, but adding/removing actors at runtime queues many
relayouts, which makes the whole system slower as a lot of unnecessary
reallocations are figured out.

While an optimization was here before, it was broken because it
broke high-contrast themes. Connect explicitly to the texture cache
to know when the icon theme has changed, instead of removing a valuable
optimization.

https://bugzilla.gnome.org/show_bug.cgi?id=672941
2012-12-13 21:35:05 -05:00
5de91197ae status/keyboard: remove the property whitelist
It was just a stopgap solution for 3.6, as the necessary UI bits
were not implemented.

https://bugzilla.gnome.org/show_bug.cgi?id=682318
2012-12-14 00:47:19 +01:00
bc6b4b01ea status/keyboard: implement remaining property types
Input methods other than Anthy need different property types, so we
should support all those exposed by the IBus protocol.

https://bugzilla.gnome.org/show_bug.cgi?id=682318
2012-12-14 00:47:19 +01:00
e89ce7358a overview: don't clone the whole message tray when layouting
The message tray actor also includes notifications themselves. We want
our ghost to be sized as the base part of the tray instead.
Just make sure to use the same style class as the base actor then, as
its height is specified by the CSS.

https://bugzilla.gnome.org/show_bug.cgi?id=690174
2012-12-13 17:56:23 -05:00
bdf0a6fd0b message-tray: use a style class for summary-mode actor
We want to use the same style class for the message tray ghost.

https://bugzilla.gnome.org/show_bug.cgi?id=690174
2012-12-13 17:56:22 -05:00
783abd4f5f Reverting "extensionUtils: Remove unused property"
This reverts commit 28aa9201f0.

This broke the extension-state-changed signal.

https://bugzilla.gnome.org/show_bug.cgi?id=690173
2012-12-13 14:16:44 -05:00
28aa9201f0 extensionUtils: Remove unused property
https://bugzilla.gnome.org/show_bug.cgi?id=690173
2012-12-13 19:55:34 +01:00
378df515d0 extensionSystem: Fix error reporting in lg / ListExtensionErrors()
Commit c99e8eb29 removed this line probably accidentally, as no
effort has been made to replace consumers in lookingGlass and
shellDBus.

https://bugzilla.gnome.org/show_bug.cgi?id=690173
2012-12-13 19:55:33 +01:00
04d68c6e36 overview: overview as boxlayouts
https://bugzilla.gnome.org/show_bug.cgi?id=682286
2012-12-13 09:38:45 -05:00
5308d12239 search: skip combining diacritical marks in search operations
https://bugzilla.gnome.org/show_bug.cgi?id=648587
2012-12-12 17:41:45 +01:00
15cac0157c networkAgent: Only unregister if we've registered
It's possible to turn auto_register back on, but not immediately be
registered. Don't cause a (harmless) critical in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=689884
2012-12-12 06:35:46 -05:00
fc696bc054 userMenu: Update user name on session mode changes
The new privacy panel offers separate settings for the user name
visibility in lock screen and normal mode. The code to support
either setting is already in place, but we need to make sure to
update the user name on session mode changes to pick up the correct
one.

https://bugzilla.gnome.org/show_bug.cgi?id=690049
2012-12-11 20:31:46 +01:00
5a7b7b7389 bluetooth: Update settings desktop file
For the one now used in gnome-control-center

https://bugzilla.gnome.org/show_bug.cgi?id=690046
2012-12-11 17:12:00 +01:00
9c9cf6f5ab Depend on libpulse 2.0
Commit 3af9f636af introduced a dependency on
libpulse 2.0 so best to check for it.

https://bugzilla.gnome.org/show_bug.cgi?id=689965
2012-12-11 11:42:50 +01:00
0155739bef search: remove more dead code
https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:54 -05:00
d0902fa28b search: remove SearchProvider base class
This is causing more confusion than anything else these days; the DBus
API is properly documented now and that's what people are expected to
use, the rest are implementation details we're not interested in
exposing.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:54 -05:00
3aa0d455c9 search: remove SearchResultDisplay base class
It's unused, and the clear() method is just wrong. Remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:54 -05:00
835d4e4b58 appDisplay: Don't use icons in results for settings
The search results are not necessarily improved by including icons, so don't.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:54 -05:00
6075332f2f remoteSearch: We do not need a fallback for createIcon
Remote providers no longer have access to a grid layout, where an icon is
a requirement. If they don't specify an icon, don't create one.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:53 -05:00
c5d8484e19 searchDisplay: Add ListSearchResult and ListSearchResults
These are for all search results except apps (and Wanda).
We also simplify a bit the packing of search results, which removes some
ugly code in navigateFocus() where we needed to call
st_widget_navigate_focus() twice, since the grid icon was composed by
two nested boxes, both focusable.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:53 -05:00
575ab0d609 searchDisplay: simplify drag actor source code
Make sure this._dragActorSource is always set from _init() to siplify
code.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:53 -05:00
b48a7d5cfd popupMenu: Break separator drawing code out of PopupSeparatorMenuItem
And into a separate HorizontalSeparatorClass.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:53 -05:00
9af107feff searchDisplay, and others: Switch from provider title to provider icon
Display a '+' icon on the provider icon if there are more results that are
hidden. If the provider icon is clicked, ask the provider to launch itself and
perform a search with the current terms.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
2012-12-10 16:50:53 -05:00
70b5db16d3 search: make sure to pass a timestamp to LaunchSearch()
Do not repeat past mistakes while we're still in time.

https://bugzilla.gnome.org/show_bug.cgi?id=690009
2012-12-10 16:50:22 -05:00
5072ea7e47 Calendar: remove dead code
this._weekdateHeader is never assigned, so _setWeekdateHeaderWidth is
useless. Everything else falls from that.

Spotted by mathematical.coffee@gmail.com, our human coverity :)

https://bugzilla.gnome.org/show_bug.cgi?id=687250
2012-12-10 22:34:10 +01:00
13b83c95b7 build: Remove Makefile-gvc.am
This is now unused, and potentially confusing.

https://bugzilla.gnome.org/show_bug.cgi?id=689955
2012-12-10 14:38:07 -05:00
e48dbe65f1 overview: Clean up overview code
The comment here is a liar. We certainly can handle failure
using _syncInputMode().

https://bugzilla.gnome.org/show_bug.cgi?id=688589
2012-12-10 14:38:07 -05:00
14fb51e6d7 overview: Fix stuck grabs when mashing the overlay-key
When pressing the overlay key three times, things went like this:

  * show(), push a modal
  * hide(), will pop a modal after hiding is done
  * show(), push a modal

Thus, when the showing is done, and then it activated the hiding,
it popped one modal, but not the other. This patch changes things
to be:

  * show(), push a modal
  * hide(), will pop a modal after hiding is done
  * hide(), no-op

That is, mashing the overlay-key when it's showing will always make
it hide, not mashing an odd number of times.

https://bugzilla.gnome.org/show_bug.cgi?id=688589
2012-12-10 14:38:07 -05:00
b42af9aa99 popupMenu: Don't slide menus when we're changing them
As calling close() will drop the grab, we were inadverdently
re-closing menus, causing them to re-animate with a full animation.

https://bugzilla.gnome.org/show_bug.cgi?id=689954
2012-12-10 14:38:07 -05:00
ca2ee22827 popupMenu: Display the proper animations for popup menus
BoxPointer's API changed to take a BoxPointer.PopupAnimation
enumeration value, but the code was accidentally replaced with
older code when porting the PopupMenuManager code to GrabHelper.

https://bugzilla.gnome.org/show_bug.cgi?id=689954
2012-12-10 14:38:07 -05:00
13a2b28bf1 popupMenu: Complete the dummy fake menu
"toggle" is used when clicking on the source actor. As we don't
actually have a menu, we don't want to actually take any grabs
through the menu system, so make it a no-op rather than have it
toggle the menu state.

https://bugzilla.gnome.org/show_bug.cgi?id=689954
2012-12-10 14:38:06 -05:00
04bf75d137 panel: Remove a dead check
With the dummy menu item now in place, we will always have a menu.

https://bugzilla.gnome.org/show_bug.cgi?id=689954
2012-12-10 14:38:06 -05:00
76c589702f Assamese translation updated 2012-12-10 18:24:06 +05:30
c11f89e72a messageTray: Don't add ourselves more than once to CtrlAltTabManager
This way _sessionUpdated() can be called multiple times without side
effects.

https://bugzilla.gnome.org/show_bug.cgi?id=689959
2012-12-10 11:50:05 +01:00
cfacb05461 gnome-shell-jhbuild: Allow passing args to gnome-shell
$ ./gnome-shell -- --list-modes

https://bugzilla.gnome.org/show_bug.cgi?id=689778
2012-12-09 18:30:46 -05:00
c4ba31cb23 Updated POTFILES.in
Yes, it has to be there. Run:

git submodule init && git submodule update

to make it work.
2012-12-09 19:13:01 +01:00
db0eacddc5 Updated Norwegian bokmål translation 2012-12-09 14:02:59 +01:00
62972f5138 Update Arabic translation 2012-12-09 04:53:24 +02:00
6fe263f19f Drop removed file 2012-12-09 04:46:09 +02:00
b6a87acb71 gvc: Update git submodule
This fixes the build.
2012-12-08 13:38:43 -05:00
784b04b191 VolumeMenu: show headphone icon when headphones are plugged in
This will show the user where sound will come out, and should
help if he forgets them plugged, or forgets to plug them before
playing music.

https://bugzilla.gnome.org/show_bug.cgi?id=675902
2012-12-08 15:54:05 +01:00
3af9f636af Use libgnome-volume-control from a submodule
To be shared with gnome-control-center and gnome-settings-daemon
2012-12-08 15:53:46 +01:00
16c0585b95 fileUtils: correctly determine file type for symbolic links
Extensions in a folder that is a symbolic link do not get loaded,
since the returned file type is unknown.

https://bugzilla.gnome.org/show_bug.cgi?id=689868
2012-12-08 02:53:21 -05:00
fc9a96ac85 popupMenu: Introduce PopupDummyMenu
This is designed for things like the activities button that sort of
need a menu to make navigation work, but not really have it do anything.

https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-12-07 19:55:28 -05:00
9dfc3af9d7 popupMenu: Port to GrabHelper
https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-12-07 19:55:28 -05:00
8dc63932fc grabHelper: Fix up event handling for ignoring releases
We need to return 'true' to signify that we handled the event.

https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-12-07 19:55:23 -05:00
066e5cddb5 grabHelper: Drop to the actor clicked on
This is necessary for child popups in menus, e.g. while in a combo box,
clicking outside of the user menu should drop the entire menu, but
clicking on the user menu itself should only drop the combo box.

https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-12-07 19:54:46 -05:00
27ffad2148 grabHelper: Treat the current grabbed actor as a grabbed actor
This should be obvious, but I guess it wasn't necessary for the
message tray case.

https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-12-07 19:53:47 -05:00
41db363b06 grabHelper: Use captured-event for escape ungrabs
I have no idea why we used 'event' rather than 'captured-event' before.
'event' has some really strange quirks that came up when porting PopupMenu
to the GrabHelper

https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-12-07 19:53:46 -05:00
184ac11c93 ctrlAltTab: Remove leftover
Accidentally forgot to remove this before pushing.
2012-12-07 13:02:57 -05:00
673aa3c5f2 Updated Kannada Translations 2012-12-07 16:12:16 +05:30
2dd1c04bf3 Updated Kannada Translations 2012-12-07 15:37:39 +05:30
4df1222ce7 screen-shield: disconnect from title-changed on destroy
https://bugzilla.gnome.org/show_bug.cgi?id=689820
2012-12-06 19:07:27 -05:00
208121646c St: recompute all theme nodes when the icon theme changes
StWidget considers "same theme node" as an indication that the style
did not change, and skips emitting style-changed in that case. This
means that icon theme changes are not picked up by StIcon.

https://bugzilla.gnome.org/show_bug.cgi?id=689353
2012-12-06 17:42:07 -05:00
f47a11f792 Updated POTFILES.in 2012-12-06 22:37:41 +01:00
36fc3a5c96 st: fix rendering of corners in the box-shadow
https://bugzilla.gnome.org/show_bug.cgi?id=689789
2012-12-06 18:42:37 +00:00
ed12c9d611 fileUtils: Don't fail if we can't find an error
We need to make sure that we decrement the number of dirs that
we've loaded, and call the callback on error.

https://bugzilla.gnome.org/show_bug.cgi?id=689749
2012-12-06 13:32:12 -05:00
4153feeb15 grabHelper: Use focus_default_window
This prevents us from having to track the previously focused window.

https://bugzilla.gnome.org/show_bug.cgi?id=689653
2012-12-06 12:25:37 -05:00
349c642d10 ctrlAltTab: Add a "Windows" option to Ctrl+Alt+Tab
This lets accessibility users easily access the desktop after focusing the panel.

https://bugzilla.gnome.org/show_bug.cgi?id=689653
2012-12-06 12:25:37 -05:00
4728105f43 ctrlAltTab: Only add to the focus manager if we have an StWidget.
https://bugzilla.gnome.org/show_bug.cgi?id=689653
2012-12-06 12:25:37 -05:00
1f46a0dc26 ctrlAltTab: Remove some dead code for a "window" parameter
This isn't set on any item, so we can safely remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=689653
2012-12-06 12:25:37 -05:00
7ff7ced504 switcherPopup: Add a timestamp argument to _finish()
And use it elsewhere.

https://bugzilla.gnome.org/show_bug.cgi?id=689653
2012-12-06 12:25:37 -05:00
a43ee41b0b app-display: use a GAppInfo for the settings provider
this._gnomecc is currently unused; we actually need a GAppInfo for this
provider if we want to display an icon next to it (see future commits),
so just turn it into one.
We might move this to an external provider altogether in the future.

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:15:13 -05:00
ec7ade4ee6 remote-search: implement new ActivateResult() method
This allows us to fix the shortcomings of the original ActivateResult()
method. In particular:
- allow to pass the search terms to the provider
- allow to pass a user interaction timestamp

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:15:13 -05:00
9b846cbb83 search: remove additional params from activateResult() call
The only case when we're interested in using those parameters nowadays
is for DnD, which is handled in a separate method already.
Since we're not going to support DnD for non-app search results anyway,
drop the params from all the activateResults() calls; this will be
useful later since we're going to add another parameter to it.

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:15:13 -05:00
2cc7fd07f8 remote-search: implement LaunchSearch() DBus method
This will be used to launch a search in the application itself.

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:15:13 -05:00
72d54d9915 remote-search: first implementation of SearchProvider2
We read the implemented version from the search provider's keyfile, and
then create a RemoteSearchProvider object from the right class
accordingly.
Wire ActivateResult() to the new method (without actually passing the
new parameters along) - an actual implementation will be added in a
future commit.

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:15:12 -05:00
b390b82e9d remote-search: add an org.gnome.ShellSearchProvider2 dbus interface
We are going to change the interface, so add a new version of it.
Providers will need to opt-in to the new API.
A summary of the differences compared to the previous API:
- ActivateResult() now also takes the search terms and a timestamp as
  parameters
- a new LaunchSearch() method is added

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:13:24 -05:00
1ef9ee13a3 remote-search: properly document the DBus interface
Use real annotations in the XML, and use gdbus-codegen to extract those
into docbook. We then include it in the Shell's gtk-doc.

https://bugzilla.gnome.org/show_bug.cgi?id=689735
2012-12-06 12:13:24 -05:00
6822795bb8 build: Fix distcheck 2012-12-05 23:35:35 +01:00
187dec2816 sessionMode: Add support for 'parentMode' property
Defining a mode that differs significantly from the default one
can get rather cumbersome. For convenience, allow mode definitions
to inherit from an existing mode.

https://bugzilla.gnome.org/show_bug.cgi?id=689308
2012-12-05 21:56:57 +01:00
31f75e4607 extensionSystem: Add support for mode-specific extensions
As currently envisioned, the fallback replacement in 3.8 should be
a separate session at the login screen. As we will use extensions
to implement this mode, we need a way to specify extensions per
session rather than per user, so add a session-mode property for
extensions that should be loaded in addition to the user-defined
ones.

https://bugzilla.gnome.org/show_bug.cgi?id=689305
2012-12-05 21:56:57 +01:00
92083eaf76 sessionMode: Make loading of external modes asynchronous
Blocking IO on startup is bad m'kay ...

https://bugzilla.gnome.org/show_bug.cgi?id=689304
2012-12-05 21:56:57 +01:00
6b40c3974d extensionUtils: Load extensions asynchronously
Use the new collectFromDatadirsAsync() function for extension
loading as well.

https://bugzilla.gnome.org/show_bug.cgi?id=689304
2012-12-05 21:56:21 +01:00
c528401b62 remoteSearch: Factor out collectFromDatadirsAsync() utility function
Processing files from a subdirectory of various share/gnome-shell
directories asynchronously is a common enough pattern to share
the common code.

https://bugzilla.gnome.org/show_bug.cgi?id=689304
2012-12-05 21:56:20 +01:00
8a17f512f4 sessionMode: Add support for external mode definitions
Currently adding a new session mode requires patching the sources.
As defining custom modes can be desirable in some circumstances
(for instance for administrators of kiosk setups), load additional
modes from JSON files.

https://bugzilla.gnome.org/show_bug.cgi?id=689304
2012-12-05 21:56:17 +01:00
e725f8a0fe altTab: Re-implement 'switch-windows' keybinding
Now that we use the new 'switch-applications' keybinding for the
application-based alt-tab popup, we can use the 'switch-windows'
keybinding for a more traditional switcher.

Based heavily on the alternate-tab extension from Giovanni Campagna.

https://bugzilla.gnome.org/show_bug.cgi?id=688913
2012-12-05 18:42:08 +01:00
525d3c2619 altTab: Factor out thumbnail creation
https://bugzilla.gnome.org/show_bug.cgi?id=688913
2012-12-05 18:42:08 +01:00
aba46720c0 altTab: Rename AltTabPopup to AppSwitcherPopup
We will add support for a window-based popup in addition to the
current application-based one, so use a more descriptive name.

https://bugzilla.gnome.org/show_bug.cgi?id=688913
2012-12-05 18:42:08 +01:00
2fb1d707fe altTab: Use 'switch-applications' for app switcher
The Shell's alt-tab popup is application-based, so using the
'switch-windows' keybinding for it never really made sense.
Use the newly added 'switch-applications' keybinding instead.

https://bugzilla.gnome.org/show_bug.cgi?id=688913
2012-12-05 18:42:07 +01:00
dd06aa98ad gnome-shell.doap: belatedly remove me as a maintainer 2012-12-05 07:48:55 -05:00
cfb66ca153 update Punjabi Translation for master 2012-12-05 07:40:56 +05:30
0b4660702b switcherPopup: Add missing Meta declaration
This is used in the edge case if we fail a pointer grab.
2012-12-04 13:18:51 -05:00
9760227c66 Assamese translation updated 2012-12-04 15:55:17 +05:30
5faeaa2028 AppSwitcher: Remove a lost timeout on destroy
Doesn't look harmful but there's no point in running this code after
we're destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=689528
2012-12-04 10:06:37 +01:00
cd58f9f9e5 windowManager: Make use of the switch-panels-backward keybinding
We have it in the schema so there's no reason for it not to work.

https://bugzilla.gnome.org/show_bug.cgi?id=689528
2012-12-04 10:06:37 +01:00
00338bbc4b switcherPopup: Factor out altTab and ctrlAltTab's common code
https://bugzilla.gnome.org/show_bug.cgi?id=689528
2012-12-04 10:06:37 +01:00
31d14a2fb0 panel: Update the hot corner when the panel box allocation changes
This fixes the missing hotcorner in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=689537
2012-12-03 16:09:46 -05:00
49fa0ddebc layout: Use translation_y for panel animation
The anchor point is deprecated.

https://bugzilla.gnome.org/show_bug.cgi?id=689537
2012-12-03 16:06:34 -05:00
d50c3e6c67 panel: Don't create a menu for the ActivitiesButton
A "dontCreateMenu" item was created for the lock screen; we should
just use that instead of having a hacked up menu.

https://bugzilla.gnome.org/show_bug.cgi?id=689537
2012-12-03 16:06:34 -05:00
b39f56e813 messageTray: Remove an unused instance variable 2012-12-03 16:06:34 -05:00
ead0286ca6 st-private: Don't round-trip through a font-string
ClutterText can support a PangoFontDescription directly.

https://bugzilla.gnome.org/show_bug.cgi?id=689568
2012-12-03 15:56:59 -05:00
6eb05af306 workspacesView: Restore activation of (empty) workspaces
Clicking empty workspaces to leave the overview was broken by
commit 830e701d13, restore the previous behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=689552
2012-12-03 19:40:29 +01:00
6b1e632621 NetworkMenu: don't notify for failed connections if cancelled by the user
If the user cancels the secret dialog, the NM will report the connection
failure, but we should not notify it as it is a user-initiated action.

https://bugzilla.gnome.org/show_bug.cgi?id=684823
2012-12-03 19:02:16 +01:00
29cb10fed8 iconGrid: Handle preferred height requests for infinite widths
Request enough height to fit all children in a single line instead of
requesting 0.

https://bugzilla.gnome.org/show_bug.cgi?id=679168
2012-12-03 12:43:46 -05:00
a88433dba6 st-private: Fix style 2012-12-02 20:11:36 -05:00
7e5f1fe411 st-private: Don't create attr lists if we don't need them
Decorations are fairly uncommon in gnome-shell, so it's
worthwhile to avoid effort creating empty attr lists. This
can also help prevent a relayout.

https://bugzilla.gnome.org/show_bug.cgi?id=689400
2012-12-02 20:11:10 -05:00
00c78d33e4 MessageTray, ScreenShield: adjust missed message counter
Fix counter size and position and add some padding in
ScreenShield notifications to not obscure the items below
the missed message counter.

https://bugzilla.gnome.org/show_bug.cgi?id=686472
2012-12-02 23:20:10 +01:00
50fbf9982e MessageTray: clean-up chat timestamps
Change the text for design reasons and correct some English issues
in the timestamp string.

https://bugzilla.gnome.org/show_bug.cgi?id=680989
2012-12-02 23:12:28 +01:00
71ad39b6e3 Add a setting for the default state of 'Remember Password'
https://bugzilla.gnome.org/show_bug.cgi?id=688039
2012-12-02 23:01:56 +01:00
3d329cdf2d Updated Tamil translation 2012-12-02 17:10:13 +05:30
21af5c8f73 Added Norwegian bokmål translation 2012-12-01 11:33:46 +01:00
716d7bb93e shell-app-usage: Fix several problems in xml parsing
Coverity rightly complained about the context < 0 comparison.
In addition, context was shadowing the parameter of the same
name, and the loops over the attributes were unnecessarily
running all the way.

https://bugzilla.gnome.org/show_bug.cgi?id=689325
2012-11-30 20:16:50 -05:00
98f4b99446 overview: Remove custom swipe scrolling implementation
https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-30 16:03:35 -05:00
830e701d13 workspacesView: Don't use the overview swipe scrolling system
Switch to a ClutterPanAction instead too.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-30 16:03:34 -05:00
57d9e7d5aa workspacesView: Clean up scroll code a bit
There's no code path that results in us not animating.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-30 16:03:34 -05:00
5fc16bb05b searchDisplay, appDisplay: Use ClutterPanAction for re-swipe scrolling
The sooner we can kill off the custom overview swipe scroll code, the
better.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-30 16:03:34 -05:00
cb08bd2e2e altTab: Minor code cleanup
https://bugzilla.gnome.org/show_bug.cgi?id=688913
2012-11-30 20:04:22 +01:00
961dba7faa MessageTray: don't close the tray when interacting with the right click menu
If the chosen action is not open, the tray should not be closed, to
let the user further interact with it (for example to mute or remove
more sources)

https://bugzilla.gnome.org/show_bug.cgi?id=689296
2012-11-30 18:43:57 +01:00
41f933b89e MessageTray: fix notification height expansion
MessageTray._tween removes all tweens now, so it removes also
those setting the height to expanded for critical notifications.

This is a regression from 1a27d7dfc0

https://bugzilla.gnome.org/show_bug.cgi?id=689295
2012-11-30 18:42:18 +01:00
d4dc1c87c5 dbus: Add a read-only org.gnome.Shell.Mode property
This is meant to expose the global.session_mode to applications such
as the gnome-tweak-tool, which would need it to differentiate between
the vanilla GNOME Shell mode and the fallback replacement mode.

https://bugzilla.gnome.org/show_bug.cgi?id=689300
2012-11-30 17:28:34 +01:00
e58fbeea17 appDisplay: don't increment counter if we didn't add a category
Or we'll later try to jump to the wrong category when clicking on it.
2012-11-29 19:21:41 -05:00
2492dc50db scroll-bar: Remove jitter on the scroll bar when moving the mouse
This was due to incorrect pixel clamping, which bounced the height
of the actor between values. Just remove pixel clamping, as Clutter
will correctly do it for us.

https://bugzilla.gnome.org/show_bug.cgi?id=689243
2012-11-29 16:43:47 -05:00
b4f5f1e461 scroll-view-fade: Fade gradients when near edges
Rather than sharply transitioning to gradients, fade them out when
near the edge of the scroll view.

https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
69347fff09 scroll-view-fade: Only calculate the ratios if they're needed
This prevents some calculations being done for poor drivers with
bad optimizers.

https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
5c439f4e9c scroll-view-fade: Do the offset math in the shader
This doesn't (or shouldn't) change the visual appearance of the fade
effect, but does do all the testing math inside the shader, rather
than on the CPU. This will make fading the offset much easier in
the future.

https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
c84236ed73 scroll-view-fade: Use GLSL 1.20
GLSL 1.20 is a better language, and we'll rely on it in future updates.
This doesn't have any additional constraints, since GLSL 1.20 was
standardized before GLSL-supporting drivers came out.

https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
ae1a3a0cb2 scroll-view-fade: Clean up GLSL
Basic cleanup of what we're doing already. This moves a bunch
of the "inside the fade area" checks to the top, before doing
any calculations.

https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
b3fea016f1 scroll-view-fade: Put the shader in another file
This doesn't make any changes to the shader outside of adding
a header; it simply makes changes in the future easier to edit.

https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
7c93639e59 scroll-view-sizing: Enable vfade by default
https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:09 -05:00
affcd5c7de scroll-view-sizing: Add a lot more boxes
https://bugzilla.gnome.org/show_bug.cgi?id=689249
2012-11-29 16:17:08 -05:00
e00eb06f66 overview: Handle sessionMode.hasOverview changes
Currently we assume that either the initial sessionMode will have
the overview or none of the pushed modes - starting without the
overview and pushing a mode that adds it fails spectacularly.
However this is exactly what we are going to do when loading external
modes asynchronously - we'll initially use the default mode while
the modes are loading, and switch to the mode passed on the command
line when finished. So make sure that the overview UI gets initialized
properly in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=689304
2012-11-29 21:31:06 +01:00
5ecc204d57 main: Fix signal name
It's SessionMode::updated, not SessionMode::update ...
2012-11-29 21:26:45 +01:00
2a5eed1eb4 viewSelector: Ignore key-presses during non-overview modals
Since commit 0c807bddaf, the run dialog no longer handles Escape
key presses itself but uses the action key mechanism of modal dialogs.
As the latter uses key-release events, our own handling of the Escape
key runs on key-press.
Fix this by bailing out early if anything has pushed a modal in addition
to the overview (like system modals, looking glass, ...).

https://bugzilla.gnome.org/show_bug.cgi?id=688196
2012-11-28 21:15:09 +01:00
d517c13d7a Telepathy: ignore errors from ack_all_pending_messages()
Invalid ID errors from that function are normal, because the set
of IDs to acknowledge may not match the set in the connection manager
due to race conditions.
This is also what empathy does.

https://bugzilla.gnome.org/show_bug.cgi?id=683449
2012-11-28 17:46:39 +01:00
bb88265d78 workspacesViews: Update new padding rules for workspacesOnlyOnPrimary
Tim Lunn fixed this for the !workspacesOnlyOnPrimary case, but not the
other.
2012-11-27 17:46:53 -05:00
858694f4cc wanda: Update code to use Panel.Animation
This simplifies our code tremendously.
2012-11-27 13:25:18 -05:00
a46321baa0 panel: Make Animation visible by default
None of the other widget actors hide themselves by default;
that's a GTK+ thing.
2012-11-27 13:25:18 -05:00
9808e8ab0d panel: Split off Animation code from AnimatedIcon
This is to share with wanda.
2012-11-27 13:16:30 -05:00
7bd7b53845 panel: Remove a bit of duplicated code
The play() method does what we want here.
2012-11-27 13:16:30 -05:00
056cfc9dc6 wanda: fix a refactor fallout
load_sliced_image() would need an additional parameter, but fold the
notify::mapped callback into the load callback while we're at it.
2012-11-27 12:56:40 -05:00
b7b60d103e Assamese translation updated 2012-11-27 14:41:28 +05:30
14fd0eb73e StWidget: don't dispose the theme node when destroyed
Theme nodes are interned and shared with other widgets, so they cannot
be disposed, otherwise we blow useful resources, and in particular we
break the parent-child chain.

https://bugzilla.gnome.org/show_bug.cgi?id=689029
2012-11-26 22:59:22 +01:00
ca73017100 extensionSystem: Don't spam the error log with OUT_OF_DATE errors
Nobody cares

https://bugzilla.gnome.org/show_bug.cgi?id=689108
2012-11-26 15:11:58 -05:00
123fb350ce screenshot: don't fire flash if we failed to take picture
https://bugzilla.gnome.org/show_bug.cgi?id=688004
2012-11-26 14:09:07 -05:00
1a27d7dfc0 MessageTray: remove all tweens when tweening for state parameters
MessageTray._tween sets the state variable to the in-progress value,
so it must be sure that at the end of the animation the value will
be the corresponding final and nothing else will happen in between.

https://bugzilla.gnome.org/show_bug.cgi?id=683986
2012-11-26 18:16:50 +01:00
b0c6d44515 Theme: improve notification scrollbar appearance
Message tray: modify bubble scrollview notification padding to
have the same padding at right, bottom, top and left since
having different padding make scrollbar looks missaligned.
Also adjust border radius of bubble to not clash the scrollbar.

https://bugzilla.gnome.org/show_bug.cgi?id=688393
2012-11-26 13:53:23 +00:00
6092e01428 Telepathy: consolidate and improve connection notifications
Use the empathy icon and name instead of the error icon, use
a friendlier title and remove the Reconnect button.

https://bugzilla.gnome.org/show_bug.cgi?id=687213
2012-11-26 13:49:54 +00:00
e20ff5ae45 Assamese translation updated 2012-11-26 15:51:37 +05:30
621a0d70e2 Updated Malayalam translations 2012-11-26 15:03:03 +05:30
855b238ec5 Make it possible to not show the users name permanently
In particular on the lock screen, this can be a privacy issue.
https://bugzilla.gnome.org/show_bug.cgi?id=688577
2012-11-24 17:11:19 -05:00
96f44e1959 WindowOverlay: animate the close button together with the border
Since the introduction of overlay hover borders, there has a been
a timing disconnection between hiding the border and button, and
this creates noise and reduces the effect of the window+overlay
as a single unit.
Solve that by animating the close button too, so that the two actors
are shown and hidden always at the same time.
Also, consolidate the code to make it clear to future authors that
those two items need to stay coordinated.

https://bugzilla.gnome.org/show_bug.cgi?id=688966
2012-11-24 18:55:47 +01:00
242dc8cddd Revert "configure.ac: relax NetworkManager requirement to 0.9.6"
This reverts commit b8a2004872.
2012-11-24 02:03:18 +09:00
b8a2004872 configure.ac: relax NetworkManager requirement to 0.9.6
0.9.7 is an unreleased version and Its actually not needed
2012-11-24 01:40:24 +09:00
63f08bf2c2 Assamese translation updated 2012-11-23 17:19:28 +05:30
4734a9ac18 Updated Hebrew translation. 2012-11-23 10:14:22 +02:00
81cd1e6c40 MessageTray: be explicit about removing tweens
Turns out that tweener has a very complex logic to decide when a new
tween on the same properties overrides completely the old, and unfortunately
what we were doing was not enough in all cases.
Just be explicit, and don't let anything else mess with the state.

https://bugzilla.gnome.org/show_bug.cgi?id=688895
2012-11-22 21:36:17 +01:00
0b9cdea7d2 Updated Dutch translation 2012-11-22 13:37:24 +01:00
f63fceb2ea workspacesDisplay: add spacing around the workspacesView
On additional monitors the workspacesView takes up the entire monitor
and in some cases windows in overview can end up hard against the
edge of the monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=688133
2012-11-21 20:02:38 +01:00
f0f7165ab6 theme: Style the panel differently according to mode
https://bugzilla.gnome.org/show_bug.cgi?id=684573
2012-11-21 13:10:46 +01:00
2511f60d39 sessionMode: Add panelStyle property
The panel should change appearance according to the sessionMode,
so add a new panelStyle sessionMode property which allows to
specify a mode specific style class for the panel actors.

https://bugzilla.gnome.org/show_bug.cgi?id=684573
2012-11-21 13:10:46 +01:00
c0f868dd56 panel: Remove .in-overview style class
The panel used to be styled differently in the overview, but
nowadays this is just a left-over.

https://bugzilla.gnome.org/show_bug.cgi?id=684573
2012-11-21 13:10:46 +01:00
a112bfdaa2 panelCorner: Only overlap panel if necessary
The panel corners overlap the panel in order to hide the underline
used for active buttons where it is supposed to arc downwards
following the roundness of the corner.
Unfortunately this prevents us from using a transparent panel background,
as the overlapped area ends up with the wrong transparency. Work around
this limitation by only overlapping the panel if there is a visible
border.

https://bugzilla.gnome.org/show_bug.cgi?id=684573
2012-11-21 13:10:46 +01:00
4535a70f08 Block cancellation of the unlock dialog when dragging
Pressing esc while the mouse is down should not make the curtain fall,
otherwise a gray screen results.

https://bugzilla.gnome.org/show_bug.cgi?id=686800
2012-11-21 12:35:55 +01:00
b59529e579 MessageTray: fix closing the right click menu
We were trying to disconnect a signal we never added.

https://bugzilla.gnome.org/show_bug.cgi?id=688771
2012-11-21 12:29:43 +01:00
393c23820a unlockDialog: set password char on verif. failure
Commit c3cab28 removed bits setting the password char that was used to
allow typing the password after a failure but before the first question
for the new attempt came.

Without that code, in complex PAM setups you can end up with a visible
password.

https://bugzilla.gnome.org/show_bug.cgi?id=687113
2012-11-21 00:15:23 +01:00
e6a3958e45 appDisplay: do not show empty categories
Desktop files can specify if the application should only be shown for
specified desktops with OnlyShowIn and NotShowIn directives options.

If a menu category only contained entries for a different desktop, we
were still creating the category.

We now only add a category button if there is at least one application
to be displayed in this category.

https://bugzilla.gnome.org/show_bug.cgi?id=687970
2012-11-20 21:17:57 +01:00
59a7fdd2c9 Login: add a spinner for better process indication
We need to do a better job of indicating login process. This can
sometimes take a few seconds (particularly if you get your password
wrong): we need to give better feedback of what's going on.

This adds a spinner next to the login button if the authorization takes
some time.

https://bugzilla.gnome.org/show_bug.cgi?id=687113
2012-11-20 21:08:38 +01:00
c3cab28c9b Login: sensitivity fixes
The login dialog had these issues:
  - the entry was not really disabled, you could still edit text
  - the sensitivity state was not reset on verification failure
  - the session list was not disabled

The unlock dialog had these issues:
  - "Login as another user..." was not insensitive
  - redundant password char setting, overwriting the one given by the
    question

The entry insensitive style was also wrong.

https://bugzilla.gnome.org/show_bug.cgi?id=687113
2012-11-20 21:08:37 +01:00
4c55a6f436 modalDialog: do not launch disabled button actions
The "Sign In" button of the login dialog has its look disabled when the
entry is empty, but it can still be triggered by the Enter key.

This fixes the modal dialog so it does not trigger the action of an
insensitive button, and also means we do not need to connect to the
"activate" signal of the entry anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=687113
2012-11-20 21:08:37 +01:00
c10e4c3117 modalDialog: give more control over the layout
Make the button layout public for callers to be able to have more
control over like adding custom widgets. Also, the clearButtons and
addButton methods are added as convenience for the most frequent usage.

https://bugzilla.gnome.org/show_bug.cgi?id=687113
2012-11-20 21:08:37 +01:00
3b70094151 MessageTray: fix popping up after there were modals
Open a modal dialog, try to open the message tray -> no effect, the message
tray is blocked by the dialog.
Close the dialog, try to open the message tray by pointer -> still
no effect, because the old timeout id was not cleared the first time,
so the dwell callback thinks the tray is about to open.

https://bugzilla.gnome.org/show_bug.cgi?id=688750
2012-11-20 20:04:30 +01:00
a370697385 Workspace: Highlight window clone and caption when hovered
Windows in the overview should be highlighted when hovered, to indicate
they are an active target.

Based on a patch by Marc Plano-Lesay <marc.planolesay@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=665310
2012-11-20 18:01:11 +01:00
8a7c0313f6 Layout: show the OSK on the monitor where the focused window lives
In multimonitor scenarios, it makes sense to show the OSK close to
the window that will actually receive keystrokes.

https://bugzilla.gnome.org/show_bug.cgi?id=685856
2012-11-20 17:57:24 +01:00
00201f7e6c networkAgent: ensure auto-register is set when the component is enabled
Setting auto-register to true launches the initial registration, and will
afterwards re-launch the agent registration if NetworkManager gets restarted.

When the component is disabled we'll first disable auto-registration, and only
then request to unregister.

https://bugzilla.gnome.org/show_bug.cgi?id=688379
2012-11-20 14:00:03 +01:00
5e3111bad8 ctrl-alt-tab: use better icons
The top panel and message tray icons were by default a gnome foot and
are replaced by better ones. The applications icon is now using the
symbolic apps icon of the dash, and the windows icon is also improved.

https://bugzilla.gnome.org/show_bug.cgi?id=641303
2012-11-20 11:42:04 +00:00
a327c10c60 Add 'No Messages' label when message tray is empty
To avoid confusion in new users, a 'No Messages' label is shown when messages
tray is empty.

https://bugzilla.gnome.org/show_bug.cgi?id=686738
2012-11-20 09:36:47 +00:00
938bc07e3c Fixed some errors in Russian translation 2012-11-20 11:47:45 +04:00
d053d45a6d messageTray: don't accidentally shift the tray around in the overview
https://bugzilla.gnome.org/show_bug.cgi?id=688422
2012-11-20 01:06:47 +01:00
5200da6eec Bump version to 3.7.2
Update NEWS
2012-11-20 00:01:40 +01:00
b0523860d9 build: Actually remove shell-screen-grabber.[ch]
Commit 7f8bfcc939 removed the code, but not the actual files,
breaking make distcheck.
2012-11-20 00:01:39 +01:00
1a1215527f messageTray: restore toggle tray in normal mode (non overview)
https://bugzilla.gnome.org/show_bug.cgi?id=688507
2012-11-20 00:01:39 +01:00
360c018c9e calendar-server: Remove useless g_type_init 2012-11-20 00:03:13 +01:00
7bed964ab2 ScreenShield: unbreak blurring the background
It was missing a uniform, so it had no effect besides desaturation.

https://bugzilla.gnome.org/show_bug.cgi?id=682536
2012-11-19 20:13:36 +01:00
989d0a5682 bluetooth: add translation hints
A couple of translations were hard to translate.

https://bugzilla.gnome.org/show_bug.cgi?id=638351
2012-11-19 19:56:08 +01:00
b121c25184 MessageTray: restore opacity when expanding a notification
MessageTray tweens both opacity and y to hide or show _notificationWidget,
but only y when expanding it. This means that an existing tween to hide
the notification will continue running, clearing the notification state.
If the hiding one completes before the showing one, the onComplete handler
will throw an exception (because the notification was nullified) and
therefore break the state tracking.

https://bugzilla.gnome.org/show_bug.cgi?id=683986
2012-11-19 19:20:31 +01:00
e0d127b3e4 shell-recorder-src: Set frame duration
We where not setting a duration for the frames, which caused the resulting videos to
have a broken header.

Fix that by making the source a live source and setting the correct frame duration.

https://bugzilla.gnome.org/show_bug.cgi?id=688487
2012-11-19 19:17:31 +01:00
a0c56c74e1 test-recoder: Use webm file extension
This matches our default pipeline.

https://bugzilla.gnome.org/show_bug.cgi?id=688487
2012-11-19 19:17:23 +01:00
f4b61a7f24 recorder: Show icon and indicator on the primary monitor
https://bugzilla.gnome.org/show_bug.cgi?id=688470
2012-11-19 19:16:24 +01:00
b2400fb883 build: require gsettings-desktop-schemas 3.7.2
For shell search provider settings schema.
2012-11-19 12:01:13 -05:00
f25832d1b6 view-selector: add support for disable-external search setting
https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-19 11:45:21 -05:00
cf363171aa remote-search: apply sort-order from GSettings
Sort providers according to the GSettings state, and make sure to reload
them as soon as the sort order changes.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-19 11:45:21 -05:00
38c8569d16 remote-search: restructure remote search provider loading process
Instead of adding search providers to the system as we find them, wait
until we loaded information from all the directories, and then add all
providers at once.
This will be useful when we will sort the providers information
according to the sort order saved in GSettings.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-19 11:45:21 -05:00
9791d15f39 view-selector: filter out disabled search providers
If the added search provider has an appId in the list of the disabled
search providers settings, ignore it.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-19 11:45:21 -05:00
80e7f5832b search: add API to get a list of remote providers
This will be used to reload them in case the configuration changes.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-19 11:45:21 -05:00
6e46ddaad3 search: propagate GAppInfo to SearchProvider
Save the GAppInfo in the provider object; this will be used when
filtering.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-19 11:45:21 -05:00
8499e4aab2 [l10n] Updated Estonian translation 2012-11-19 16:41:52 +02:00
5eae1851a1 Login dialog - tweak the user name text shadow
The shadow under the user name should suggest that the light source
is directly above.

https://bugzilla.gnome.org/show_bug.cgi?id=688557
2012-11-17 23:54:35 +00:00
c48a246ccb panel: programmatic anim. control of AnimatedIcon
The AnimatedIcon does not have an API for controlling the animation but
relies on the :visible property changes to start and stop a timeout used
to update the frame.

This has the inconvenient of having a side effect when visible is set to
true multiple times, and is not really the API expected from such
component. Also, there is a race if it is displayed before the images
are loaded: there is no child yet and thus we get this._frame = NaN
which leads to a crash.

Switch to a play/stop API instead, and add a load event callback to the
TextureCache.load_slice_image to exactly know when we can start using
the images.

https://bugzilla.gnome.org/show_bug.cgi?id=687583
2012-11-17 22:26:55 +01:00
f084011a61 viewSelector: Make toggle-application-view binding available in overview
https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:52 +01:00
bd40cf194c recorder: Make toggle-recorder action available in the overview
There's not really a good reason to not allow starting a recording
in the overview ...

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:51 +01:00
2434af7e8a messageTray: Make toggle-message-tray available when up
It makes so much sense that the setting even has 'toggle' in its name.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:51 +01:00
ced7fa9f01 Add screenshield and unlock dialog to ctrl-alt-tab
As we now allow the ctrl-alt-tab popup on the lock screen, it should
be possible to navigate back from the top bar, so add the corresponding
elements to the switcher.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:51 +01:00
28b559e812 windowManager: Replace sessionMode.allowKeybindingsWhenModal
The original condition the property was based on was added to make
the a11y switcher available in the login screen, though it did never
work properly - after popping up the switcher, additional tab key
presses were ignored. As we are now able to filter bindings much more
selectively, we can simplify the check and drop the sessionMode property.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:51 +01:00
76d776245b windowManager: Use generic filter mechanism for all keybindings
With the new flexible system in place, there's no point explicitly
hardcoding some built-in keybindings; just use the generic mechanism
for everything.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:51 +01:00
0d9f70492e windowManager: Add a generic mechanism for filtering keybindings
Currently we hardcode the set of keybindings that are available in the
overview; add a generic mechanism to specify in which KeybindingModes
a keybinding should be available.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:52:51 +01:00
b58f502dd6 main: Add optional keybindingMode parameter to pushModal()
For now we just use it to assign an identifier to modal modes in
which we want to allow some keybindings, but we don't use it for
any actual filtering; we'll start doing this shortly.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:44:22 +01:00
5f367248c5 grabHelper: Support optional parameters to pushModal()
https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:44:22 +01:00
c2065cc3e2 main: Use Params for optional parameters to pushModal()
As the number of optional parameters grows, it gets more convenient
to use Params instead of passing in a lot of undefined/null/0 values.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:44:22 +01:00
034408971d windowManager: Implement keybinding_filter hook
We are currently using a hack to allow a select set of keybindings
in the overview. Implement the new MetaPlugin keybinding_filter
hook, which provides a cleaner way to achieve the same.

https://bugzilla.gnome.org/show_bug.cgi?id=688202
2012-11-17 01:44:22 +01:00
490206b5b2 NetworkMenu: rework multiple NIC support
Remove section titles for ethernet and mobile broadband, and replace
them with device status items that recognize if multiple devices are
installed in the same section, and if so automatically disambiguate.

https://bugzilla.gnome.org/show_bug.cgi?id=677142
2012-11-16 13:52:52 -05:00
d8540819af st-theme-node-drawing: Group multiple cogl_rectangle calls
Calling cogl_rectangles is more efficent then using multiple cogl_rectangle calls.

https://bugzilla.gnome.org/show_bug.cgi?id=688475
2012-11-16 19:28:47 +01:00
d1a9aec526 recorder: Remove dead code
This calls are nops (already called a few lines above) so just remove them.
2012-11-16 19:28:23 +01:00
e4b681a5a5 Updated Galician translations 2012-11-16 18:44:18 +01:00
52036871d1 StThemeNode: add a trivial-case short cut to all comparisons for equality
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-15 17:08:33 +00:00
4fc6a804f5 st_widget_recompute_style: short-circuit if the theme node is the same
It appears to be somewhat common for st_widget_style_changed() to be
called when no style-relevant attributes have, in fact, changed. Now that
we cache theme nodes, we're likely to get the same theme node back from
the cache. If we do, we don't need to waste time asking whether its
geometry and painting are equal to itself: we can just note that nothing
really changed and get on with our lives.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-15 17:08:31 +00:00
08d2ca300a st_theme_node_copy_cached_paint_state: allow self-assignment
If you copy a theme node's paint state into itself, it should be an
inexpensive no-op. What actually happened was that we destroyed the
old paint state, re-initialized to blank, then copied the blank state
back into itself. In the process, we lost (for instance) the textures
for rounded corners.

Until I introduced the texture cache, this never actually happened,
because when st_widget_recompute_style() calls st_widget_get_theme_node(),
we'd always get a fresh theme node. Now, we get a theme node T back
from the cache, notice that paint_equal(T, T) is true, short-circuit
slightly by copying its drawing state into itself, and destroy drawing
state that we still needed.

I'm going to fix this in recompute_style() too, but as a general
principle, self-assignment ought to be harmless.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-15 17:07:42 +00:00
dc2ec0a8f9 Keep similar theme nodes so we don't have to recompute CSS so often
Because we calculate and cache CSS properties once per StThemeNode,
and only a certain set of attributes can affect the CSS properties,
it's advantageous for as many widgets as possible to share a single
StThemeNode. Similarly, if a widget changes state and then changes back
(e.g. gaining and losing the :hover pseudo-class), it should ideally
get its original StThemeNode back again when it returns to the old
state.

Here, I'm using the StThemeContext as the location for a cache.
StThemeNodes are currently never freed: this seems OK for Shell's usage
(a finite number of IDs, classes, pseudo-classes and types).

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-14 19:24:42 +00:00
2cfed952bb Remove unsplit element classes and pseudo-classes
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-14 19:24:31 +00:00
a7da137778 st_theme_node_equal: use split (pseudo-)classes
This is a prerequisite for getting rid of the unsplit versions.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-14 19:24:30 +00:00
5ae2f87ce9 Use pre-split element classes and pseudo-classes to optimize matching
In my testing this cuts the longest time to dispatch(), when showing the
calendar menu for the first time, from 604 to 442 milliseconds,
while reducing additional_selector_matches_style() from 32% to 13% of
CPU time used.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-14 19:24:26 +00:00
c4f6619fbd Store CSS classes and pseudo-classes pre-split in the StThemeNode
Tokenizing every time we want to evaluate CSS seems a poor plan.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687465
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2012-11-14 19:23:40 +00:00
65edbc1424 a11y: also set the WM HighContrast theme when switch is flipped
Now that we have a HighContrast-specific WM theme.

https://bugzilla.gnome.org/show_bug.cgi?id=688256
2012-11-13 11:24:18 -05:00
1f2d7fa28f Bluetooth: Remove ObexFTP functionality
ObexFTP browsing in gvfs is completely broken, and unmaintained.
http://www.hadess.net/2011/11/obexftp-in-gnome-non-update.html

Remove the UI for it. The more adventurous can go and use it
(as long as I don't get the bug reports).

https://bugzilla.gnome.org/show_bug.cgi?id=688160
2012-11-13 17:03:21 +01:00
2407a0c4e2 main: Stop using Metacity's keybinding files
The descriptions for keybindings shared with Metacity are now
duplicated in Mutter, so only use the latter to avoid duplicate
entries in System Settings.

https://bugzilla.gnome.org/show_bug.cgi?id=687672
2012-11-12 21:18:06 +01:00
7f8bfcc939 Remove shell-screen-grabber
The screen grabber was a workaround for an extremely slow path in Mesa
when reading back pixel data from the frame buffer. It was using pixel
buffer objects by directly calling into GL to hit a fast blit path in
Intel's driver. This should no longer be necessary with the latest
Mesa because the normal read pixels path now has a fast path to just
memcpy the data. Using PBOs in that case just adds an extra
indirection because the data is read into an intermediate buffer and
then copied back out again.

We want to be able to remove the dependency on linking against libGL
directly from Gnome Shell because that will not work if Cogl is
actually using GLES. Also libGL includes GLX which means gnome-shell
ends up with a hard dependency on Xlib which hinders the goal of
getting Gnome Shell to be a Wayland compositor.

https://bugs.freedesktop.org/show_bug.cgi?id=46631

https://bugzilla.gnome.org/show_bug.cgi?id=685915
2012-11-12 19:07:57 +01:00
fae4cb9e56 loginDialog: Fix yet another StIconType removal fallout
https://bugzilla.gnome.org/show_bug.cgi?id=688181
2012-11-12 18:45:10 +01:00
063bbb02f2 loginDialog: Remove the correct focus root from ctrl-alt-tab
Commit 3abfcda8b5 fixed the focus root passed to addGroup(),
but left the one in removeGroup() unchanged.

https://bugzilla.gnome.org/show_bug.cgi?id=688181
2012-11-12 18:45:10 +01:00
15e1470c50 polkitAgent: Expand password entry to the full width
Due to an oversight, the width of the password entry is currently
determined by the length of the message description. Fix the flags
so that the entry spans the entire width of the dialog.

https://bugzilla.gnome.org/show_bug.cgi?id=684810
2012-11-12 16:59:12 +01:00
f602993aa9 dash: Disable animations during overview transitions
When updating the dash, we already avoid all animations while the
overview is hidden. However, as we are using Main.queueDeferredWork(),
updates may be deferred up to ~20 seconds while the overview is hidden.
If the overview is entered before a queued update has taken place, it
will be run immediately on map - as the overview is visible by then,
this means animating any outstanding changes.
Work around this by skipping animations during overview transitions as
well.

https://bugzilla.gnome.org/show_bug.cgi?id=686530
2012-11-12 16:59:12 +01:00
271508c0a8 ScreenShield: fix code to detect missing unlock dialog
If the session mode has no locking support, screenshield had code to
unlock automatically, but it did so by checking the return value of
the constructor, instead of checking if the constructor was actually
callable, so it would get a TypeError before reaching the check.

https://bugzilla.gnome.org/show_bug.cgi?id=687708
2012-11-11 19:17:58 +01:00
50f96d1c9c Stop using clutter alpha
It is deprecated.

https://bugzilla.gnome.org/show_bug.cgi?id=688089
2012-11-11 17:13:38 +01:00
809544800b MessageTray: fix reentrancy when calling out to the grab helper
Similar to 683546. I'm not sure where this bug lives, but let's make
the code robust.

https://bugzilla.gnome.org/show_bug.cgi?id=683986
2012-11-10 17:36:00 +01:00
e757b06987 power: indicate 1 hour remaining correctly
Before 60 minutes remaining were displayed
as "0 minutes" now it is "1 hour".

https://bugzilla.gnome.org/show_bug.cgi?id=687958
2012-11-09 17:19:05 +01:00
6f2da1baf1 Updated Hebrew translation. 2012-11-09 11:36:39 +02:00
f30dcad8a7 messageTray: Close the notification on Escape
Now that the notifications can be focused with the keyboard, it's
important we can close the active one also this way.

https://bugzilla.gnome.org/show_bug.cgi?id=652082
2012-11-08 21:19:52 +01:00
7dc235511e messageTray: Add a notification focus keybinding
At the moment, only the mouse can be used to focus and answer a chat
notification.

This adds a new keybinding (defaults to <Super>+n) to focus and expand
the active notification.

https://bugzilla.gnome.org/show_bug.cgi?id=652082
2012-11-08 15:46:16 +01:00
644c210fe2 Rename "System Settings" to "Settings"
"System Settings" has been renamed to "Settings" in gnome-control-center.
See bug https://bugzilla.gnome.org/show_bug.cgi?id=681543

This patch does the same rename in the shell itself, as per

https://bugzilla.gnome.org/show_bug.cgi?id=687738
2012-11-07 16:05:23 +00:00
68e8f98671 .gitignore: Update to ignore the generated manpage 2012-11-07 14:39:28 +01:00
1228db6ac1 unlockDialog: better confirmation button label
If I click on "Not listed?" in the login screen, I come to a username
field with two buttons: "Cancel" and "Sign In".

Clicking on "Sign In" doesn't actually sign me in though - it takes me
to the login entry. It would be better to rename "Sign In" to "Next" for
the username stage, therefore.

Gdm emit a signal to ask a question or a secret, but we can not know if
this is the last authentication question, hence we only use "Sign In"
for secret questions which improve the situation a lot.

https://bugzilla.gnome.org/show_bug.cgi?id=687656
2012-11-07 01:26:35 +01:00
86596749fa Revert "overview: highlight windows on launcher hover"
This reverts commit 76229a3601.

Pushed by accident.
2012-11-07 00:33:32 +01:00
76229a3601 overview: highlight windows on launcher hover
When in the overview, if you move the mouse cursor over one of the
application launchers in the dash, all the unrelated windows are dimmed
both both in the window view and in the workspace view.

It helps to easily understand whether or not there are already opened
windows for this application, and where they are. It can also help in
differentiating the windows in the overview (sometimes the thumbnails
aren't precise enough to easily know which thumbnail belongs to which
application).

https://bugzilla.gnome.org/show_bug.cgi?id=657315
2012-11-07 00:27:31 +01:00
95abdeb919 dash: simplify app retrieval from AppWellIcon
This has also the benefit of getting the application even if it can not
be retrieved through AppSystem, which can happen if the runtime WMClass
does not match the one of the desktop file.

This especially looked wrong with the following commits related to the
bug.

https://bugzilla.gnome.org/show_bug.cgi?id=657315
2012-11-07 00:27:31 +01:00
df0151d338 dash: rename a local variable for clarity
createAppIcon creates an appIcon, not a 'display', which made things
unnecessarily more difficult to understand.

https://bugzilla.gnome.org/show_bug.cgi?id=657315
2012-11-07 00:26:50 +01:00
ee2f12fe81 dash: properly restore item label on popup close
We simply hide the label when the popup is opened instead of relying
on the popup state when the hover state change.

To do this we replace the flag isMenuUp by a 'menu-state-changed' signal
on the AppWellIcon. This simplifies the dash label visibility handling
code that need additional changes for the bug.

https://bugzilla.gnome.org/show_bug.cgi?id=657315
2012-11-07 00:26:11 +01:00
10c104529f remote-search: initialize the DBus proxy asynchronously
Initializing this synchronously means that we will possibly wait for the
process to be auto-activated and answering to our call.
If the process is already running it also might not answer immediately
our request, as it might be doing sync I/O.
The right thing to do is to initialize the proxy asynchronously; there
are try/catch blocks in place for when the object is not available, or
not properly initialized.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-06 18:11:56 -05:00
cbc8ec6508 remote-search: don't use g_file_query_exists()
This is called in the main thread, which we should never block for
synchronous I/O.
Since the operation we're wrapping is async already, just use
g_file_query_info_async() instead.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-06 17:47:48 -05:00
8e7758e280 remote-search: require a DesktopId field in search providers
Remote search providers install an auxiliary keyfile to specify
static information, such as the object path/bus name needed to activate
the binary. Such keyfiles also specify the application the providers
pushes results for; currently, we support two formats for application
information
- two fields, "Title" and "Icon" that specify a (translatable) title and
  an icon name for display
- one field "DesktopId" that specifies the desktop file name of the
  application backing the provider, which obsoletes the previous
  Title/Icon syntax

Since all providers in GNOME use DesktopId now, and we need to ensure a
remote search providers is always backed by an application for future
development, this commit drops the support for the older syntax.

https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-06 17:47:48 -05:00
9aefbd189c view-selector: add missing semicolon
https://bugzilla.gnome.org/show_bug.cgi?id=687491
2012-11-06 17:47:47 -05:00
b9d50584d8 screenshield: use the correct actor for the background
Commit 4fd690333a added the GLSL snippet to
the background actor, but then discarded the newly created actor.
2012-11-06 17:47:13 -05:00
e5f7390c09 ScreenShield: hide the cursor while the lock screen is on
While the screen is locked and the cursor is not moved, the mouse
cursor should be hidden, to indicate the machine is idle.

https://bugzilla.gnome.org/show_bug.cgi?id=682535
2012-11-06 23:10:01 +01:00
797b1ff8bb ScreenShield: account for motion velocity when hiding the lock screen
Switch from a ClutterDragAction to a ClutterGestureAction, that gives
us the velocity of mouse motion at each step, and use it to compute the
animation time for completing the hide gesture.

https://bugzilla.gnome.org/show_bug.cgi?id=682537
2012-11-06 23:04:15 +01:00
09b738045c MessageTray: change height in chat notification to have more context.
https://bugzilla.gnome.org/show_bug.cgi?id=665255
2012-11-06 21:53:28 +00:00
4fd690333a ScreenShield: blur and desaturate the screenshield background
The background is the same as the normal desktop, so we blur and
desaturate it to clearly show that it's not the normal system state.
To do so, we don't use standard ClutterEffects, to avoid the FBO
indirection. Instead, we take advantage of MetaBackgroundActor support
for GLSL code and paint the shaded background texture directly.

https://bugzilla.gnome.org/show_bug.cgi?id=682536
2012-11-06 22:50:10 +01:00
5ef5e25a7f Use "Decline" instead of "Reject" for incoming calls
This makes GNOME Shell more polite
Fixes bug #661194
2012-11-06 20:52:53 +00:00
87e8770cbc loginDialog: support disable-user-list key
In some deployments showing a user list at the login
screen is undesirable.

GDM's fallback login screen has a configuration key:

org.gnome.login-screen disable-user-list false

that causes the user-list to get hidden.

This commit adds similar functionality to the normal,
shell-based login screen.

Based on a series of patches by Marius Rieder.

https://bugzilla.gnome.org/show_bug.cgi?id=660660
2012-11-06 15:05:15 -05:00
cac9d120be loginDialog: hide session list until username is entered
Right now when a user clicks "Not Listed?" they end up
seeing a session list that gets reset after they enter their
username.

This commit hides the session list until the username has
been entered.

https://bugzilla.gnome.org/show_bug.cgi?id=660660
2012-11-06 15:02:36 -05:00
1ae0fadbf4 loginDialog: don't rely on PAM to ask for a username
For the "Not Listed?" case we will need to be able
to identify when the user has entered their username.

Once we have a way of tracking when the username is
entered, we can then defer showing the session list
too early, before the user can reliably pick a
session.

This username tracking will also be important for
implementing a disable-user-list configuration key.
If the config key gets toggled off at runtime, we'll
need to know if we're at a disruptive part of
the authentication process or not, so we know whether
we can can expose the user list right away, or wait
until the authentication conversation finishes.

Right now, we pass null in for an initial username,
and let the PAM machinery ask the user, which means we
have no good way of knowing when the username is entered.

This commit changes the "Not Listed?" code to ask the
user their username up front, before starting the PAM
conversation in much the same way we do if the user
picks a user from the user list.

https://bugzilla.gnome.org/show_bug.cgi?id=660660
2012-11-06 15:02:36 -05:00
65497e089a [l10n] Updated German translation 2012-11-06 20:15:34 +01:00
2d763bd033 st-entry: Change the pointer cursor on enter/leave events
Change the pointer cursor to an i-beam when it is inside the ClutterText.

https://bugzilla.gnome.org/show_bug.cgi?id=687130
2012-11-06 11:47:49 +00:00
4ebf396cf5 a11y: fixing a regression with the accessible name at dash items
After some changes, the tooltip label at the dash is not available
until it is visually shown. As this is not anymore a reliable
source of accessible name, we just set the accessible name
with the string used on that label.

https://bugzilla.gnome.org/show_bug.cgi?id=686583
2012-11-06 10:05:18 +01:00
6faa50d496 Add a --disable-man configure option
OSTree doesn't have DocBook stylesheets, so generating
man pages from xml causes build failures there.
2012-11-05 23:43:03 -05:00
6fcd6298c8 Use the same xsltproc parameters as other modules
Using the same parameters makes sure that the generated man
pages look more or less uniform.
2012-11-05 23:42:52 -05:00
5c16be5dbb Some updates to the man page
Mention relevant files, and how gnome-shell gets started
in the session.

https://bugzilla.gnome.org/show_bug.cgi?id=680601
2012-11-05 19:32:01 -05:00
e3abb6f178 Convert man page to Docbook
This make it easier to update the content and to transform
the man page into other output formats, like HTML.

https://bugzilla.gnome.org/show_bug.cgi?id=680601
2012-11-05 19:31:54 -05:00
70736be4eb mobile-providers: new country-specific type to gather providers
shell_mobile_providers_parse() was returning the country information split
into a hash table with providers and a hash table with country names. This
patch merges both outputs into a single per-country object, so the parse()
method now returns a GHashTable with the following element-type:
   (element-type utf8 ShellCountryMobileProvider>)
This also avoids more complex setups like returning lists inside of hash tables,
which was actually breaking either g-i or gtk-doc.

shell_mobile_providers_parse() was also modified to allow inputting the paths
of the country codes and provider list files to use. If paths are not given, the
default ones will be used. This helps us to provide test files during unit
tests.

Both the findProviderForMCCMNC() and findProviderForSid() methods are exported
out of the GSM and CDMA specific classes, and new unit tests for them are
implemented. Tests can be run manually with:
    $> ./tests/run-test.sh tests/unit/mobileProviders.js

https://bugzilla.gnome.org/show_bug.cgi?id=687356.
2012-11-05 22:20:08 +01:00
1c3e7330f3 ScreenShield: don't rely on gnome-session to hide the lightbox
If we lock before the user becomes active again, gnome-session will never
change presence from IDLE, and thus we'll never hide the lightbox.
Instead, install our own idle monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=687020
2012-11-05 22:04:09 +01:00
6e4c89b310 main: hide the overview on key release
Entering the overview with the overlay key is done on key release but
exiting the overview on key press, which is inconsistent.

This change makes the overview hidden also on key release.

https://bugzilla.gnome.org/show_bug.cgi?id=683024
2012-11-05 21:14:28 +01:00
73b4a0ef5f st-theme: Optimize string_in_list
Rather than using a complicated set of function calls across
library boundaries and our own scanning logic, use strtok(),
which glibc already provides, and is probably much more optimized.

https://bugzilla.gnome.org/show_bug.cgi?id=687465
2012-11-05 15:10:31 -05:00
d88002c4ed Revert "panel: programmatic anim. control of AnimatedIcon"
This reverts commit e04a4c3923.

This commit exposed an already-existing race condition in the panel
animation code that caused the shell to crash for some people.

https://bugzilla.gnome.org/show_bug.cgi?id=687112
2012-11-05 14:31:04 -05:00
025c63c045 Implement non-linear overview shade for background
Adding a radial gradent to the dimming effect gives more depth to
the background.
Shading is computed in a GLSL fragment shader, and uses distance to
center of the screen to interpolate the darkening value to use.

Based on a patch by Pierre-Eric Pelloux-Prayer <pelloux@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=669798
2012-11-05 19:16:53 +01:00
b189cbd46e Updated Norwegian bokmål translation 2012-11-05 19:10:48 +01:00
a21ddb5914 gnome-shell-perf-tool: Fix various problems
* Fix wrong parameter name to on_name_appeared callbacks
* optparse doesn't just leave extra command line arguments, it
  errors out, so don't try to pass through extra arguments -
  instead add explicit passthrough for '--replace'
* Fix usage of Gio.DBusProxy
* Add a default value for --perf so that if it's not supplied
  things don't die with a mysterious error message. (This wasn't
  needed when --perf enabled perf-mode)

https://bugzilla.gnome.org/show_bug.cgi?id=687287
2012-11-05 13:08:25 -05:00
e04a4c3923 panel: programmatic anim. control of AnimatedIcon
The AnimatedIcon does not have an API for controlling the animation but
relies on the :visible property changes to start and stop a timeout used
to update the frame.

This has the inconvenient of having a side effect when visible is set to
true multiple times, and is not really the API expected from such
component.

Switch to a start/stop API instead. Also, update to the first frame at
startup while we are at it, since this is the expected behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=687583
2012-11-05 15:05:14 +01:00
ae0821e07b Disable the login button when there is no input
You can't login until something has been entered in the password field.
We should therefore make the login button insensitive until you have
entered some text.

https://bugzilla.gnome.org/show_bug.cgi?id=687112
2012-11-05 10:17:46 +00:00
a508bece36 Updated Czech translation 2012-11-04 20:00:52 +01:00
2c9969a8f4 Updated Russian translation 2012-11-04 20:49:26 +04:00
dd9fc91f6f keyboard: simplify using Caribou.KeyModel.label
https://bugzilla.gnome.org/show_bug.cgi?id=687242
2012-11-03 08:57:23 +09:00
39d9838cc1 Show feedback notifications when the user is busy
Notifications that are created in response to direct user actions like
"is ready" or "'foo' has been removed from favorites" should always be
displayed even though the user has marked him/herself busy.

https://bugzilla.gnome.org/show_bug.cgi?id=662900
2012-11-02 19:25:26 +01:00
1397c7c624 build: Add missing file
Fix distcheck breakage from commit 687e1eabed.
2012-11-02 16:56:42 +01:00
c09fcba94f layout: Remove message tray pointer barrier
The barrier was introduced to make the message tray hot corner
usable in multiple monitor setups. With the hot corner gone in
3.6, the pointer barrier doesn't make much sense anymore, so
remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=687457
2012-11-02 16:29:37 +01:00
c77b38fc4f telepathyClient: Fix auto-scroll to bottom
Instead of keeping track of the old adjustment.upper keep track of the
old adjustment.value that corresponded to the bottom scroll position.

This fixes the integrated chatview not always scrolling to the bottom
by removing the assumption that page_size is constant between updates,
which is not the case as the view is presented in various different ways.

https://bugzilla.gnome.org/show_bug.cgi?id=686571
2012-11-02 12:06:52 +01:00
aef9b733e5 loginDialog: drop spurious parameter
_onNotListed had an unusued, incorrect parameter.

This commit drops it.

https://bugzilla.gnome.org/show_bug.cgi?id=660660
2012-11-01 14:24:45 -04:00
348208617b Use the correct icon in the restart dialog
It currently uses system-shutdown-symbolic. view-refresh-symbolic
is a better fit in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=670687
2012-11-01 16:21:52 +00:00
2c34c8e20f Overview search box is too subtle
When it isn't focused, the search box can be quite hard to see.

The text/icon/border color is changed to be brighter in order to increase
contrast with the dark background and this works well with various
wallpapers.

https://bugzilla.gnome.org/show_bug.cgi?id=686479
2012-11-01 11:32:40 +00:00
d19fa731d6 Updated Polish translation 2012-10-31 19:15:34 +01:00
59bb1cc387 Add a setting to force the 'Log out' menuitem
I've heard quite a bit of feedback from people who want to log out,
even if they are the sole user on their system. It doesn't seem worth
alienating them over this; so add a setting to make the 'Log out' item
always show up.
https://bugzilla.gnome.org/show_bug.cgi?id=686057
2012-10-31 12:46:49 -04:00
56909d0646 Show 'Log out' in more situations
When the current user is a remote account, or a we are logged in
as root, we should always show 'Log out'.

https://bugzilla.gnome.org/show_bug.cgi?id=686736
2012-10-31 12:45:08 -04:00
04da29c939 appMenu: Update on icon theme changes
While we recreate icons on style changes elsewhere, the faded
icon in the application menu will stick around after icon theme
changes until another application is focused.

https://bugzilla.gnome.org/show_bug.cgi?id=687224
2012-10-31 00:06:46 +01:00
307f7a3024 IM status menu: adjust the combo popup background
The transparent background for available/unavailable IM status menu
makes the text difficult to read.

Simplifies that by using the default combo-popup background instead of a
custom one.

https://bugzilla.gnome.org/show_bug.cgi?id=658091
2012-10-30 22:51:50 +00:00
e80bfa39f5 userMenu: Use "offline" instead of "unavailable"
https://bugzilla.gnome.org/show_bug.cgi?id=687226
2012-10-30 23:01:22 +01:00
29714922ea calendar: Drop unnecessary libedataserverui dependency
The libedataserverui dependency is a relic of the old E-D-S API.
As of 3.6.0, E-D-S now centralizes authentication prompts so clients
don't have to display their own.  This also allows trading the GTK+
main loop for a plain GMainLoop in gnome-shell-calendar-server.c.

https://bugzilla.gnome.org/show_bug.cgi?id=687189
2012-10-30 14:18:39 -04:00
88192114ac NetworkAgent: cancel requests when disabling component
When the NetworkAgent is disabled (for example because the lock screen
is being activated), cancel all modal dialogs.

https://bugzilla.gnome.org/show_bug.cgi?id=685239
2012-10-30 16:34:13 +01:00
9d78208b76 NetworkMenu: don't use a global switch for all VPN connections
Stop pretending that VPN is a NMDevice, and split the useful bits into
a NMConnectionBased interface.
Make each connection have its own switch menu item and handle its own
status, and remove the VPN section title, which is no longer needed.

https://bugzilla.gnome.org/show_bug.cgi?id=682929
2012-10-30 16:08:33 +01:00
d817bf0395 theme: standardize the run dialog text styles a bit
Use the standard color for dialog headings, and use the standard
text style for the entry field. These tweaks make the dialog easier
to read.

https://bugzilla.gnome.org/show_bug.cgi?id=687127
2012-10-30 15:50:05 +01:00
4d51056226 runDialog: Remove "Run" button again
While not in the mockups, it was introduced during review of commit
0c807bddaf after discussion on IRC, but the designers disagree;
remove it again.

https://bugzilla.gnome.org/show_bug.cgi?id=687127
2012-10-30 15:50:05 +01:00
a607174a25 runDialog: Add entry to focus chain
Currently the entry takes the intial key focus, but is not actually
part of the focus chain. Fix that, even though keynav does not work
too well for the dialog anyway, due to the entry consuming tab for
command completion.

https://bugzilla.gnome.org/show_bug.cgi?id=687127
2012-10-30 15:50:05 +01:00
37d6a624b7 Improve the button insensitive style
The current insensitive style for buttons needs to be improved. Right
now we just change the text color: this doesn't make it clear that the
button is actually insensitive.

Instead of just changing the text color, we make the button background
almost transparent. We also make the text color the same as the border
color, use a thinner border.

This patch also simplifies some border rule overwrites to emphasis
only the border width is changed on focus, and makes the button look
closer to the mockups.

https://bugzilla.gnome.org/show_bug.cgi?id=687110
2012-10-30 12:35:48 +00:00
0c807bddaf runDialog: Better match style of other modal dialogs
Update the run dialog to
 - use a proper title
 - use dialog buttons
 - use the standard entry style

https://bugzilla.gnome.org/show_bug.cgi?id=687127
2012-10-29 19:12:12 +01:00
a0470bfc66 UnlockDialog: clear the password on failure
It is wrong, and the user can't correct it because it's obfuscated.
Just let him type it again.

https://bugzilla.gnome.org/show_bug.cgi?id=687132
2012-10-29 17:54:12 +01:00
b9463d23e8 ShellUserVerifier: fix fail counter
If it is updated after checking, it counts the number of failures
not including the current one, so it allows one extra attempt. Instead,
by updating it before checking, we get the expected result of dropping the
curtain at the third password.

https://bugzilla.gnome.org/show_bug.cgi?id=687132
2012-10-29 17:54:12 +01:00
04debd1623 LoginDialog: clear previous auth failed messages when trying again
When the user has the entered the password for the second time
and clicked OK, clear messages from the previous attempt, so any
new failure is shown clearly.

https://bugzilla.gnome.org/show_bug.cgi?id=687132
2012-10-29 17:54:11 +01:00
9d31576cf5 App search: Match GenericName too
This is making shell search results more useful in many cases,
such as 'web', 'browser', spreadsheet'.
https://bugzilla.gnome.org/show_bug.cgi?id=687121
2012-10-29 11:24:36 -04:00
8daca28a90 Updated Slovak translation 2012-10-28 19:50:05 +00:00
9899604261 Updated Slovak translation 2012-10-28 18:27:51 +00:00
687e1eabed Overview: Resize the window title labels on content change
Reposition the window overlay when the title changes, using the current
transformed size of the window clone.
Includes a test that changes title to a string of random length every 3 seconds.

Based on a patch by Alex Hultman <alexhultman@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=620874
2012-10-27 18:18:48 +02:00
eb09f34114 recorder: save recorded video as recent item
Often the first thing a user wants to do after making a recording
is post it somewhere.

This commit adds the video to recently used items, so that it shows
up prominently in open file choosers.

https://bugzilla.gnome.org/show_bug.cgi?id=680647
2012-10-26 13:29:30 -04:00
fbeb446ed7 recorder: rename "filename" property to "file-template"
The filename property is actually a template string with
substitution variables, not a filename.

This commit renames for clarity.

https://bugzilla.gnome.org/show_bug.cgi?id=680647
2012-10-26 13:29:30 -04:00
92033ce0f5 recorder: keep test-recorder alive until done recording
Recording continues for some time after the recorder object
is closed, since closing isn't a synchronous operation.

This commit defers quiting the test-recorder application until
the recording is finished.

https://bugzilla.gnome.org/show_bug.cgi?id=680647
2012-10-26 13:29:30 -04:00
9171bab5e5 recorder: keep recorder object alive until pipeline finishes
We want to make sure the recorder isn't finalized until the
saved recording hits disk.  This means the pipeline object needs
a hard reference on the recorder.

https://bugzilla.gnome.org/show_bug.cgi?id=680647
2012-10-26 13:29:30 -04:00
f9819eb7b0 recorder: Clean up stage lifetime handling
The stage is a floating object. We don't own a reference
to it, so we shouldn't unref it.

This commit removes the erroneous unref call and makes sure
we call clutter_actor_destroy on the stage when we're done
with it.

https://bugzilla.gnome.org/show_bug.cgi?id=680647
2012-10-26 13:29:30 -04:00
85728f0d15 layout: Use a MetaBackgroundActor, not a custom ClutterX11TexturePixmap
While looking at how the plymouth implementation was built, I was so
short-sighted and focused on the string "_XROOTPMAP_ID" that I didn't
realize it was the name of the standard background on the root window.
Remove our own implementation, and switch to using a standard mutter
MetaBackgroundActor.

https://bugzilla.gnome.org/show_bug.cgi?id=682428
2012-10-26 11:54:25 -04:00
9396849d56 message-tray: Restore Fittsability of summary items
The reactive area of tray items should extend to the screen edge. This
regressed when implementing the new tray design, make it work again.

https://bugzilla.gnome.org/show_bug.cgi?id=686474
2012-10-26 16:32:07 +02:00
6f5e5672bb panelMenu: Fix exception when destroying menuless button
There's explicit API to create PanelMenu.Buttons with no menu, so
guard against this case in destroy().

https://bugzilla.gnome.org/show_bug.cgi?id=686763
2012-10-26 15:49:26 +02:00
b936e60876 screenShield: Tweak curtain animation timings
Rationale:
 - Getting something out of the way should be quick;

 - Very few things in the real world move linearly so, linear
   animations, especially for something as big and visible as this,
   felt too artificial;

 - Moving the curtain out should start slower to make it feel like
   having weight (it fills the whole screen after all) but quickly
   accelerate towards the end to make it snappy too.

https://bugzilla.gnome.org/show_bug.cgi?id=686745
2012-10-26 12:56:17 +02:00
fa4bd91213 build: Stop linking gnome-desktop
Since commit 80eac7370e removed the last build-time dependency ages
ago, we only use GnomeDesktop via introspection.
2012-10-26 12:37:33 +02:00
81eeef7d3c messageTray: Hide summary notification immediately when closing the tray
When the summary notification is open when the tray is closed, we end
up with two concurrent animations: the notification fading out, and the
tray moving away from underneath it. Sliding out the tray should be the
primary transition here, so hide the notification immediately to not
draw the user's attention away from it.

https://bugzilla.gnome.org/show_bug.cgi?id=686888
2012-10-25 22:45:36 +02:00
a7b5134820 messageTray: Hide notification close button immediately on click
Having the close button move away from under the pointer after
clicking it is confusing and distracts from the main transition,
which is hiding the notification. Just hide it immediately.

https://bugzilla.gnome.org/show_bug.cgi?id=682237
2012-10-25 22:41:32 +02:00
92a01c67ba messageTray: Don't destroy the notification when clicking on the close button
Clicking on the close button should simply hide the notification.

https://bugzilla.gnome.org/show_bug.cgi?id=682237
2012-10-25 22:41:32 +02:00
71c23613b5 messageTray: Only hide the notification stack on clicking close
Rather than destroying the entire source, which is unintuitive, simply
close the notification. Removing the entire source is still possible
by right-clicking on the summary item and choosing "Remove".

https://bugzilla.gnome.org/show_bug.cgi?id=682237
2012-10-25 22:41:05 +02:00
4f876995de messageTray: make SummaryItem._closeButton public
Use this to show/hide the close button instead of closeButtonVisible.

https://bugzilla.gnome.org/show_bug.cgi?id=682237
2012-10-25 21:45:18 +02:00
9cf4a76196 po: Enforce RTL in fa/ug for messages that might end up as LTR
See commit 8b796d80a7.

https://bugzilla.gnome.org/show_bug.cgi?id=686630
2012-10-25 20:12:25 +02:00
9efe5287e4 gdm: Move logo into the panel
GDM has a 'logo' key in its schema to allow distributors to add
some branding. It is currently placed above the user list, which
no longer works too well since the login screen lost its dialog
window. Display the logo in the top-left corner instead of the
Activities button instead.

https://bugzilla.gnome.org/show_bug.cgi?id=685852
2012-10-25 18:31:16 +02:00
8c4b34de4e messageTray: Fix close button position in RTL locales 2012-10-25 18:31:16 +02:00
93e3559dc3 style: Adjust close button overlap
After changing the button size, we need to adjust the x-offset by
1px (apparently the y-offset already assumed the correct size).
2012-10-25 18:31:16 +02:00
caa0f63e1f style: Fix close button size
The image is actually 32px, so we end up with a slightly fuzzy
button when scaling up to 34px. Don't do that.

Spotted by lamefun.xOr<at>gmail.com

https://bugzilla.gnome.org/show_bug.cgi?id=686574
2012-10-25 18:27:59 +02:00
a4e29e1244 calendar: Handle calendar-server errors
The current code assumes that the GetEvents call will always
receive, causing an exception in the error case.

https://bugzilla.gnome.org/show_bug.cgi?id=686805
2012-10-24 18:26:03 +02:00
599f2f43e3 Revert "screenShield: Connect to the actor's show signal instead of using BEFORE_REDRAW"
This reverts commit bdeb7d86b6.

git bz PEBKAC
2012-10-24 10:17:43 -04:00
3a453c5f73 messageTray: Fix lightbox
Commit 448517032e accidentally reverted the condition for showing
the lightbox. Fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=686728
2012-10-24 09:03:12 +02:00
98b313c75f popupMenu: Overwrite ongoing animations when calling close repeatedly
Currently close() is a no-op when the menu has already been closed.
However, repeated calls could pass different animation parameters.
For instance in the user menu, we try to hide the menu immediately
before locking the screen, to avoid the popup jumping across the
screen while fading out - as we do this from the corresponding
item's activate handler, the closing is still animated if the menu's
own handler (which requests a full animation) is run first.
Fix this by changing close() to overwrite ongoing animations before
bailing out early.

https://bugzilla.gnome.org/show_bug.cgi?id=686484
2012-10-23 22:21:45 +02:00
8b796d80a7 po: Enforce RTL in he for messages that might end up as LTR
As the messages start with a string placeholder that might be
untranslated, we need an explicit mark to ensure that the string
does not end up as LTR.

https://bugzilla.gnome.org/show_bug.cgi?id=686630
2012-10-23 22:21:45 +02:00
172 changed files with 12821 additions and 15171 deletions

4
.gitignore vendored
View File

@ -38,6 +38,7 @@ docs/reference/*/*.txt
docs/reference/*/*.types
docs/reference/*/html/
docs/reference/*/xml/
docs/reference/shell/doc-gen-*
gtk-doc.make
js/misc/config.js
intltool-extract.in
@ -45,6 +46,7 @@ intltool-merge.in
intltool-update.in
libtool
m4/
man/gnome-shell.1
omf.make
po/*.gmo
po/gnome-shell.pot
@ -84,6 +86,8 @@ src/test-theme
src/st.h
src/stamp-st.h
src/stamp-st.h.tmp
src/st-scroll-view-fade-generated.c
src/stamp-st-scroll-view-fade-generated.c
stamp-h1
tests/run-test.sh
xmldocs.make

3
.gitmodules vendored Normal file
View File

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

View File

@ -1,7 +1,11 @@
# Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src browser-plugin tests po man docs
SUBDIRS = data js src browser-plugin tests po docs
if ENABLE_MAN
SUBDIRS += man
endif
EXTRA_DIST = \
.project \
@ -12,6 +16,7 @@ EXTRA_DIST = \
# These are files checked into Git that we don't want to distribute
DIST_EXCLUDE = \
.gitignore \
.gitmodules \
gnome-shell.doap \
HACKING \
MAINTAINERS \
@ -21,4 +26,4 @@ distcheck-hook:
@echo "Checking disted files against files in git"
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-man

124
NEWS
View File

@ -1,3 +1,127 @@
3.7.3.1
=======
* Revert 490206b to not depend on NMGTK-0.9.7, which hasn't been released yet
3.7.3
=====
* Add 'No Messages' label when message tray is empty [Victoria; #686738]
* Use better icons in Ctrl-Alt-Tab popup [Stéphane; #641303]
* Show the OSK on the monitor where the focused window lives [Giovanni; #685856]
* Highlight window clone and caption when hovered [Giovanni, Marc; #665310]
* Improve login process indication [Stéphane; #687113]
* Omit empty categories in apps view [Stéphane; #687970]
* Style panel differently according to mode [Florian; #684573]
* Make it possible to hide the user name [Matthias; #688577]
* Consolidate and improve chat connection notifications [Giovanni; #687213]
* Improve notification scrollbar appearance [Carlos; #688393]
* Fade scroll view fade near scrolling edges [Jasper; #689249]
* Add a read-only org.gnome.Shell.Mode property [Debarshi; #689300]
* Don't close message tray after using context menus [Giovanni; #689296]
* Port swipe-scrolling to ClutterPanAction [Jasper, Florian; #689062, #689552]
* Remember state of 'Remember Password' checkbox [Ron; #688039]
* Improve timestamp format in chat notifications [Carlos; #680989]
* Improve style of missed-messages counter [Carlos; #686472]
* Omit connection failure notifications if cancelled by user [Giovanni; #684823]
* Add window-based Alt-Tab popup [Florian; #688913]
* Support external session mode definitions [Florian; #689304]
* Support session-mode-specific extensions [Florian; #689305]
* Support 'parentMode' property in session modes [Florian; #689308]
* Support a new org.gnome.ShellSearchProvider2 DBus interface
[Cosimo; #689735, #690009]
* Add "windows" to Ctrl-Alt-Tab popup [Jasper; #689653]
* Port PopupMenu to GrabHelper [Jasper; #689109, #689954]
* Show headphone icon when headphones are plugged in [Giovanni; #675902]
* Display (non-app) search results as list [Tanner, Cosimo; #681797]
* Skip diacritical marks in search terms [Aleksander; #648587]
* Expose all engine options in input sources [Giovanni, Rui; #682318]
* Add input source switcher popup [Rui; #682315]
* Add minimal support for InfiniBand in network menu [Dan; #677150]
* Misc bug fixes and cleanups [Sebastian, Aleksander, Giovanni, Tim, Cosimo,
Florian, Matthias, Rui, Lionel, Colin, Piotr, Guillaume, Bastien, Tanner,
Carlos, Stéphane, Jakub; #688422, #688379, #688750, #688771, #686800,
#688133, #688895, #688966, #683986, #688004, #689108, #689029, #683449,
#688196, #689304, #689243, #689295, #689325, #689400, #679168, #689568,
#689537, #689528, #689749, #689789, #689353, #689820, #689868, #689778,
#689959, #688589, #688589, #689955, #687250, #689965, #690046, #690049,
#689884, #682286, #690173, #690174, #672941, #689876, #687881, #690171,
#690241, #690312, #690175, #687955, #650843, #688234, #690427
Contributors:
Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Stéphane Démurget,
Guillaume Desmottes, Tanner Doshier, Piotr Drąg, Sebastian Keller,
Lionel Landwerlin, Tim Lunn, Victoria Martínez de la Cruz, Aleksander Morgado,
Florian Müllner, Bastien Nocera, Marc Plano-Lesay, Carlos Soriano Sánchez,
Jakub Steiner, Jasper St. Pierre, Colin Walters, Dan Winship, Ron Yorston
Translations:
Yuri Myasoedov [ru], Wouter Bolsterlee [nl], Yaron Shahrabani [he],
Nilamdyuti Goswami [as], Ani Peter [ml], Kjartan Maraas [nb],
Dr.T.Vasudevan [ta], A S Alam [pa], Shankar Prasad [kn], Khaled Hosny [ar],
Daniel Mustieles [es], Dušan Kazik [sk]
3.7.2
=====
* Enforce RTL in he for messages that might end up as LTR [Florian; #686630]
* gdm: Move logo into the panel [Florian; #685852]
* Hide notifications when closed button is clicked [Jasper, Florian; #682237]
* Tweak screenShield animations [Rui; #686745]
* Restore Fittsability of summary items in message tray [Florian; #686474]
* Save screencasts as recent item [Ray; #680647]
* overview: Resize window captions on content change [Giovanni, Alex; #620874]
* App search: Match GenericName too [Matthias; #687121]
* runDialog: Better match style of other modal dialogs [Florian, Allan; #687127]
* Improve the button insensitive style [Stéphane; #687110]
* network: Don't use a global switch for all VPN connections [Giovanni; #682929]
* appMenu: Update on icon theme changes [Florian; #687224]
* Show 'Log out' in more situations [Matthias; #686736]
* Add a setting to force the 'Log out' menuitem [Matthias; #686057]
* overview: Improve styling of search box [Stéphane; #686479]
* Implement 'disable-user-list' in login screen [Ray; #660660]
* Fix auto-scroll to bottom in chat notifications [Sjoerd; #686571]
* Show feedback notifications when user is busy [Stéphane; #662900]
* Disable login button when there is no input [Stéphane; #687112]
* Use non-linear overview shade for background [Giovanni, Pierre-Eric; #669798]
* Reduce blocking in compositor thread [Simon, Jasper; #687465]
* network: new country-specific type to gather providers [Aleksander; #687356]
* Update man page [Matthias; #680601]
* st-entry: Change the pointer cursor on enter/leave events [Thomas; #687130]
* screenShield: Blur and desaturate the background [Giovanni, Cosimo; #682536]
* Change height of chat notifications to have more context [Carlos; #665255]
* screenShield: Account for motion velocity when hiding [Giovanni; #682537]
* screenShield: hide the cursor while the lock screen is on [Giovanni; #682535]
* Support remote search provider settings [Cosimo; #687491]
* unlockDialog: Improve label of confirmation button [Stéphane; #687656]
* userMenu: Rename "System Settings" item to "Settings" [Elad; #687738]
* messageTray: Add keybinding to focus current notification [Stéphane; #652082]
* Remove shell-screen-grabber [Neil; #685915]
* main: Stop using Metacity's keybinding files [Florian; #687672]
* Bluetooth: Remove ObexFTP functionality [Bastien; #688160]
* a11y: Also set WM theme when HighContrast is switched on [Cosimo; #688256]
* network: Rework multiple NIC support [Giovanni; #677142]
* Rework keybindings to allow selective blocking/processing [Florian; #688202]
* recorder: Show indicator on primary monitor [Adel; #688470]
* recorder: Set frame duration to fix broken video headers [Adel; #688487]
* Misc. bugfixes and cleanups [Florian, Jasper, Giovanni, Matthew, Stéphane,
Allan, Daiki, Owen, Alejandro, Jean-François, Cosimo, Sebastian, Adel, Alban;
#686484, #686728, #686805, #686574, #686763, #682428, #687132, #685239,
#687189, #687226, #658091, #670687, #687457, #687242, #687287, #687020,
#686583, #661194, #687491, #657315, #687958, #683986, #688089, #687708,
#686530, #684810, #688181, #688475, #688557, #688507, #638351]
Contributors:
Elad Alfassa, Matthew Barnes, Alban Browaeys, Giovanni Campagna,
Cosimo Cecchi, Matthias Clasen, Allan Day, Stéphane Démurget,
Jean-François Fortin Tam, Adel Gadllah, Alex Hultman, Sebastian Keller,
Rui Matos, Simon McVittie, Aleksander Morgado, Florian Müllner,
Bastien Nocera, Pierre-Eric Pelloux-Prayer, Alejandro Piñeiro, Neil Roberts,
Sjoerd Simons, Carlos Soriano Sánchez, Jasper St. Pierre, Ray Strode,
Owen Taylor, Daiki Ueno, Thomas Wood
Translations:
Dušan Kazik [sk], Pavol Klačanský [sk], Piotr Drąg [pl], Yuri Myasoedov [ru],
Marek Černocký [cs], Kjartan Maraas [nb], Wolfgang Stöggl [de],
Yaron Shahrabani [he], Fran Diéguez [gl], Mattias Põldaru [et]
3.7.1
=====
* Add shortcut to open application view directly [Jeremy; #685738]

View File

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

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.7.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.7.3.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -36,6 +36,8 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
PKG_PROG_PKG_CONFIG([0.22])
AC_PATH_PROG([XSLTPROC], [xsltproc])
GLIB_GSETTINGS
# Get a value to substitute into gnome-shell.in
@ -52,7 +54,7 @@ AC_MSG_CHECKING([for GStreamer (needed for recording functionality)])
if $PKG_CONFIG --exists gstreamer-1.0 '>=' $GSTREAMER_MIN_VERSION ; then
AC_MSG_RESULT(yes)
build_recorder=true
recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11"
recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11 gtk+-3.0"
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes gl)
else
AC_MSG_RESULT(no)
@ -63,7 +65,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.11.11
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.33.2
MUTTER_MIN_VERSION=3.7.1
MUTTER_MIN_VERSION=3.7.3
GTK_MIN_VERSION=3.3.9
GIO_MIN_VERSION=2.35.0
LIBECAL_MIN_VERSION=3.5.3
@ -76,6 +78,7 @@ STARTUP_NOTIFICATION_MIN_VERSION=0.11
GCR_MIN_VERSION=3.3.90
GNOME_DESKTOP_REQUIRED_VERSION=3.7.1
GNOME_MENUS_REQUIRED_VERSION=3.5.3
PULSE_MIN_VERS=2.0
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
@ -97,8 +100,7 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
libnm-glib libnm-util gnome-keyring-1
gcr-3 >= $GCR_MIN_VERSION
gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
gcr-3 >= $GCR_MIN_VERSION)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
@ -122,8 +124,8 @@ LIBS=$saved_LIBS
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.5.4)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2.2)
AC_MSG_CHECKING([for bluetooth support])
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
@ -139,7 +141,7 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
AC_SUBST([HAVE_BLUETOOTH],[0])
AC_MSG_RESULT([no])])
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION libedataserverui-3.0 >= $LIBEDATASERVERUI_MIN_VERSION gio-2.0)
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION gio-2.0)
AC_SUBST(CALENDAR_SERVER_CFLAGS)
AC_SUBST(CALENDAR_SERVER_LIBS)
@ -208,6 +210,18 @@ AC_SUBST(TYPELIBDIR)
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
AC_ARG_ENABLE(man,
[AS_HELP_STRING([--enable-man],
[generate man pages [default=yes]])],,
enable_man=yes)
if test "$enable_man" != no; then
AC_PATH_PROG([XSLTPROC], [xsltproc])
if test -z "$XSLTPROC"; then
AC_MSG_ERROR([xsltproc is required for --enable-man])
fi
fi
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
@ -254,6 +268,7 @@ AC_CONFIG_FILES([
js/Makefile
src/calendar-server/evolution-calendar.desktop.in
src/Makefile
src/gvc/Makefile
browser-plugin/Makefile
tests/Makefile
po/Makefile.in

View File

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

View File

@ -11,7 +11,9 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
@INTLTOOL_DESKTOP_RULE@
introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = org.gnome.ShellSearchProvider.xml
introspection_DATA = \
org.gnome.ShellSearchProvider.xml \
org.gnome.ShellSearchProvider2.xml
themedir = $(pkgdatadir)/theme
dist_theme_DATA = \
@ -32,6 +34,7 @@ dist_theme_DATA = \
theme/gnome-shell.css \
theme/logged-in-indicator.svg \
theme/message-tray-background.png \
theme/more-results.svg \
theme/noise-texture.png \
theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \

View File

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

View File

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

View File

@ -57,6 +57,29 @@ value here is from the TpConnectionPresenceType enumeration.</_summary>
<_summary>Internally used to store the last session presence status for the user. The
value here is from the GsmPresenceStatus enumeration.</_summary>
</key>
<key name="always-show-log-out" type="b">
<default>false</default>
<_summary>Always show the 'Log out' menuitem in the user menu.</_summary>
<_description>
This key overrides the automatic hiding of the 'Log out'
menuitem in single-user, single-session situations.
</_description>
</key>
<key name="show-full-name" type="b">
<default>true</default>
<_summary>Show full name in the user menu</_summary>
<_description>Whether the users full name is shown in the user menu or not.</_description>
</key>
<key name="remember-mount-password" type="b">
<default>false</default>
<_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary>
<_description>
The shell will request a password when an encrypted device or a
remote filesystem is mounted. If the password can be saved for
future use a 'Remember Password' checkbox will be present.
This key sets the default state of the checkbox.
</_description>
</key>
<child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="recorder" schema="org.gnome.shell.recorder"/>
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
@ -98,6 +121,13 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
Keybinding to toggle the visibility of the message tray.
</_description>
</key>
<key name="focus-active-notification" type="as">
<default>["&lt;Super&gt;n"]</default>
<_summary>Keybinding to focus the active notification</_summary>
<_description>
Keybinding to focus the active notification.
</_description>
</key>
<key name="toggle-recording" type="as">
<default><![CDATA[['<Control><Shift><Alt>r']]]></default>
<_summary>Keybinding to toggle the screen recorder</_summary>
@ -156,6 +186,33 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
</key>
</schema>
<enum id="org.gnome.shell.window-switcher.AppIconMode">
<value value="1" nick="thumbnail-only"/>
<value value="2" nick="app-icon-only"/>
<value value="3" nick="both"/>
</enum>
<schema id="org.gnome.shell.window-switcher"
path="/org/gnome/shell/window-switcher/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="app-icon-mode" enum="org.gnome.shell.window-switcher.AppIconMode">
<default>'both'</default>
<_summary>The application icon mode.</_summary>
<_description>
Configures how the windows are shown in the switcher. Valid possibilities
are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-only'
(shows only the application icon) or 'both'.
</_description>
</key>
<key type="b" name="current-workspace-only">
<default>false</default>
<summary>Limit switcher to current workspace.</summary>
<description>
If true, only windows from the current workspace are shown in the switcher.
Otherwise, all windows are included.
</description>
</key>
</schema>
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="attach-modal-dialogs" type="b">

View File

@ -39,7 +39,6 @@ stage {
/* small */
.app-well-menu,
.contact-details-status,
.run-dialog-label,
.run-dialog-error-label {
font-size: 9pt;
}
@ -50,7 +49,7 @@ stage {
.switcher-list,
.app-well-app > .overview-icon,
.show-apps > .overview-icon,
.search-result-content > .overview-icon {
.grid-search-result .overview-icon {
font-size: 9pt;
font-weight: bold;
}
@ -311,7 +310,7 @@ StScrollBar StButton#vhandle:active {
.notification-icon-button:focus,
.hotplug-notification-item:focus,
.modal-dialog-button:focus {
border: 2px solid #8b8b8b;
border-width: 2px;
}
.dash-search-button:active,
@ -326,17 +325,20 @@ StScrollBar StButton#vhandle:active {
background-gradient-end: rgba(255, 255, 255, 0.2);
}
.notification-button:insensitive,
.notification-icon-button:insensitive,
.notification-button:insensitive {
.modal-dialog-button:insensitive {
border-color: #666666;
color: #9f9f9f;
background-gradient-direction: none;
background-color: rgba(102, 102, 102, 0.15);
}
/* Entries */
#searchEntry,
.notification StEntry,
.login-dialog-prompt-entry,
.prompt-dialog-password-entry {
.modal-dialog StEntry {
color: rgb(64, 64, 64);
caret-color: rgb(64, 64, 64);
font-size: 12pt;
@ -346,6 +348,7 @@ StScrollBar StButton#vhandle:active {
}
#searchEntry,
.run-dialog-entry,
.notification StEntry {
border: 2px solid rgba(245,245,245,0.2);
background-gradient-start: rgba(5,5,6,0.1);
@ -358,8 +361,7 @@ StScrollBar StButton#vhandle:active {
#searchEntry:focus,
#searchEntry:hover,
.notification StEntry:focus,
.login-dialog-prompt-entry,
.prompt-dialog-password-entry {
.modal-dialog StEntry {
border: 2px solid rgb(136,138,133);
background-gradient-start: rgb(200,200,200);
background-gradient-end: white;
@ -368,12 +370,17 @@ StScrollBar StButton#vhandle:active {
}
.notification StEntry:focus,
.prompt-dialog-password-entry:focus,
.login-dialog-prompt-entry:focus {
.modal-dialog StEntry:focus {
border: 2px solid #3465a4;
}
#searchEntry {
border-color: rgba(245,245,245,0.3);
color: rgb(192, 192, 192);
caret-color: rgb(192, 192, 192);
}
#searchEntry:hover {
color: rgb(128, 128, 128);
caret-color: rgb(128, 128, 128);
}
@ -386,8 +393,7 @@ StScrollBar StButton#vhandle:active {
}
.notification StEntry,
.prompt-dialog-password-entry,
.login-dialog-prompt-entry {
.modal-dialog StEntry {
border-radius: 5px;
padding: 4px 4px;
}
@ -399,11 +405,13 @@ StScrollBar StButton#vhandle:active {
padding: 0 4px;
}
.login-dialog-prompt-entry:insensitive {
color: rgba(0,0,0,0.7);
border: 2px solid #565656;
background-gradient-start: rgb(200,200,200);
background-gradient-end: rgb(210,210,210);
.modal-dialog StEntry:insensitive {
border-color: #666666;
color: #9f9f9f;
border: 2px solid #9f9f9f;
background-gradient-direction: none;
background-color: rgba(102, 102, 102, 0.15);
box-shadow: inset 0 0 rgba(0,0,0,1.0);
}
/* Panel */
@ -412,6 +420,18 @@ StScrollBar StButton#vhandle:active {
background-color: black;
font-weight: bold;
height: 1.86em;
transition-duration: 250;
}
#panel.lock-screen {
height: 2em;
background-color: rgba(0,0,0,0.3);
}
#panel.unlock-screen,
#panel.login-screen {
height: 2em;
background-color: transparent;
}
#panelLeft, #panelCenter {
@ -447,6 +467,13 @@ StScrollBar StButton#vhandle:active {
-panel-corner-border-color: rgba(255,255,255,0.8);
}
.panel-corner.lock-screen,
.panel-corner.unlock-screen,
.panel-corner.login-screen {
-panel-corner-background-color: transparent;
-panel-corner-border-color: transparent;
}
#appMenu {
spacing: 4px;
}
@ -479,6 +506,24 @@ StScrollBar StButton#vhandle:active {
transition-duration: 100;
}
#panel.unlock-screen .panel-button,
#panel.lock-screen .panel-button,
#panel.login-screen .panel-button {
color: #e6e6e6;
}
#panel.unlock-screen .panel-button:hover,
#panel.lock-screen .panel-button:hover,
#panel.login-screen .panel-button:hover,
#panel.unlock-screen .panel-button:active,
#panel.lock-screen .panel-button:active,
#panel.login-screen .panel-button:active,
#panel.unlock-screen .panel-button:focus,
#panel.lock-screen .panel-button:focus,
#panel.login-screen .panel-button:focus {
color: white;
}
.panel-button:hover {
color: white;
text-shadow: black 0px 2px 2px;
@ -513,6 +558,10 @@ StScrollBar StButton#vhandle:active {
spacing: 4px;
}
.lock-screen-status-button-box {
spacing: 8px;
}
/* User Menu */
#panelUserMenu {
@ -551,7 +600,6 @@ StScrollBar StButton#vhandle:active {
}
.status-chooser-combo.popup-combo-menu {
background-color: rgba(0,0,0,0.7);
padding: .4em 0em;
border-radius: 4px;
border: 1px solid #5f5f5f;
@ -569,7 +617,15 @@ StScrollBar StButton#vhandle:active {
/* Overview */
#overview {
spacing: 40px;
spacing: 24px;
}
#overview-group {
spacing: 32px;
}
.workspaces-display {
spacing: 32px; /* needs to be the same value as #overview-group */
}
.window-caption {
@ -610,39 +666,56 @@ StScrollBar StButton#vhandle:active {
border-radius: 8px;
padding: 4px 12px;
-shell-caption-spacing: 12px;
border: 2px solid rgba(0, 0, 0, 0);
}
.window-close, .notification-close {
background-image: url("close-window.svg");
background-size: 34px;
height: 34px;
width: 34px;
background-size: 32px;
height: 32px;
width: 32px;
}
.window-close {
-shell-close-overlap: 20px;
-shell-close-overlap: 16px;
}
.window-caption:hover {
border: 2px solid rgba(255, 255, 255, 0);
}
.window-clone-border {
border: 4px solid rgba(255, 255, 255, 0.5);
border-radius: 4px;
}
.notification-close {
/* we start out in the top right of the
* notification, inset.
*
* center is 32px/2 = 17px
* center is 32px/2 = 16px
*
* adjust left 2px
* adjust down 8px */
-shell-close-overlap-x: 15px;
-shell-close-overlap-x: 14px;
-shell-close-overlap-y: -12px;
}
.notification-close:rtl {
/* as above, but starting out in the top left of the
* notification. */
-shell-close-overlap-x: -14px;
}
.window-close:rtl {
-st-background-image-shadow: 2px 2px 6px rgba(0,0,0,0.5);
}
.window-picker {
-horizontal-spacing: 40px;
-vertical-spacing: 40px;
-horizontal-spacing: 32px;
-vertical-spacing: 32px;
}
/* Dash */
@ -682,6 +755,11 @@ StScrollBar StButton#vhandle:active {
.search-entry-icon {
icon-size: 1em;
color: #c0c0c0;
}
#searchEntry:hover .search-entry-icon,
#searchEntry:focus .search-entry-icon {
color: #8d8f8a;
}
@ -694,7 +772,7 @@ StScrollBar StButton#vhandle:active {
#searchResultsContent {
padding-right: 20px;
spacing: 36px;
spacing: 16px;
}
#searchResultsContent:rtl {
@ -702,11 +780,22 @@ StScrollBar StButton#vhandle:active {
padding-left: 20px;
}
.search-section-header {
padding: 4px 12px;
spacing: 4px;
color: #6f6f6f;
font-size: .8em;
.search-section {
/* This should be equal to #searchResultsContent spacing */
spacing: 16px;
}
.search-section-separator {
-gradient-height: 1px;
-gradient-start: rgba(255,255,255,0);
-gradient-end: rgba(255,255,255,0.5);
-margin-horizontal: 1.5em;
height: 1px;
}
.search-section-content {
/* This is the space between the provider icon and the results container */
spacing: 32px;
}
.search-statustext {
@ -715,16 +804,8 @@ StScrollBar StButton#vhandle:active {
font-weight: bold;
}
.search-section-results {
padding: 6px;
}
.search-section-list-results {
spacing: 4px;
}
.results-container {
spacing: 4px;
.list-search-results {
spacing: 3px;
}
/* Text labels are an odd number of pixels tall. The uneven top and bottom
@ -753,7 +834,7 @@ StScrollBar StButton#vhandle:active {
-x-offset: 8px;
}
/* Application Launchers and Grid */
/* Application Launchers, Grid and List results */
.icon-grid {
spacing: 36px;
@ -805,9 +886,34 @@ StScrollBar StButton#vhandle:active {
padding: 4px 8px;
}
.list-search-result-content {
spacing: 12px;
padding: 12px;
}
.list-search-result-title {
font-weight: bold;
font-size: 14pt;
color: white;
}
.list-search-result-description {
font-weight: bold;
font-size: 12pt;
color: #eeeeec;
}
.search-provider-icon-more {
width: 16px;
height: 16px;
background-image: url("more-results.svg");
}
.app-well-app > .overview-icon,
.show-apps > .overview-icon,
.search-result-content > .overview-icon {
.search-provider-icon,
.list-search-result,
.grid-search-result .overview-icon {
border-radius: 4px;
padding: 3px;
border: 1px rgba(0,0,0,0);
@ -823,7 +929,9 @@ StScrollBar StButton#vhandle:active {
.app-well-app:hover > .overview-icon,
.show-apps:hover > .overview-icon,
.search-result-content:hover > .overview-icon {
.search-provider-icon:hover,
.list-search-result:hover,
.grid-search-result:hover .overview-icon {
background-color: rgba(255,255,255,0.1);
text-shadow: black 0px 2px 2px;
transition-duration: 100;
@ -858,10 +966,14 @@ StScrollBar StButton#vhandle:active {
}
.app-well-app:focus > .overview-icon,
.search-result-content:focus > .overview-icon,
.grid-search-result:focus .overview-icon,
.show-apps:focus > .overview-icon,
.search-provider-icon:focus,
.list-search-result:focus,
.app-well-app:selected > .overview-icon,
.search-result-content:selected > .overview-icon {
.grid-search-result:selected .overview-icon,
.search-provider-icon:selected,
.list-search-result:selected {
background-color: rgba(255,255,255,0.33);
}
@ -1193,7 +1305,6 @@ StScrollBar StButton#vhandle:active {
background: #2e3436 url(message-tray-background.png);
background-repeat: repeat;
transition-duration: 250;
height: 72px;
}
#message-tray:keyboard {
@ -1203,12 +1314,22 @@ StScrollBar StButton#vhandle:active {
#message-tray:overview {
background: rgba(0, 0, 0, 0.1);
border-top: 1px solid rgba(128, 128, 128, 0.3);
outline: 1px solid rgba(128, 128, 128, 0.3);
}
.message-tray-summary {
height: 72px;
}
.no-messages-label {
font-family: cantarell, sans-serif;
font-size: 11pt;
color: #999999;
}
.notification {
border-radius: 10px 10px 0px 0px;
background: rgba(0,0,0,0.8);
background: rgba(0,0,0,0.9);
padding: 8px 8px 4px 8px;
spacing-rows: 10px;
spacing-columns: 10px;
@ -1239,8 +1360,8 @@ StScrollBar StButton#vhandle:active {
}
.summary-boxpointer {
-arrow-border-radius: 8px;
-arrow-background-color: rgba(0,0,0,0.8);
-arrow-border-radius: 15px;
-arrow-background-color: rgba(0,0,0,0.9);
-arrow-base: 36px;
-arrow-rise: 18px;
color: white;
@ -1260,8 +1381,8 @@ StScrollBar StButton#vhandle:active {
.summary-notification-stack-scrollview {
max-height: 18em;
padding-top: 6px;
padding-bottom: 6px;
padding-top: 8px;
padding-bottom: 8px;
}
.summary-notification-stack-scrollview:ltr {
@ -1416,6 +1537,10 @@ StScrollBar StButton#vhandle:active {
padding-right: 4px;
}
.chat-notification-scrollview{
max-height: 22em;
}
.subscription-message {
font-style: italic;
}
@ -1424,44 +1549,46 @@ StScrollBar StButton#vhandle:active {
border-radius: 4px;
}
#summary-mode {
padding: 0px 6px 0px 6px; /* same as the values in .summary-source */
height: 60px;
spacing: 10px;
}
.summary-source-button {
border-radius: 4px;
transition-duration: 100;
padding: 6px 3px 6px 3px;
}
.summary-source-button:hover {
.summary-source-button:last-child:ltr {
padding-right: 6px;
}
.summary-source-button:last-child:rtl {
padding-left: 6px;
}
.summary-source-button:hover .summary-source {
background-color: rgba(255,255,255,0.1);
}
.summary-source-button:focus,
.summary-source-button:selected {
.summary-source-button:focus .summary-source,
.summary-source-button:selected .summary-source {
background-color: rgba(255,255,255,0.33);
}
.summary-source {
padding-right: 6px;
padding-left: 6px;
border-radius: 4px;
padding: 0 6px 0 6px;
transition-duration: 100;
}
.summary-source-counter {
background-image: url("summary-counter.svg");
background-size: 2.5em;
background-size: 2.4em;
font-size: 10pt;
font-weight: bold;
height: 2.5em;
width: 2.5em;
-shell-counter-overlap-x: 4px;
-shell-counter-overlap-y: 4px;
height: 2.4em;
width: 2.4em;
-shell-counter-overlap-x: 13px;
-shell-counter-overlap-y: 13px;
}
/* App Switcher */
#altTabPopup {
.switcher-popup {
padding: 8px;
spacing: 16px;
}
@ -1624,35 +1751,26 @@ StScrollBar StButton#vhandle:active {
padding: 4px 32px 5px;
}
.modal-dialog-button:insensitive {
color: rgb(60, 60, 60);
}
.modal-dialog-button:focus {
padding: 3px 31px 4px;
}
/* Run Dialog */
.run-dialog-label {
font-size: 12pt;
font-weight: bold;
color: #999999;
padding-bottom: .4em;
}
.run-dialog-error-box {
padding-top: 15px;
spacing: 5px;
}
.run-dialog-entry {
font-weight: bold;
width: 23em;
selection-background-color: white;
selected-color: black;
}
.run-dialog {
border-radius: 16px;
padding-right: 21px;
padding-left: 21px;
padding-bottom: 15px;
padding-top: 15px;
.modal-dialog .run-dialog-entry {
width: 20em;
}
.lightbox {
@ -2112,7 +2230,7 @@ StScrollBar StButton#vhandle:active {
font-weight: bold;
text-align: left;
padding-left: 15px;
text-shadow: black 4px 4px 3px 0px;
text-shadow: black 0px 4px 3px 0px;
}
.login-dialog-prompt-layout {
@ -2178,24 +2296,24 @@ StScrollBar StButton#vhandle:active {
height: .75em;
}
.login-dialog .modal-dialog-button-box {
spacing: 3px;
}
.login-dialog .modal-dialog-button {
border: 1px solid #666666;
border-radius: 5px;
padding: 3px 18px;
}
.login-dialog .modal-dialog-button:focus {
padding: 2px 17px;
border: 2px solid #8b8b8b;
}
.login-dialog .modal-dialog-button:default {
background-gradient-start: #6793c4;
background-gradient-end: #335d8f;
background-gradient-direction: vertical;
padding: 2px 17px;
border: 2px solid #16335d;
border-color: #16335d;
}
.login-dialog .modal-dialog-button:default:focus {
@ -2213,6 +2331,13 @@ StScrollBar StButton#vhandle:active {
background-gradient-end: #74a0d0;
}
.login-dialog .modal-dialog-button:default:insensitive {
border-color: #666666;
color: #9f9f9f;
background-gradient-direction: none;
background-color: rgba(102, 102, 102, 0.15);
}
.login-dialog-message-warning {
color: orange;
}
@ -2280,16 +2405,21 @@ StScrollBar StButton#vhandle:active {
}
.screen-shield-notification-source {
padding: 0 24px;
padding: 13px 24px;
spacing: 5px;
}
.screen-shield-notification-label {
font-size: 1.2em;
font-weight: bold;
padding: 0px 18px;
color: #babdb6;
}
.screen-shield-notification-count-text {
padding: 0px 18px;
}
/* Remove background from notifications, otherwise
opacity is doubled and they look darker
*/
@ -2305,3 +2435,8 @@ StScrollBar StButton#vhandle:active {
padding-bottom: 0px;
}
.input-source-switcher-symbol {
font-size: 42pt;
width: 96px;
height: 96px;
}

109
data/theme/more-results.svg Normal file
View File

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

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

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

View File

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

View File

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

View File

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

View File

@ -39,13 +39,19 @@ const GdmUtil = imports.gdm.util;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Panel = imports.ui.panel;
const PanelMenu = imports.ui.panelMenu;
const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu;
const _RESIZE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_NAME_SIZE = 48;
const _LOGO_ICON_HEIGHT = 16;
const WORK_SPINNER_ICON_SIZE = 24;
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
const WORK_SPINNER_ANIMATION_TIME = 0.3;
let _loginDialog = null;
@ -82,6 +88,36 @@ function _smoothlyResizeActor(actor, width, height) {
return hold;
}
const LogoMenuButton = new Lang.Class({
Name: 'LogoMenuButton',
Extends: PanelMenu.Button,
_init: function() {
this.parent(0.0, null, true);
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
Lang.bind(this, this._updateLogo));
this._iconBin = new St.Bin();
this.actor.add_actor(this._iconBin);
this._updateLogo();
},
_updateLogo: function() {
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
let icon = null;
if (path) {
let file = Gio.file_new_for_path(path);
let cache = St.TextureCache.get_default();
icon = cache.load_uri_async(file.get_uri(), -1, _LOGO_ICON_HEIGHT);
}
this._iconBin.set_child(icon);
}
});
const UserListItem = new Lang.Class({
Name: 'UserListItem',
@ -573,6 +609,14 @@ const SessionList = new Lang.Class({
this.close();
},
updateSensitivity: function(sensitive) {
this._button.reactive = sensitive;
this._button.can_focus = sensitive;
for (let id in this._items)
this._items[id].actor.reactive = sensitive;
},
setActiveSession: function(sessionId) {
if (sessionId == this._activeSessionId)
return;
@ -629,6 +673,7 @@ const LoginDialog = new Lang.Class({
this.parent({ shellReactive: true,
styleClass: 'login-dialog',
parentActor: parentActor,
keybindingMode: Main.KeybindingMode.LOGIN_SCREEN,
shouldFadeIn: false });
this.connect('destroy',
Lang.bind(this, this._onDestroy));
@ -653,22 +698,20 @@ const LoginDialog = new Lang.Class({
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
this._userVerifier.connect('verification-failed', Lang.bind(this, this._verificationFailed));
this._userVerifier.connect('reset', Lang.bind(this, this._reset));
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
this._verifyingUser = false;
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
Lang.bind(this, this._updateLogo));
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
Lang.bind(this, this._updateBanner));
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
Lang.bind(this, this._updateBanner));
this._logoBox = new St.Bin({ style_class: 'login-dialog-logo-box' });
this.contentLayout.add(this._logoBox);
this._updateLogo();
this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
Lang.bind(this, this._updateDisableUserList));
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
text: '' });
@ -676,7 +719,8 @@ const LoginDialog = new Lang.Class({
this._updateBanner();
this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
text: C_("title", "Sign In") });
text: C_("title", "Sign In"),
visible: false });
this.contentLayout.add(this._titleLabel,
{ y_fill: false,
@ -706,6 +750,7 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START });
this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true });
this._promptEntryTextChangedId = 0;
this._promptBox.add(this._promptEntry,
{ expand: true,
x_fill: true,
@ -719,6 +764,9 @@ const LoginDialog = new Lang.Class({
this._promptLoginHint.hide();
this._promptBox.add(this._promptLoginHint);
this._signInButton = null;
this._workSpinner = null;
this._sessionList = new SessionList();
this._sessionList.connect('session-activated',
Lang.bind(this, function(list, sessionId) {
@ -744,7 +792,7 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._notListedButton.connect('clicked', Lang.bind(this, this._onNotListedClicked));
this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAndLogIn));
this.contentLayout.add(this._notListedButton,
{ expand: false,
@ -770,18 +818,19 @@ const LoginDialog = new Lang.Class({
},
_updateLogo: function() {
this._logoBox.child = null;
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
_updateDisableUserList: function() {
let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
if (path) {
let file = Gio.file_new_for_path(path);
let uri = file.get_uri();
// If this is the first time around, set initial focus
if (this._disableUserList == undefined && disableUserList)
this.setInitialKeyFocus(this._promptEntry);
let textureCache = St.TextureCache.get_default();
this._logoBox.child = textureCache.load_uri_async(uri, -1, _LOGO_ICON_NAME_SIZE);
if (disableUserList != this._disableUserList) {
this._disableUserList = disableUserList;
if (!this._verifyingUser)
this._reset();
}
},
_updateBanner: function() {
@ -796,32 +845,23 @@ const LoginDialog = new Lang.Class({
}
},
_onReset: function(client, serviceName) {
_reset: function() {
this._updateSensitivity(true);
this._promptMessage.hide();
let tasks = [this._hidePrompt,
new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
this._fadeInNotListedButton,
this._fadeInLogo]),
function() {
this._sessionList.close();
this._promptLoginHint.hide();
this._userList.actor.show();
this._userList.actor.opacity = 255;
return this._userList.showItems();
},
function() {
this._userList.actor.reactive = true;
this._userList.actor.grab_key_focus();
}];
this._user = null;
this._verifyingUser = false;
let batch = new Batch.ConsecutiveBatch(this, tasks);
batch.run();
if (this._disableUserList)
this._hideUserListAndLogIn();
else
this._showUserList();
},
_verificationFailed: function() {
this._promptEntry.text = '';
this._updateSensitivity(true);
this._setWorking(false);
},
_onDefaultSessionChanged: function(client, sessionId) {
@ -829,9 +869,13 @@ const LoginDialog = new Lang.Class({
},
_showMessage: function(userVerifier, message, styleClass) {
this._promptMessage.text = message;
this._promptMessage.styleClass = styleClass;
GdmUtil.fadeInActor(this._promptMessage);
if (message) {
this._promptMessage.text = message;
this._promptMessage.styleClass = styleClass;
GdmUtil.fadeInActor(this._promptMessage);
} else {
GdmUtil.fadeOutActor(this._promptMessage);
}
},
_showLoginHint: function(verifier, message) {
@ -872,6 +916,9 @@ const LoginDialog = new Lang.Class({
if (this._user && this._user.is_logged_in())
return null;
if (!this._verifyingUser)
return null;
return GdmUtil.fadeInActor(this._sessionList.actor);
},
@ -884,24 +931,15 @@ const LoginDialog = new Lang.Class({
return batch.run();
},
_showPrompt: function() {
_showPrompt: function(forSecret) {
let hold = new Batch.Hold();
let buttons = [{ action: Lang.bind(this, this.cancel),
label: _("Cancel"),
key: Clutter.Escape },
{ action: Lang.bind(this, function() {
hold.release();
}),
label: C_("button", "Sign In"),
default: true }];
let tasks = [function() {
return this._fadeInPrompt();
},
function() {
this.setButtons(buttons);
this._prepareDialog(forSecret, hold);
},
hold];
@ -911,17 +949,86 @@ const LoginDialog = new Lang.Class({
return batch.run();
},
_prepareDialog: function(forSecret, hold) {
this._workSpinner = new Panel.AnimatedIcon('process-working.svg', WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._workSpinner.actor.show();
this.buttonLayout.visible = true;
this.clearButtons();
if (!this._disableUserList || this._verifyingUser)
this.addButton({ action: Lang.bind(this, this.cancel),
label: _("Cancel"),
key: Clutter.Escape },
{ expand: true,
x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this.buttonLayout.add(this._workSpinner.actor,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._signInButton = this.addButton({ action: Lang.bind(this, function() {
hold.release();
}),
label: forSecret ? C_("button", "Sign In") : _("Next"),
default: true },
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
this._promptEntryTextChangedId =
this._promptEntry.clutter_text.connect('text-changed',
Lang.bind(this, function() {
this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
}));
},
_updateSensitivity: function(sensitive) {
this._promptEntry.reactive = sensitive;
this._promptEntry.clutter_text.editable = sensitive;
this._sessionList.updateSensitivity(sensitive);
this._updateSignInButtonSensitivity(sensitive);
},
_updateSignInButtonSensitivity: function(sensitive) {
if (this._signInButton) {
this._signInButton.reactive = sensitive;
this._signInButton.can_focus = sensitive;
}
},
_hidePrompt: function() {
this.setButtons([]);
if (this._promptEntryTextChangedId > 0) {
this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId);
this._promptEntryTextChangedId = 0;
}
let tasks = [function() {
this._setWorking(false);
return GdmUtil.fadeOutActor(this._promptBox);
},
function() {
this._promptLoginHint.hide();
this._promptEntry.reactive = true;
this._updateSensitivity(true);
this._promptEntry.set_text('');
this.clearButtons();
this._workSpinner = null;
this._signInButton = null;
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
@ -929,18 +1036,63 @@ const LoginDialog = new Lang.Class({
return batch.run();
},
_setWorking: function(working) {
if (!this._workSpinner)
return;
if (working) {
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
this._workSpinner.stop();
}
});
}
},
_askQuestion: function(verifier, serviceName, question, passwordChar) {
this._promptLabel.set_text(question);
this._promptEntry.set_text('');
this._promptEntry.clutter_text.set_password_char(passwordChar);
let tasks = [function() {
return this._showPrompt(!!passwordChar);
},
function() {
let text = this._promptEntry.get_text();
this._updateSensitivity(false);
this._setWorking(true);
this._userVerifier.answerQuery(serviceName, text);
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
return batch.run();
},
_askForUsernameAndLogIn: function() {
this._promptLabel.set_text(_("Username: "));
this._promptEntry.set_text('');
this._promptEntry.clutter_text.set_password_char('');
let tasks = [this._showPrompt,
function() {
let _text = this._promptEntry.get_text();
let userName = this._promptEntry.get_text();
this._promptEntry.reactive = false;
this._userVerifier.answerQuery(serviceName, _text);
return this._beginVerificationForUser(userName);
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
@ -1075,7 +1227,7 @@ const LoginDialog = new Lang.Class({
}));
},
_onNotListedClicked: function(user) {
_hideUserListAndLogIn: function() {
let tasks = [function() {
return this._userList.hideItems();
},
@ -1089,26 +1241,37 @@ const LoginDialog = new Lang.Class({
},
new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
this._fadeOutNotListedButton,
this._fadeOutLogo]),
this._fadeOutNotListedButton]),
function() {
let hold = new Batch.Hold();
this._userVerifier.begin(null, hold);
return hold;
return this._askForUsernameAndLogIn();
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
batch.run();
},
_fadeInLogo: function() {
return GdmUtil.fadeInActor(this._logoBox);
},
_showUserList: function() {
let tasks = [this._hidePrompt,
_fadeOutLogo: function() {
return GdmUtil.fadeOutActor(this._logoBox);
new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
this._fadeInNotListedButton]),
function() {
this._sessionList.close();
this._promptLoginHint.hide();
this._userList.actor.show();
this._userList.actor.opacity = 255;
return this._userList.showItems();
},
function() {
this._userList.actor.reactive = true;
this._userList.actor.grab_key_focus();
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
batch.run();
},
_fadeInBanner: function() {
@ -1139,6 +1302,7 @@ const LoginDialog = new Lang.Class({
let hold = new Batch.Hold();
this._userVerifier.begin(userName, hold);
this._verifyingUser = true;
return hold;
},
@ -1159,8 +1323,7 @@ const LoginDialog = new Lang.Class({
},
new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
this._fadeOutNotListedButton,
this._fadeOutLogo]),
this._fadeOutNotListedButton]),
function() {
return this._userList.shrinkToNaturalHeight();
@ -1192,6 +1355,8 @@ const LoginDialog = new Lang.Class({
this._userList.addUser(users[i]);
}
this._updateDisableUserList();
this._userManager.connect('user-added',
Lang.bind(this, function(userManager, user) {
this._userList.addUser(user);
@ -1215,7 +1380,7 @@ const LoginDialog = new Lang.Class({
_onOpened: function() {
Main.ctrlAltTabManager.addGroup(this.dialogLayout,
_("Login Window"),
'dialog-password',
'dialog-password-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE });
},
@ -1223,6 +1388,6 @@ const LoginDialog = new Lang.Class({
close: function() {
this.parent();
Main.ctrlAltTabManager.removeGroup(this._group);
Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
}
});

View File

@ -23,6 +23,7 @@ const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
const ALLOWED_FAILURES_KEY = 'allowed-failures';
const LOGO_KEY = 'logo';
const DISABLE_USER_LIST_KEY = 'disable-user-list';
function fadeInActor(actor) {
if (actor.opacity == 255 && actor.visible)
@ -125,6 +126,9 @@ const ShellUserVerifier = new Lang.Class({
},
answerQuery: function(serviceName, answer) {
// Clear any previous message
this.emit('show-message', null, null);
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
},
@ -330,12 +334,11 @@ const ShellUserVerifier = new Lang.Class({
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
// go back to the welcome screen.
this._failCounter++;
let canRetry = retry && this._userName &&
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
if (canRetry) {
this._failCounter++;
this.clear();
this.begin(this._userName, new Batch.Hold());
} else {

View File

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

View File

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

View File

@ -46,8 +46,70 @@ let _providersTable;
function _getProvidersTable() {
if (_providersTable)
return _providersTable;
let [providers, countryCodes] = Shell.mobile_providers_parse();
return _providersTable = providers;
return _providersTable = Shell.mobile_providers_parse(null,null);
}
function findProviderForMCCMNC(table, needle) {
let needlemcc = needle.substring(0, 3);
let needlemnc = needle.substring(3, needle.length);
let name2, name3;
for (let iter in table) {
let country = table[iter];
let providers = country.get_providers();
// Search through each country's providers
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
// Search through MCC/MNC list
let list = provider.get_gsm_mcc_mnc();
for (let j = 0; j < list.length; j++) {
let mccmnc = list[j];
// Match both 2-digit and 3-digit MNC; prefer a
// 3-digit match if found, otherwise a 2-digit one.
if (mccmnc.mcc != needlemcc)
continue; // MCC was wrong
if (!name3 && needle.length == 6 && needlemnc == mccmnc.mnc)
name3 = provider.name;
if (!name2 && needlemnc.substring(0, 2) == mccmnc.mnc.substring(0, 2))
name2 = provider.name;
if (name2 && name3)
break;
}
}
}
return name3 || name2 || null;
}
function findProviderForSid(table, sid) {
if (sid == 0)
return null;
// Search through each country
for (let iter in table) {
let country = table[iter];
let providers = country.get_providers();
// Search through each country's providers
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
let cdma_sid = provider.get_cdma_sid();
// Search through CDMA SID list
for (let j = 0; j < cdma_sid.length; j++) {
if (cdma_sid[j] == sid)
return provider.name;
}
}
}
return null;
}
const ModemGsm = new Lang.Class({
@ -91,64 +153,29 @@ const ModemGsm = new Lang.Class({
},
_findOperatorName: function(name, opCode) {
if (name.length != 0 && (name.length > 6 || name.length < 5)) {
// this looks like a valid name, i.e. not an MCCMNC (that some
// devices return when not yet connected
return name;
}
if (isNaN(parseInt(name))) {
// name is definitely not a MCCMNC, so it may be a name
// after all; return that
return name;
if (name) {
if (name && name.length != 0 && (name.length > 6 || name.length < 5)) {
// this looks like a valid name, i.e. not an MCCMNC (that some
// devices return when not yet connected
return name;
}
if (isNaN(parseInt(name))) {
// name is definitely not a MCCMNC, so it may be a name
// after all; return that
return name;
}
}
let needle;
if (name.length == 0 && opCode)
if ((name == null || name.length == 0) && opCode)
needle = opCode;
else if (name.length == 6 || name.length == 5)
needle = name;
else // nothing to search
return null;
return this._findProviderForMCCMNC(needle);
},
_findProviderForMCCMNC: function(needle) {
let table = _getProvidersTable();
let needlemcc = needle.substring(0, 3);
let needlemnc = needle.substring(3, needle.length);
let name2, name3;
for (let iter in table) {
let providers = table[iter];
// Search through each country's providers
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
// Search through MCC/MNC list
let list = provider.get_gsm_mcc_mnc();
for (let j = 0; j < list.length; j++) {
let mccmnc = list[j];
// Match both 2-digit and 3-digit MNC; prefer a
// 3-digit match if found, otherwise a 2-digit one.
if (mccmnc.mcc != needlemcc)
continue; // MCC was wrong
if (!name3 && needle.length == 6 && needlemnc == mccmnc.mnc)
name3 = provider.name;
if (!name2 && needlemnc.substring(0, 2) == mccmnc.mnc.substring(0, 2))
name2 = provider.name;
if (name2 && name3)
break;
}
}
}
return name3 || name2 || null;
return findProviderForMCCMNC(table, needle);
}
});
Signals.addSignalMethods(ModemGsm.prototype);
@ -189,39 +216,14 @@ const ModemCdma = new Lang.Class({
this.operator_name = null;
} else {
let [bandClass, band, id] = result;
if (name.length > 0)
this.operator_name = this._findProviderForSid(id);
else
if (name.length > 0) {
let table = _getProvidersTable();
this.operator_name = findProviderForSid(table, id);
} else
this.operator_name = null;
}
this.emit('notify::operator-name');
}));
},
_findProviderForSid: function(sid) {
if (sid == 0)
return null;
let table = _getProvidersTable();
// Search through each country
for (let iter in table) {
let providers = table[iter];
// Search through each country's providers
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
let cdma_sid = provider.get_cdma_sid();
// Search through CDMA SID list
for (let j = 0; j < cdma_sid.length; j++) {
if (cdma_sid[j] == sid)
return provider.name;
}
}
}
return null;
}
});
Signals.addSignalMethods(ModemCdma.prototype);

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -84,9 +84,12 @@ const AppFavorites = new Lang.Class({
let app = Shell.AppSystem.get_default().lookup_app(appId);
Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
this._removeFavorite(appId);
}));
Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()),
{ forFeedback: true,
undoCallback: Lang.bind(this, function () {
this._removeFavorite(appId);
})
});
},
addFavorite: function(appId) {
@ -116,9 +119,11 @@ const AppFavorites = new Lang.Class({
return;
Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
Lang.bind(this, function () {
this._addFavorite(appId, pos);
}));
{ forFeedback: true,
undoCallback: Lang.bind(this, function () {
this._addFavorite(appId, pos);
})
});
}
});
Signals.addSignalMethods(AppFavorites.prototype);

View File

@ -141,6 +141,7 @@ const BoxPointer = new Lang.Class({
this._muteInput();
Tweener.removeTweens(this);
Tweener.addTween(this, { opacity: fade ? 0 : 255,
xOffset: xOffset,
yOffset: yOffset,

View File

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

View File

@ -408,7 +408,10 @@ const VPNRequestHandler = new Lang.Class({
}
},
cancel: function() {
cancel: function(respond) {
if (respond)
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
if (this._newStylePlugin && this._shellDialog) {
this._shellDialog.close(global.get_current_time());
this._shellDialog.destroy();
@ -595,11 +598,23 @@ const NetworkAgent = new Lang.Class({
},
enable: function() {
this._native.register();
this._native.auto_register = true;
},
disable: function() {
this._native.unregister();
let requestId;
for (requestId in this._dialogs)
this._dialogs[requestId].cancel();
this._dialogs = { };
for (requestId in this._vpnRequests)
this._vpnRequests[requestId].cancel(true);
this._vpnRequests = { };
this._native.auto_register = false;
if (this._native.registered)
this._native.unregister();
},
_newRequest: function(agent, requestId, connection, settingName, hints, flags) {
@ -622,7 +637,7 @@ const NetworkAgent = new Lang.Class({
this._dialogs[requestId].destroy();
delete this._dialogs[requestId];
} else if (this._vpnRequests[requestId]) {
this._vpnRequests[requestId].cancel();
this._vpnRequests[requestId].cancel(false);
delete this._vpnRequests[requestId];
}
},

View File

@ -49,7 +49,7 @@ const AuthenticationDialog = new Lang.Class({
let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
vertical: true });
mainContentBox.add(messageBox,
{ y_align: St.Align.START });
{ expand: true, y_align: St.Align.START });
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
text: _("Authentication Required") });

View File

@ -1,5 +1,6 @@
const Lang = imports.lang;
const Main = imports.ui.main;
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
@ -16,13 +17,16 @@ const Recorder = new Lang.Class({
},
enable: function() {
global.display.add_keybinding('toggle-recording',
this._bindingSettings,
Meta.KeyBindingFlags.NONE, Lang.bind(this, this._toggleRecorder));
Main.wm.addKeybinding('toggle-recording',
this._bindingSettings,
Meta.KeyBindingFlags.NONE,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._toggleRecorder));
},
disable: function() {
global.display.remove_keybinding('toggle-recording');
Main.wm.removeKeybinding('toggle-recording');
},
_ensureRecorder: function() {
@ -41,7 +45,7 @@ const Recorder = new Lang.Class({
recorder.set_framerate(this._recorderSettings.get_int('framerate'));
/* Translators: this is a filename used for screencast recording */
// xgettext:no-c-format
recorder.set_filename(_("Screencast from %d %t") + '.' + this._recorderSettings.get_string('file-extension'));
recorder.set_file_template(_("Screencast from %d %t") + '.' + this._recorderSettings.get_string('file-extension'));
let pipeline = this._recorderSettings.get_string('pipeline');
if (!pipeline.match(/^\s*$/))

View File

@ -383,25 +383,12 @@ const TelepathyClient = new Lang.Class({
}
/* Display notification to ask user to accept/reject request */
let source = this._ensureSubscriptionSource();
let source = this._ensureAppSource();
let notif = new SubscriptionRequestNotification(source, contact);
source.notify(notif);
},
_ensureSubscriptionSource: function() {
if (this._subscriptionSource == null) {
this._subscriptionSource = new MessageTray.Source(_("Subscription request"),
'gtk-dialog-question');
Main.messageTray.add(this._subscriptionSource);
this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
this._subscriptionSource = null;
}));
}
return this._subscriptionSource;
},
_accountConnectionStatusNotifyCb: function(account) {
let connectionError = account.connection_error;
@ -415,7 +402,7 @@ const TelepathyClient = new Lang.Class({
return;
/* Display notification that account failed to connect */
let source = this._ensureAccountSource();
let source = this._ensureAppSource();
notif = new AccountNotification(source, account, connectionError);
this._accountNotifications[account.get_object_path()] = notif;
@ -425,17 +412,16 @@ const TelepathyClient = new Lang.Class({
source.notify(notif);
},
_ensureAccountSource: function() {
if (this._accountSource == null) {
this._accountSource = new MessageTray.Source(_("Connection error"),
'gtk-dialog-error');
Main.messageTray.add(this._accountSource);
this._accountSource.connect('destroy', Lang.bind(this, function () {
this._accountSource = null;
_ensureAppSource: function() {
if (this._appSource == null) {
this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
Main.messageTray.add(this._appSource);
this._appSource.connect('destroy', Lang.bind(this, function () {
this._appSource = null;
}));
}
return this._accountSource;
return this._appSource;
}
});
@ -492,7 +478,7 @@ const ChatSource = new Lang.Class({
}));
item.connect('activate', Lang.bind(this, function() {
this.setMuted(!this.isMuted);
this.emit('done-displaying-content');
this.emit('done-displaying-content', false);
}));
rightClickMenu.add(item.actor);
return rightClickMenu;
@ -744,8 +730,7 @@ const ChatSource = new Lang.Class({
_ackMessages: function() {
// Don't clear our messages here, tp-glib will send a
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(Lang.bind(this, function(src, result) {
this._channel.ack_all_pending_messages_finish(result);}));
this._channel.ack_all_pending_messages_async(null);
}
});
@ -771,16 +756,19 @@ const ChatNotification = new Lang.Class({
this.emit('unfocused');
}));
this._oldMaxScrollAdjustment = 0;
this._createScrollArea();
this._lastGroup = null;
this._lastGroupActor = null;
// Keep track of the bottom position for the current adjustment and
// force a scroll to the bottom if things change while we were at the
// bottom
this._oldMaxScrollValue = this._scrollArea.vscroll.adjustment.value;
this._scrollArea.add_style_class_name('chat-notification-scrollview');
this._scrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
let currentValue = adjustment.value + adjustment.page_size;
if (currentValue == this._oldMaxScrollAdjustment)
if (adjustment.value == this._oldMaxScrollValue)
this.scrollTo(St.Side.BOTTOM);
this._oldMaxScrollAdjustment = adjustment.upper;
this._oldMaxScrollValue = Math.max(adjustment.lower, adjustment.upper - adjustment.page_size);
}));
this._inputHistory = new History.HistoryManager({ entry: this._responseEntry.clutter_text });
@ -938,26 +926,24 @@ const ChatNotification = new Lang.Class({
}
// Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){
/* Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"*/
/* Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/
// xgettext:no-c-format
format = _("<b>%H:%M</b> on Yesterday");
format = _("<b>Yesterday</b>, <b>%H:%M</b>");
}
// Show a week day and time if date is in the last week
else if (daysAgo < 7) {
/* Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday*/
/* Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/
// xgettext:no-c-format
format = _("<b>%H:%M</b> on <b>%A</b>");
format = _("<b>%A</b>, <b>%H:%M</b>");
} else if (date.getYear() == now.getYear()) {
/* Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
shown when you get a chat message in the same year */
/* Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/
// xgettext:no-c-format
format = _("<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>");
format = _("<b>%B</b> <b>%d</b>, <b>%H:%M</b>");
} else {
/* Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
shown when you get a chat message in a different year */
/* Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/
// xgettext:no-c-format
format = _("<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y");
format = _("<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> ");
}
return date.toLocaleFormat(format);
@ -1133,7 +1119,7 @@ const AudioVideoNotification = new Lang.Class({
this.parent(source, title, null, { customContent: true });
this.setResident(true);
this.addButton('reject', _("Reject"));
this.addButton('reject', _("Decline"));
/* translators: this is a button label (verb), not a noun */
this.addButton('answer', _("Answer"));
@ -1350,26 +1336,16 @@ const AccountNotification = new Lang.Class({
this.parent(source,
/* translators: argument is the account name, like
* name@jabber.org for example. */
_("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true });
this._label = new St.Label();
this.addActor(this._label);
this._updateMessage(connectionError);
_("Unable to connect to %s").format(account.get_display_name()),
this._getMessage(connectionError));
this._account = account;
this.addButton('reconnect', _("Reconnect"));
this.addButton('edit', _("Edit account"));
this.addButton('view', _("View account"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) {
case 'reconnect':
// If it fails again, a new notification should pop up with the
// new error.
account.reconnect_async(null);
break;
case 'edit':
case 'view':
let cmd = '/usr/bin/empathy-accounts'
+ ' --select-account=%s'
.format(account.get_path_suffix());
@ -1395,19 +1371,19 @@ const AccountNotification = new Lang.Class({
if (status == Tp.ConnectionStatus.CONNECTED) {
this.destroy();
} else if (status == Tp.ConnectionStatus.DISCONNECTED) {
this._updateMessage(account.connection_error);
this.update(this.title, this._getMessage(account.connection_error));
}
}));
},
_updateMessage: function(connectionError) {
_getMessage: function(connectionError) {
let message;
if (connectionError in _connectionErrorMessages) {
message = _connectionErrorMessages[connectionError];
} else {
message = _("Unknown reason");
}
this._label.set_text(message);
return message;
},
destroy: function() {

View File

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

View File

@ -23,8 +23,7 @@ const DASH_ITEM_HOVER_TIMEOUT = 300;
function getAppFromSource(source) {
if (source instanceof AppDisplay.AppWellIcon) {
let appSystem = Shell.AppSystem.get_default();
return appSystem.lookup_app(source.getId());
return source.app;
} else if (source.metaWindow) {
let tracker = Shell.WindowTracker.get_default();
return tracker.get_window_app(source.metaWindow);
@ -142,6 +141,7 @@ const DashItemContainer = new Lang.Class({
setLabelText: function(text) {
this._labelText = text;
this.child.accessible_name = text;
},
hideLabel: function () {
@ -259,7 +259,6 @@ const ShowAppsIcon = new Lang.Class({
this.setChild(this.toggleButton);
this.setDragApp(null);
this.toggleButton.label_actor = this.label;
},
_createIcon: function(size) {
@ -492,32 +491,51 @@ const Dash = new Lang.Class({
},
_createAppItem: function(app) {
let display = new AppDisplay.AppWellIcon(app,
let appIcon = new AppDisplay.AppWellIcon(app,
{ setSizeManually: true,
showLabel: false });
display._draggable.connect('drag-begin',
appIcon._draggable.connect('drag-begin',
Lang.bind(this, function() {
display.actor.opacity = 50;
appIcon.actor.opacity = 50;
}));
display._draggable.connect('drag-end',
appIcon._draggable.connect('drag-end',
Lang.bind(this, function() {
display.actor.opacity = 255;
appIcon.actor.opacity = 255;
}));
appIcon.connect('menu-state-changed',
Lang.bind(this, function(appIcon, opened) {
this._itemMenuStateChanged(item, opened);
}));
let item = new DashItemContainer();
item.setChild(display.actor);
item.setChild(appIcon.actor);
// Override default AppWellIcon label_actor, now the
// accessible_name is set at DashItemContainer.setLabelText
appIcon.actor.label_actor = null;
item.setLabelText(app.get_name());
// Override default AppWellIcon label_actor
display.actor.label_actor = item.label;
display.icon.setIconSize(this.iconSize);
appIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(item);
return item;
},
_itemMenuStateChanged: function(item, opened) {
// When the menu closes, it calls sync_hover, which means
// that the notify::hover handler does everything we need to.
if (opened) {
if (this._showLabelTimeoutId > 0) {
Mainloop.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0;
}
item.hideLabel();
}
},
_onHover: function (item) {
if (item.child.get_hover() && !item.child._delegate.isMenuUp) {
if (item.child.get_hover()) {
if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
@ -619,8 +637,10 @@ const Dash = new Lang.Class({
icon.setIconSize(this.iconSize);
// Don't animate the icon size change when the overview
// is not visible or when initially filling the dash
if (!Main.overview.visible || !this._shownInitially)
// is transitioning, not visible or when initially filling
// the dash
if (!Main.overview.visible || Main.overview.animationInProgress ||
!this._shownInitially)
continue;
let [targetWidth, targetHeight] = icon.icon.get_size();
@ -744,8 +764,9 @@ const Dash = new Lang.Class({
for (let i = 0; i < removedActors.length; i++) {
let item = removedActors[i]._delegate;
// Don't animate item removal when the overview is hidden
if (Main.overview.visible)
// Don't animate item removal when the overview is transitioning
// or hidden
if (Main.overview.visible && !Main.overview.animationInProgress)
item.animateOutAndDestroy();
else
item.destroy();
@ -760,8 +781,9 @@ const Dash = new Lang.Class({
return;
}
// Don't animate item addition when the overview is hidden
if (!Main.overview.visible)
// Don't animate item addition when the overview is transitioning
// or hidden
if (!Main.overview.visible || Main.overview.animationInProgress)
return;
for (let i = 0; i < addedItems.length; i++)

View File

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

View File

@ -105,7 +105,7 @@ const restartDialogContent = {
endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }],
iconName: 'system-shutdown-symbolic',
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};

View File

@ -126,13 +126,10 @@ function logExtensionError(uuid, error) {
let message = '' + error;
if (error.state)
extension.state = error.state;
else
extension.state = ExtensionState.ERROR;
extension.state = ExtensionState.ERROR;
if (!extension.errors)
extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message));
_signals.emit('extension-state-changed', { uuid: uuid,
@ -145,18 +142,16 @@ function loadExtension(extension) {
extension.state = ExtensionState.ERROR;
if (ExtensionUtils.isOutOfDate(extension)) {
let error = new Error('extension is not compatible with current GNOME Shell and/or GJS version');
error.state = ExtensionState.OUT_OF_DATE;
throw error;
}
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
if (enabled) {
initExtension(extension.uuid);
if (extension.state == ExtensionState.DISABLED)
enableExtension(extension.uuid);
extension.state = ExtensionState.OUT_OF_DATE;
} else {
extension.state = ExtensionState.INITIALIZED;
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
if (enabled) {
initExtension(extension.uuid);
if (extension.state == ExtensionState.DISABLED)
enableExtension(extension.uuid);
} else {
extension.state = ExtensionState.INITIALIZED;
}
}
_signals.emit('extension-state-changed', extension);
@ -217,8 +212,16 @@ function initExtension(uuid) {
_signals.emit('extension-loaded', uuid);
}
function getEnabledExtensions() {
let extensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
if (!Array.isArray(Main.sessionMode.enabledExtensions))
return extensions;
return Main.sessionMode.enabledExtensions.concat(extensions);
}
function onEnabledExtensionsChanged() {
let newEnabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
let newEnabledExtensions = getEnabledExtensions();
if (!enabled)
return;
@ -252,7 +255,7 @@ function onEnabledExtensionsChanged() {
function _loadExtensions() {
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
enabledExtensions = getEnabledExtensions();
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', function(signals, extension) {
@ -294,10 +297,17 @@ function disableAllExtensions() {
}
function _sessionUpdated() {
if (Main.sessionMode.allowExtensions)
// For now sessionMode.allowExtensions controls extensions from both the
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (initted)
onEnabledExtensionsChanged();
enableAllExtensions();
else
} else {
disableAllExtensions();
}
}
function init() {

View File

@ -23,6 +23,7 @@ function _navigateActor(actor) {
// GrabHelper:
// @owner: the actor that owns the GrabHelper
// @params: optional parameters to pass to Main.pushModal()
//
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
// associated with a set of actors.
@ -34,14 +35,14 @@ function _navigateActor(actor) {
const GrabHelper = new Lang.Class({
Name: 'GrabHelper',
_init: function(owner) {
_init: function(owner, params) {
this._owner = owner;
this._modalParams = params;
this._grabStack = [];
this._actors = [];
this._capturedEventId = 0;
this._eventId = 0;
this._keyFocusNotifyId = 0;
this._focusWindowChangedId = 0;
this._ignoreRelease = false;
@ -76,9 +77,12 @@ const GrabHelper = new Lang.Class({
},
_isWithinGrabbedActor: function(actor) {
let currentActor = this.currentGrab.actor;
while (actor) {
if (this._actors.indexOf(actor) != -1)
return true;
if (actor == currentActor)
return true;
actor = actor.get_parent();
}
return false;
@ -88,6 +92,14 @@ const GrabHelper = new Lang.Class({
return this._grabStack[this._grabStack.length - 1] || {};
},
get grabbed() {
return this._grabStack.length > 0;
},
get grabStack() {
return this._grabStack;
},
_findStackIndex: function(actor) {
if (!actor)
return -1;
@ -99,6 +111,16 @@ const GrabHelper = new Lang.Class({
return -1;
},
_actorInGrabStack: function(actor) {
while (actor) {
let idx = this._findStackIndex(actor);
if (idx >= 0)
return idx;
actor = actor.get_parent();
}
return -1;
},
isActorGrabbed: function(actor) {
return this._findStackIndex(actor) >= 0;
},
@ -138,6 +160,7 @@ const GrabHelper = new Lang.Class({
params = Params.parse(params, { actor: null,
modal: false,
grabFocus: false,
focus: null,
onUngrab: null });
let focus = global.stage.key_focus;
@ -155,7 +178,9 @@ const GrabHelper = new Lang.Class({
if (params.grabFocus && !this._takeFocusGrab(hadFocus))
return false;
if (hadFocus || params.grabFocus)
if (params.focus)
params.focus.grab_key_focus();
else if (hadFocus || params.grabFocus)
_navigateActor(newFocus);
this._grabStack.push(params);
@ -165,11 +190,10 @@ const GrabHelper = new Lang.Class({
_takeModalGrab: function() {
let firstGrab = (this._modalCount == 0);
if (firstGrab) {
if (!Main.pushModal(this._owner))
if (!Main.pushModal(this._owner, this._modalParams))
return false;
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
}
this._modalCount++;
@ -186,11 +210,6 @@ const GrabHelper = new Lang.Class({
this._capturedEventId = 0;
}
if (this._eventId > 0) {
global.stage.disconnect(this._eventId);
this._eventId = 0;
}
Main.popModal(this._owner);
global.sync_pointer();
},
@ -202,7 +221,6 @@ const GrabHelper = new Lang.Class({
this._grabbedFromKeynav = hadFocus;
this._preGrabInputMode = global.stage_input_mode;
this._prevFocusedWindow = metaDisplay.focus_window;
if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
@ -241,13 +259,7 @@ const GrabHelper = new Lang.Class({
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
}
if (this._prevFocusedWindow) {
let metaDisplay = global.screen.get_display();
if (!metaDisplay.focus_window) {
metaDisplay.set_input_focus_window(this._prevFocusedWindow,
false, global.get_current_time());
}
}
global.screen.focus_default_window(global.get_current_time());
},
// ignoreRelease:
@ -268,7 +280,8 @@ const GrabHelper = new Lang.Class({
// If the actor that was popped from the grab stack was not the actor
// That was passed in, this call is ignored.
ungrab: function(params) {
params = Params.parse(params, { actor: this.currentGrab.actor });
params = Params.parse(params, { actor: this.currentGrab.actor,
isUser: false });
let grabStackIndex = this._findStackIndex(params.actor);
if (grabStackIndex < 0)
@ -286,7 +299,7 @@ const GrabHelper = new Lang.Class({
let poppedGrab = poppedGrabs[i];
if (poppedGrab.onUngrab)
poppedGrab.onUngrab();
poppedGrab.onUngrab(params.isUser);
if (poppedGrab.modal)
this._releaseModalGrab();
@ -309,12 +322,18 @@ const GrabHelper = new Lang.Class({
if (release && this._ignoreRelease) {
this._ignoreRelease = false;
return false;
return true;
}
if (!button && this._modalCount == 0)
return false;
if (type == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab({ isUser: true });
return true;
}
if (this._isWithinGrabbedActor(event.get_source()))
return false;
@ -326,33 +345,22 @@ const GrabHelper = new Lang.Class({
// which should be a release event.
if (press)
this._ignoreRelease = true;
this.ungrab({ actor: this._grabStack[0].actor });
let i = this._actorInGrabStack(event.get_source()) + 1;
this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
}
return this._modalCount > 0;
},
// We catch 'event' rather than 'key-press-event' so that we get
// a chance to run before the overview's own Escape check
_onEvent: function(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab();
return true;
}
return false;
},
_onKeyFocusChanged: function() {
let focus = global.stage.key_focus;
if (!focus || !this._isWithinGrabbedActor(focus))
this.ungrab();
this.ungrab({ isUser: true });
},
_focusWindowChanged: function() {
let metaDisplay = global.screen.get_display();
if (metaDisplay.focus_window != null)
this.ungrab();
this.ungrab({ isUser: true });
}
});

View File

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

View File

@ -20,25 +20,6 @@ const KEYBOARD_TYPE = 'keyboard-type';
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
// Key constants taken from Antler
// FIXME: ought to be moved into libcaribou
const PRETTY_KEYS = {
'BackSpace': '\u232b',
'space': ' ',
'Return': '\u23ce',
'Caribou_Prefs': '\u2328',
'Caribou_ShiftUp': '\u2b06',
'Caribou_ShiftDown': '\u2b07',
'Caribou_Emoticons': '\u263a',
'Caribou_Symbols': '123',
'Caribou_Symbols_More': '{#*',
'Caribou_Alpha': 'Abc',
'Tab': 'Tab',
'Escape': 'Esc',
'Control_L': 'Ctrl',
'Alt_L': 'Alt'
};
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
<method name='Show'>
<arg type='u' direction='in' />
@ -98,17 +79,7 @@ const Key = new Lang.Class({
},
_makeKey: function () {
let label = this._key.name;
if (label.length > 1) {
let pretty = PRETTY_KEYS[label];
if (pretty)
label = pretty;
else
label = this._getUnichar(this._key);
}
label = GLib.markup_escape_text(label, -1);
let label = GLib.markup_escape_text(this._key.label, -1);
let button = new St.Button ({ label: label,
style_class: 'keyboard-key' });
@ -280,7 +251,7 @@ const Keyboard = new Lang.Class({
this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
if (show)
this.show();
this.show(Main.layoutManager.focusIndex);
else
this._createSource();
},
@ -404,7 +375,7 @@ const Keyboard = new Lang.Class({
if (!this._enableKeyboard)
return;
let monitor = Main.layoutManager.bottomMonitor;
let monitor = Main.layoutManager.keyboardMonitor;
let maxHeight = monitor.height / 3;
this.actor.width = monitor.width;
@ -491,9 +462,9 @@ const Keyboard = new Lang.Class({
actor._extended_keys || actor.extended_key;
},
show: function () {
show: function (monitor) {
Main.layoutManager.keyboardIndex = monitor;
this._redraw();
Main.layoutManager.showKeyboard();
this._destroySource();
},
@ -541,7 +512,7 @@ const Keyboard = new Lang.Class({
if (timestamp != Clutter.CURRENT_TIME)
this._timestamp = timestamp;
this.show();
this.show(Main.layoutManager.focusIndex);
},
Hide: function(timestamp) {
@ -595,6 +566,7 @@ const KeyboardSource = new Lang.Class({
},
open: function() {
this._keyboard.show();
// Show the OSK below the message tray
this._keyboard.show(Main.layoutManager.bottomIndex);
}
});

View File

@ -103,8 +103,9 @@ const LayoutManager = new Lang.Class({
this.monitors = [];
this.primaryMonitor = null;
this.primaryIndex = -1;
this._keyboardIndex = -1;
this._hotCorners = [];
this._rootPixmap = null;
this._background = null;
this._leftPanelBarrier = 0;
this._rightPanelBarrier = 0;
this._trayBarrier = 0;
@ -123,13 +124,11 @@ const LayoutManager = new Lang.Class({
this.addChrome(this.panelBox, { affectsStruts: true,
trackFullscreen: true });
this.panelBox.connect('allocation-changed',
Lang.bind(this, this._updatePanelBarriers));
Lang.bind(this, this._panelBoxChanged));
this.trayBox = new St.Widget({ name: 'trayBox',
layout_manager: new Clutter.BinLayout() });
this.addChrome(this.trayBox);
this.trayBox.connect('allocation-changed',
Lang.bind(this, this._updateTrayBarrier));
this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
reactive: true,
@ -242,9 +241,8 @@ const LayoutManager = new Lang.Class({
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelBox.set_size(this.primaryMonitor.width, -1);
this.keyboardBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height);
this.keyboardBox.set_size(this.bottomMonitor.width, -1);
if (this.keyboardIndex < 0)
this.keyboardIndex = this.primaryIndex;
this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height);
@ -258,6 +256,11 @@ const LayoutManager = new Lang.Class({
this.bottomMonitor.width, this.bottomMonitor.height);
},
_panelBoxChanged: function() {
this.emit('panel-box-changed');
this._updatePanelBarriers();
},
_updatePanelBarriers: function() {
if (this._leftPanelBarrier)
global.destroy_pointer_barrier(this._leftPanelBarrier);
@ -280,22 +283,6 @@ const LayoutManager = new Lang.Class({
}
},
_updateTrayBarrier: function() {
let monitor = this.bottomMonitor;
if (this._trayBarrier)
global.destroy_pointer_barrier(this._trayBarrier);
if (Main.messageTray) {
this._trayBarrier =
global.create_pointer_barrier(monitor.x + monitor.width, monitor.y + monitor.height - Main.messageTray.actor.height,
monitor.x + monitor.width, monitor.y + monitor.height,
4 /* BarrierNegativeX */);
} else {
this._trayBarrier = 0;
}
},
_monitorsChanged: function() {
this._updateMonitors();
this._updateBoxes();
@ -323,8 +310,44 @@ const LayoutManager = new Lang.Class({
return this.monitors[index];
},
get keyboardMonitor() {
return this.monitors[this.keyboardIndex];
},
get focusIndex() {
let i = Main.layoutManager.primaryIndex;
if (global.stage_input_mode == Shell.StageInputMode.FOCUSED ||
global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) {
let focusActor = global.stage.key_focus;
if (focusActor)
i = this._chrome.findIndexForActor(focusActor);
} else {
let focusWindow = global.display.focus_window;
if (focusWindow)
i = this._chrome.findIndexForWindow(focusWindow);
}
return i;
},
get focusMonitor() {
return this.monitors[this.focusIndex];
},
set keyboardIndex(v) {
this._keyboardIndex = v;
this.keyboardBox.set_position(this.keyboardMonitor.x,
this.keyboardMonitor.y + this.keyboardMonitor.height);
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
},
get keyboardIndex() {
return this._keyboardIndex;
},
_startupAnimation: function() {
this.panelBox.anchor_y = this.panelBox.height;
this.panelBox.translation_y = -this.panelBox.height;
let plymouthTransitionRunning = false;
@ -333,34 +356,34 @@ const LayoutManager = new Lang.Class({
// to the greeter. Otherwise, we'll just animate the panel,
// as usual.
if (Main.sessionMode.isGreeter) {
this._rootPixmap = global.create_xrootpmap_texture();
if (this._rootPixmap != null) {
Main.uiGroup.add_actor(this._rootPixmap);
Tweener.addTween(this._rootPixmap,
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
if (this._background != null) {
Main.uiGroup.add_actor(this._background);
Tweener.addTween(this._background,
{ opacity: 0,
time: PLYMOUTH_TRANSITION_TIME,
transition: 'linear',
onComplete: this._fadeRootpmapComplete,
onComplete: this._fadeBackgroundComplete,
onCompleteScope: this });
plymouthTransitionRunning = true;
}
}
if (!plymouthTransitionRunning)
this._fadeRootpmapComplete();
this._fadeBackgroundComplete();
},
_fadeRootpmapComplete: function() {
_fadeBackgroundComplete: function() {
// Don't animate the strut
this._chrome.freezeUpdateRegions();
if (this._rootPixmap != null) {
this._rootPixmap.destroy();
this._rootPixmap = null;
if (this._background != null) {
this._background.destroy();
this._background = null;
}
Tweener.addTween(this.panelBox,
{ anchor_y: 0,
{ translation_y: 0,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
@ -369,6 +392,7 @@ const LayoutManager = new Lang.Class({
},
_startupAnimationComplete: function() {
this.emit('panel-box-changed');
this._chrome.thawUpdateRegions();
},
@ -381,11 +405,14 @@ const LayoutManager = new Lang.Class({
onComplete: this._showKeyboardComplete,
onCompleteScope: this
});
Tweener.addTween(this.trayBox,
{ anchor_y: this.keyboardBox.height,
time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad'
});
if (this.keyboardIndex == this.bottomIndex) {
Tweener.addTween(this.trayBox,
{ anchor_y: this.keyboardBox.height,
time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
this.emit('keyboard-visible-changed', true);
},
@ -397,7 +424,8 @@ const LayoutManager = new Lang.Class({
this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
this.keyboardBox.anchor_y = this.keyboardBox.height;
this.trayBox.anchor_y = this.keyboardBox.height;
if (this.keyboardIndex == this.bottomIndex)
this.trayBox.anchor_y = this.keyboardBox.height;
}));
},
@ -413,11 +441,14 @@ const LayoutManager = new Lang.Class({
onComplete: this._hideKeyboardComplete,
onCompleteScope: this
});
Tweener.addTween(this.trayBox,
{ anchor_y: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad'
});
if (this.keyboardIndex == this.bottomIndex) {
Tweener.addTween(this.trayBox,
{ anchor_y: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
this.emit('keyboard-visible-changed', false);
},
@ -481,8 +512,12 @@ const LayoutManager = new Lang.Class({
},
findMonitorForActor: function(actor) {
return this._chrome.findMonitorForActor(actor);
}
return this.monitors[this._chrome.findIndexForActor(actor)];
},
findMonitorForWindow: function(window) {
return this.monitors[this._chrome.findIndexForWindow(window)];
},
});
Signals.addSignalMethods(LayoutManager.prototype);
@ -830,6 +865,7 @@ const Chrome = new Lang.Class({
_relayout: function() {
this._monitors = this._layoutManager.monitors;
this._primaryIndex = this._layoutManager.primaryIndex;
this._primaryMonitor = this._layoutManager.primaryMonitor;
this._updateFullscreen();
@ -845,32 +881,49 @@ const Chrome = new Lang.Class({
let monitor = this._monitors[i];
if (cx >= monitor.x && cx < monitor.x + monitor.width &&
cy >= monitor.y && cy < monitor.y + monitor.height)
return monitor;
return i;
}
// If the center is not on a monitor, return the first overlapping monitor
for (let i = 0; i < this._monitors.length; i++) {
let monitor = this._monitors[i];
if (x + w > monitor.x && x < monitor.x + monitor.width &&
y + h > monitor.y && y < monitor.y + monitor.height)
return monitor;
return i;
}
// otherwise on no monitor
return null;
return -1;
},
_findMonitorForWindow: function(window) {
return this._findMonitorForRect(window.x, window.y, window.width, window.height);
findIndexForWindow: function(window) {
let rect = window.get_input_rect();
let i = this._findMonitorForRect(rect.x, rect.y, rect.width, rect.height);
if (i >= 0)
return i;
return this._primaryIndex; // Not on any monitor, pretend its on the primary
},
// This call guarantees that we return some monitor to simplify usage of it
// In practice all tracked actors should be visible on some monitor anyway
findMonitorForActor: function(actor) {
findIndexForActor: function(actor) {
let [x, y] = actor.get_transformed_position();
let [w, h] = actor.get_transformed_size();
let monitor = this._findMonitorForRect(x, y, w, h);
if (monitor)
return monitor;
return this._primaryMonitor; // Not on any monitor, pretend its on the primary
let i = this._findMonitorForRect(x, y, w, h);
if (i >= 0)
return i;
return this._primaryIndex; // Not on any monitor, pretend its on the primary
},
findMonitorForWindow: function(window) {
let rect = window.get_input_rect();
let i = this._findMonitorForRect(rect.x, rect.y, rect.width, rect.height);
if (i >= 0)
return this._monitors[i];
else
return null;
},
findMonitorForActor: function(actor) {
return this._monitors[this.findIndexForActor(actor)];
},
_queueUpdateRegions: function() {
@ -911,14 +964,15 @@ const Chrome = new Lang.Class({
for (let i = windows.length - 1; i > -1; i--) {
let window = windows[i];
let layer = window.get_meta_window().get_layer();
let metaWindow = window.meta_window;
let layer = metaWindow.get_layer();
// Skip minimized windows
if (!window.showing_on_its_workspace())
continue;
if (layer == Meta.StackLayer.FULLSCREEN) {
let monitor = this._findMonitorForWindow(window);
let monitor = this.findMonitorForWindow(metaWindow);
if (monitor)
monitor.inFullscreen = true;
}
@ -935,7 +989,7 @@ const Chrome = new Lang.Class({
}
// Or whether it is monitor sized
let monitor = this._findMonitorForWindow(window);
let monitor = this.findMonitorForWindow(metaWindow);
if (monitor &&
window.x <= monitor.x &&
window.x + window.width >= monitor.x + monitor.width &&

View File

@ -1129,7 +1129,7 @@ const LookingGlass = new Lang.Class({
if (this._open)
return;
if (!Main.pushModal(this._entry))
if (!Main.pushModal(this._entry, { keybindingMode: Main.KeybindingMode.LOOKING_GLASS }))
return;
this._notebook.selectIndex(0);

View File

@ -20,6 +20,7 @@ const Keyboard = imports.ui.keyboard;
const MessageTray = imports.ui.messageTray;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const Params = imports.misc.params;
const RunDialog = imports.ui.runDialog;
const Layout = imports.ui.layout;
const LookingGlass = imports.ui.lookingGlass;
@ -39,6 +40,19 @@ const Util = imports.misc.util;
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
const KeybindingMode = {
NONE: 0, // block all keybindings
NORMAL: 1 << 0, // window mode
OVERVIEW: 1 << 1,
LOCK_SCREEN: 1 << 2,
UNLOCK_SCREEN: 1 << 3,
LOGIN_SCREEN: 1 << 4,
MESSAGE_TRAY: 1 << 5,
SYSTEM_MODAL: 1 << 6,
LOOKING_GLASS: 1 << 7,
ALL: ~0,
};
let componentManager = null;
let panel = null;
let overview = null;
@ -55,6 +69,7 @@ let shellDBusService = null;
let shellMountOpDBusService = null;
let screenSaverDBus = null;
let modalCount = 0;
let keybindingMode = KeybindingMode.NORMAL;
let modalActorFocusStack = [];
let uiGroup = null;
let magnifier = null;
@ -69,7 +84,17 @@ let _overridesSettings = null;
let background = null;
function _sessionUpdated() {
Meta.keybindings_set_custom_handler('panel-run-dialog', sessionMode.hasRunDialog ? openRunDialog : null);
wm.setCustomKeybindingHandler('panel-main-menu',
KeybindingMode.NORMAL |
KeybindingMode.OVERVIEW,
sessionMode.hasOverview ? Lang.bind(overview, overview.toggle) : null);
wm.allowKeybinding('overlay-key', KeybindingMode.NORMAL |
KeybindingMode.OVERVIEW);
wm.setCustomKeybindingHandler('panel-run-dialog',
KeybindingMode.NORMAL |
KeybindingMode.OVERVIEW,
sessionMode.hasRunDialog ? openRunDialog : null);
if (sessionMode.isGreeter)
screenShield.showDialog();
}
@ -136,13 +161,13 @@ function start() {
xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
overview = new Overview.Overview();
wm = new WindowManager.WindowManager();
magnifier = new Magnifier.Magnifier();
if (UnlockDialog.isSupported())
screenShield = new ScreenShield.ScreenShield();
else
screenShield = new ScreenShield.ScreenShieldFallback();
panel = new Panel.Panel();
wm = new WindowManager.WindowManager();
messageTray = new MessageTray.MessageTray();
keyboard = new Keyboard.Keyboard();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
@ -155,10 +180,8 @@ function start() {
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1);
Meta.keybindings_set_custom_handler('panel-main-menu', Lang.bind(overview, overview.toggle));
global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
sessionMode.connect('update', _sessionUpdated);
sessionMode.connect('updated', _sessionUpdated);
_sessionUpdated();
// Provide the bus object for gnome-session to
@ -167,8 +190,6 @@ function start() {
_startDate = new Date();
global.stage.connect('captured-event', _globalKeyPressHandler);
log('GNOME Shell started at ' + _startDate);
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
@ -465,80 +486,6 @@ function getWindowActorsForWorkspace(workspaceIndex) {
});
}
// This function encapsulates hacks to make certain global keybindings
// work even when we are in one of our modes where global keybindings
// are disabled with a global grab. (When there is a global grab, then
// all key events will be delivered to the stage, so ::captured-event
// on the stage can be used for global keybindings.)
function _globalKeyPressHandler(actor, event) {
if (modalCount == 0)
return false;
if (event.type() != Clutter.EventType.KEY_PRESS)
return false;
if (!sessionMode.allowKeybindingsWhenModal) {
if (modalCount > (overview.visible ? 1 : 0))
return false;
}
let symbol = event.get_key_symbol();
let keyCode = event.get_key_code();
let ignoredModifiers = global.display.get_ignored_modifier_mask();
let modifierState = event.get_state() & ~ignoredModifiers;
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = global.display.get_keybinding_action(keyCode, modifierState);
if (action == Meta.KeyBindingAction.SWITCH_PANELS) {
ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK,
modifierState);
return true;
}
switch (action) {
// left/right would effectively act as synonyms for up/down if we enabled them;
// but that could be considered confusing; we also disable them in the main view.
//
// case Meta.KeyBindingAction.WORKSPACE_LEFT:
// if (!sessionMode.hasWorkspaces)
// return false;
//
// wm.actionMoveWorkspaceLeft();
// return true;
// case Meta.KeyBindingAction.WORKSPACE_RIGHT:
// if (!sessionMode.hasWorkspaces)
// return false;
//
// wm.actionMoveWorkspaceRight();
// return true;
case Meta.KeyBindingAction.WORKSPACE_UP:
if (!sessionMode.hasWorkspaces)
return false;
wm.actionMoveWorkspace(Meta.MotionDirection.UP);
return true;
case Meta.KeyBindingAction.WORKSPACE_DOWN:
if (!sessionMode.hasWorkspaces)
return false;
wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
return true;
case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
case Meta.KeyBindingAction.COMMAND_2:
if (!sessionMode.hasRunDialog)
return false;
openRunDialog();
return true;
case Meta.KeyBindingAction.PANEL_MAIN_MENU:
case Meta.KeyBindingAction.OVERLAY_KEY:
overview.hide();
return true;
}
return false;
}
function _findModal(actor) {
for (let i = 0; i < modalActorFocusStack.length; i++) {
if (modalActorFocusStack[i].actor == actor)
@ -554,7 +501,7 @@ function isInModalStack(actor) {
/**
* pushModal:
* @actor: #ClutterActor which will be given keyboard focus
* @timestamp: optional timestamp
* @params: optional parameters
*
* Ensure we are in a mode where all keyboard and mouse input goes to
* the stage, and focus @actor. Multiple calls to this function act in
@ -565,21 +512,27 @@ function isInModalStack(actor) {
* modal stack returns to this actor, reset the focus to the actor
* which was focused at the time pushModal() was invoked.
*
* @timestamp is optionally used to associate the call with a specific user
* initiated event. If not provided then the value of
* global.get_current_time() is assumed.
* @params may be used to provide the following parameters:
* - timestamp: used to associate the call with a specific user initiated
* event. If not provided then the value of
* global.get_current_time() is assumed.
*
* @options: optional Meta.ModalOptions flags to indicate that the
* pointer is alrady grabbed
* - options: Meta.ModalOptions flags to indicate that the pointer is
* already grabbed
*
* - keybindingMode: used to set the current Main.KeybindingMode to filter
* global keybindings; the default of NONE will filter
* out all keybindings
*
* Returns: true iff we successfully acquired a grab or already had one
*/
function pushModal(actor, timestamp, options) {
if (timestamp == undefined)
timestamp = global.get_current_time();
function pushModal(actor, params) {
params = Params.parse(params, { timestamp: global.get_current_time(),
options: 0,
keybindingMode: KeybindingMode.NONE });
if (modalCount == 0) {
if (!global.begin_modal(timestamp, options ? options : 0)) {
if (!global.begin_modal(params.timestamp, params.options)) {
log('pushModal: invocation of begin_modal failed');
return false;
}
@ -606,8 +559,10 @@ function pushModal(actor, timestamp, options) {
modalActorFocusStack.push({ actor: actor,
focus: curFocus,
destroyId: actorDestroyId,
focusDestroyId: curFocusDestroyId });
focusDestroyId: curFocusDestroyId,
keybindingMode: keybindingMode });
keybindingMode = params.keybindingMode;
global.stage.set_key_focus(actor);
return true;
}
@ -634,6 +589,7 @@ function popModal(actor, timestamp) {
global.stage.set_key_focus(null);
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
keybindingMode = KeybindingMode.NORMAL;
throw new Error('incorrect pop');
}
@ -646,6 +602,7 @@ function popModal(actor, timestamp) {
if (focusIndex == modalActorFocusStack.length - 1) {
if (record.focus)
record.focus.disconnect(record.focusDestroyId);
keybindingMode = record.keybindingMode;
global.stage.set_key_focus(record.focus);
} else {
let t = modalActorFocusStack[modalActorFocusStack.length - 1];
@ -655,6 +612,7 @@ function popModal(actor, timestamp) {
for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
modalActorFocusStack[i].keybindingMode = modalActorFocusStack[i - 1].keybindingMode;
}
}
modalActorFocusStack.splice(focusIndex, 1);
@ -665,6 +623,7 @@ function popModal(actor, timestamp) {
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
Meta.enable_unredirect_for_screen(global.screen);
keybindingMode = KeybindingMode.NORMAL;
}
function createLookingGlass() {

View File

@ -314,6 +314,7 @@ const Notification = new Lang.Class({
this.resident = false;
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
this.isTransient = false;
this.forFeedback = false;
this.expanded = false;
this.focused = false;
this.acknowledged = false;
@ -713,6 +714,10 @@ const Notification = new Lang.Class({
this.isTransient = isTransient;
},
setForFeedback: function(forFeedback) {
this.forFeedback = forFeedback;
},
setUseActionIcons: function(useIcons) {
this._useActionIcons = useIcons;
},
@ -1083,14 +1088,14 @@ const Source = new Lang.Class({
item = new PopupMenu.PopupMenuItem(_("Open"));
item.connect('activate', Lang.bind(this, function() {
this.open();
this.emit('done-displaying-content');
this.emit('done-displaying-content', true);
}));
rightClickMenu.add(item.actor);
item = new PopupMenu.PopupMenuItem(_("Remove"));
item.connect('activate', Lang.bind(this, function() {
this.destroy();
this.emit('done-displaying-content');
this.emit('done-displaying-content', false);
}));
rightClickMenu.add(item.actor);
return rightClickMenu;
@ -1237,12 +1242,6 @@ const SummaryItem = new Lang.Class({
this.notificationStackWidget = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._closeButton = makeCloseButton();
this._closeButton.connect('clicked', Lang.bind(this, function() {
source.destroy();
source.emit('done-displaying-content');
}));
this.notificationStackView = new St.ScrollView({ style_class: source.isChat ? '' : 'summary-notification-stack-scrollview',
vscrollbar_policy: source.isChat ? Gtk.PolicyType.NEVER : Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER });
@ -1251,7 +1250,9 @@ const SummaryItem = new Lang.Class({
vertical: true });
this.notificationStackView.add_actor(this.notificationStack);
this.notificationStackWidget.add_actor(this.notificationStackView);
this.notificationStackWidget.add_actor(this._closeButton);
this.closeButton = makeCloseButton();
this.notificationStackWidget.add_actor(this.closeButton);
this._stackedNotifications = [];
this._oldMaxScrollAdjustment = 0;
@ -1268,14 +1269,6 @@ const SummaryItem = new Lang.Class({
global.focus_manager.add_group(this.rightClickMenu);
},
get closeButtonVisible() {
return this._closeButton.visible;
},
set closeButtonVisible(v) {
this._closeButton.visible = v;
},
_onKeyPress: function(actor, event) {
if (event.get_key_symbol() == Clutter.KEY_Up) {
actor.emit('clicked', 1);
@ -1348,7 +1341,7 @@ const SummaryItem = new Lang.Class({
},
_notificationDoneDisplaying: function() {
this.source.emit('done-displaying-content');
this.source.emit('done-displaying-content', true);
},
_notificationDestroyed: function(notification) {
@ -1401,6 +1394,8 @@ const MessageTray = new Lang.Class({
y_expand: true,
x_expand: true,
layout_manager: new Clutter.BinLayout() });
this._notificationWidget.connect('key-release-event', Lang.bind(this, this._onNotificationKeyRelease));
this.actor.add_actor(this._notificationWidget);
this._notificationBin = new St.Bin({ y_expand: true });
@ -1417,7 +1412,7 @@ const MessageTray = new Lang.Class({
actor.grab_key_focus();
}));
global.focus_manager.add_group(this.actor);
this._summary = new St.BoxLayout({ name: 'summary-mode',
this._summary = new St.BoxLayout({ style_class: 'message-tray-summary',
reactive: true,
track_hover: true,
x_align: Clutter.ActorAlign.END,
@ -1446,11 +1441,10 @@ const MessageTray = new Lang.Class({
this._clickedSummaryItem = null;
this._clickedSummaryItemMouseButton = -1;
this._clickedSummaryItemAllocationChangedId = 0;
this._pointerBarrier = 0;
this._closeButton = makeCloseButton();
this._closeButton.hide();
this._closeButton.connect('clicked', Lang.bind(this, this._onCloseClicked));
this._closeButton.connect('clicked', Lang.bind(this, this._closeNotification));
this._notificationWidget.add_actor(this._closeButton);
this._idleMonitorBecameActiveId = 0;
@ -1458,7 +1452,8 @@ const MessageTray = new Lang.Class({
this.idleMonitor = new GnomeDesktop.IdleMonitor();
this._grabHelper = new GrabHelper.GrabHelper(this.actor);
this._grabHelper = new GrabHelper.GrabHelper(this.actor,
{ keybindingMode: Main.KeybindingMode.MESSAGE_TRAY });
this._grabHelper.addActor(this._summaryBoxPointer.actor);
this._grabHelper.addActor(this.actor);
if (Main.panel.statusArea.activities)
@ -1475,6 +1470,7 @@ const MessageTray = new Lang.Class({
this._pointerInTray = false;
this._pointerInKeyboard = false;
this._keyboardVisible = false;
this._keyboardUnderMessageTray = false;
this._summaryState = State.HIDDEN;
this._pointerInSummary = false;
this._notificationClosed = false;
@ -1489,6 +1485,7 @@ const MessageTray = new Lang.Class({
this._reNotifyAfterHideNotification = null;
this._inFullscreen = false;
this._desktopClone = null;
this._inCtrlAltTab = false;
this._lightbox = new Lightbox.Lightbox(global.window_group,
{ inhibitEvents: true,
@ -1522,10 +1519,20 @@ const MessageTray = new Lang.Class({
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
global.display.add_keybinding('toggle-message-tray',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Lang.bind(this, this.toggleAndNavigate));
Main.wm.addKeybinding('toggle-message-tray',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.MESSAGE_TRAY |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this.toggleAndNavigate));
Main.wm.addKeybinding('focus-active-notification',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.MESSAGE_TRAY |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._expandActiveNotification));
this._summaryItems = [];
this._chatSummaryItemsCount = 0;
@ -1537,15 +1544,34 @@ const MessageTray = new Lang.Class({
this._trayDwellUserTime = 0;
this._sessionUpdated();
this._updateNoMessagesLabel();
},
_updateNoMessagesLabel: function() {
if (this._summaryItems.length == 0 && !this._noMessages) {
this._noMessages = new St.Label({ text: _("No Messages"),
style_class: 'no-messages-label',
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this.actor.add_actor(this._noMessages);
} else if (this._summaryItems.length > 0 && this._noMessages) {
this._noMessages.destroy();
this._noMessages = null;
}
},
_sessionUpdated: function() {
if (Main.sessionMode.isLocked || Main.sessionMode.isGreeter)
if ((Main.sessionMode.isLocked || Main.sessionMode.isGreeter) && this._inCtrlAltTab) {
Main.ctrlAltTabManager.removeGroup(this._summary);
else
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'start-here-symbolic',
this._inCtrlAltTab = false;
} else if (!this._inCtrlAltTab) {
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic',
{ focusCallback: Lang.bind(this, this.toggleAndNavigate),
sortGroup: CtrlAltTab.SortGroup.BOTTOM });
this._inCtrlAltTab = true;
}
this._updateState();
},
@ -1583,6 +1609,8 @@ const MessageTray = new Lang.Class({
},
_trayDwellTimeout: function() {
this._trayDwellTimeoutId = 0;
if (Main.modalCount > 0)
return false;
@ -1593,22 +1621,29 @@ const MessageTray = new Lang.Class({
if (currentUserTime != this._trayDwellUserTime)
return false;
this._trayDwellTimeoutId = 0;
this._traySummoned = true;
this._updateState();
return false;
},
_onCloseClicked: function() {
_onNotificationKeyRelease: function(actor, event) {
let ignoredModifiers = global.display.get_ignored_modifier_mask();
let modifierState = event.get_state() & ~ignoredModifiers;
if (event.get_key_symbol() == Clutter.KEY_Escape && modifierState == 0) {
this._closeNotification();
return true;
}
return false;
},
_closeNotification: function() {
if (this._notificationState == State.SHOWN) {
this._closeButton.hide();
this._notificationClosed = true;
this._notification.emit('done-displaying');
if (!this._notification.resident)
this._notification.destroy();
this._updateState();
this._notificationClosed = false;
}
},
@ -1672,6 +1707,8 @@ const MessageTray = new Lang.Class({
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateState(); return false; }));
this.emit('summary-item-added', summaryItem);
this._updateNoMessagesLabel();
},
getSummaryItems: function() {
@ -1704,6 +1741,8 @@ const MessageTray = new Lang.Class({
summaryItemToRemove.actor.destroy();
this._updateNoMessagesLabel();
if (needUpdate)
this._updateState();
},
@ -1889,12 +1928,15 @@ const MessageTray = new Lang.Class({
},
_onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) {
if (this._keyboardVisible == keyboardVisible)
let keyboardUnderMessageTray = layoutManager.keyboardIndex == layoutManager.bottomIndex;
if (this._keyboardVisible == keyboardVisible &&
this._keyboardUnderMesssageTray == keyboardUnderMessageTray)
return;
this._keyboardVisible = keyboardVisible;
this._keyboardUnderMessageTray = keyboardUnderMessageTray;
if (keyboardVisible)
if (keyboardVisible && keyboardUnderMessageTray)
this.actor.add_style_pseudo_class('keyboard');
else
this.actor.remove_style_pseudo_class('keyboard');
@ -1964,8 +2006,9 @@ const MessageTray = new Lang.Class({
// Notifications
let notificationQueue = this._notificationQueue;
let notificationUrgent = notificationQueue.length > 0 && notificationQueue[0].urgency == Urgency.CRITICAL;
let notificationForFeedback = notificationQueue.length > 0 && notificationQueue[0].forFeedback;
let notificationsLimited = this._busy || this._inFullscreen;
let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent) && Main.sessionMode.hasNotifications;
let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && Main.sessionMode.hasNotifications;
let nextNotification = notificationQueue.length > 0 ? notificationQueue[0] : null;
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
let notificationExpanded = this._notification && this._notification.expanded;
@ -1997,8 +2040,7 @@ const MessageTray = new Lang.Class({
let summaryPinned = this._pointerInTray || summarySummoned || this._locked;
let summaryHovered = this._pointerInTray || this._pointerInSummary;
let notificationsVisible = (this._notificationState == State.SHOWING ||
this._notificationState == State.SHOWN);
let notificationsVisible = this._notificationState != State.HIDDEN;
let notificationsDone = !notificationsVisible && !notificationsPending;
let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered;
@ -2051,12 +2093,12 @@ const MessageTray = new Lang.Class({
this._desktopCloneState == State.SHOWN);
let desktopCloneShouldBeVisible = (trayShouldBeVisible &&
!this._overviewVisible &&
!this._keyboardVisible);
(!this._keyboardVisible || !this._keyboardUnderMessageTray));
if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) {
this._showDesktopClone();
} else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) {
this._hideDesktopClone (this._keyboardVisible);
this._hideDesktopClone (this._keyboardVisible && this._keyboardUnderMessageTray);
}
},
@ -2069,6 +2111,8 @@ const MessageTray = new Lang.Class({
params.onCompleteScope = this;
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
// Remove other tweens that could mess with the state machine
Tweener.removeTweens(actor);
Tweener.addTween(actor, params);
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
@ -2101,9 +2145,8 @@ const MessageTray = new Lang.Class({
transition: 'easeOutQuad'
});
if (this._overviewVisible) {
if (!this._overviewVisible)
this._lightbox.show();
}
return true;
},
@ -2141,6 +2184,10 @@ const MessageTray = new Lang.Class({
},
_hideTray: function() {
// Having the summary item animate out while sliding down the tray
// is distracting, so hide it immediately in case it was visible.
this._summaryBoxPointer.actor.hide();
this._tween(this.actor, '_trayState', State.HIDDEN,
{ y: 0,
time: ANIMATION_TIME,
@ -2219,40 +2266,28 @@ const MessageTray = new Lang.Class({
_updateShowingNotification: function() {
this._notification.acknowledged = true;
Tweener.removeTweens(this._notificationWidget);
// We auto-expand notifications with CRITICAL urgency.
// We use Tweener.removeTweens() to remove a tween that was hiding the notification we are
// updating, in case that notification was in the process of being hidden. However,
// Tweener.removeTweens() would also remove a tween that was updating the position of the
// notification we are updating, in case that notification was already expanded and its height
// changed. Therefore we need to call this._expandNotification() for expanded notifications
// to make sure their position is updated.
if (this._notification.urgency == Urgency.CRITICAL || this._notification.expanded)
if (this._notification.urgency == Urgency.CRITICAL)
this._expandNotification(true);
// We tween all notifications to full opacity. This ensures that both new notifications and
// notifications that might have been in the process of hiding get full opacity.
//
// We tween any notification showing in the banner mode to banner height
// (this._notificationWidget.y = -this._notificationWidget.height).
// We tween any notification showing in the banner mode to the appropriate height
// (which is banner height or expanded height, depending on the notification state)
// This ensures that both new notifications and notifications in the banner mode that might
// have been in the process of hiding are shown with the banner height.
// have been in the process of hiding are shown with the correct height.
//
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
// notification is being shown.
//
// We don't set the y parameter for the tween for expanded notifications because
// this._expandNotification() will result in getting this._notificationWidget.y set to the appropriate
// fully expanded value.
let tweenParams = { opacity: 255,
y: -this._notificationWidget.height,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showNotificationCompleted,
onCompleteScope: this
};
if (!this._notification.expanded)
tweenParams.y = -this._notificationWidget.height;
this._tween(this._notificationWidget, '_notificationState', State.SHOWN, tweenParams);
},
@ -2298,6 +2333,18 @@ const MessageTray = new Lang.Class({
},
_hideNotification: function() {
// HACK!
// There seems to be a reentrancy issue in calling .ungrab() here,
// which causes _updateState to be called before _notificationState
// becomes HIDING. That hides the notification again, nullifying the
// object but not setting _notificationState (and that's the weird part)
// As then _notificationState is stuck into SHOWN but _notification
// is null, every new _updateState fails and the message tray is
// lost forever.
//
// See more at https://bugzilla.gnome.org/show_bug.cgi?id=683986
this._notificationState = State.HIDING;
this._grabHelper.ungrab({ actor: this._notification.actor });
if (this._idleMonitorBecameActiveId) {
@ -2311,6 +2358,7 @@ const MessageTray = new Lang.Class({
}
if (this._notificationRemoved) {
Tweener.removeTweens(this._notificationWidget);
this._notificationWidget.y = this.actor.height;
this._notificationWidget.opacity = 0;
this._notificationState = State.HIDDEN;
@ -2344,6 +2392,13 @@ const MessageTray = new Lang.Class({
notification.destroy(NotificationDestroyedReason.EXPIRED);
},
_expandActiveNotification: function() {
if (!this._notification)
return;
this._expandNotification(false);
},
_expandNotification: function(autoExpanding) {
// Don't grab focus in notifications that are auto-expanded.
if (!autoExpanding)
@ -2367,8 +2422,11 @@ const MessageTray = new Lang.Class({
if (this._notificationWidget.y < expandedY) {
this._notificationWidget.y = expandedY;
} else if (this._notification.y != expandedY) {
// Tween also opacity here, to override a possible tween that's
// currently hiding the notification.
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
{ y: expandedY,
opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
@ -2399,12 +2457,21 @@ const MessageTray = new Lang.Class({
});
},
_onSourceDoneDisplayingContent: function(source, closeTray) {
if (closeTray) {
this._escapeTray();
} else {
this._setClickedSummaryItem(null);
this._updateState();
}
},
_showSummaryBoxPointer: function() {
this._summaryBoxPointerItem = this._clickedSummaryItem;
this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated',
Lang.bind(this, this._onSummaryBoxPointerContentUpdated));
this._sourceDoneDisplayingId = this._summaryBoxPointerItem.source.connect('done-displaying-content',
Lang.bind(this, this._escapeTray));
Lang.bind(this, this._onSourceDoneDisplayingContent));
let hasRightClickMenu = this._summaryBoxPointerItem.rightClickMenu != null;
if (this._clickedSummaryItemMouseButton == 1 || !hasRightClickMenu) {
@ -2420,10 +2487,14 @@ const MessageTray = new Lang.Class({
this._notificationQueue = newQueue;
this._summaryBoxPointer.bin.child = this._summaryBoxPointerItem.notificationStackWidget;
this._summaryBoxPointerItem.closeButtonVisible = true;
let closeButton = this._summaryBoxPointerItem.closeButton;
closeButton.show();
this._summaryBoxPointerCloseClickedId = closeButton.connect('clicked', Lang.bind(this, this._hideSummaryBoxPointer));
this._summaryBoxPointerItem.prepareNotificationStackForShowing();
} else if (this._clickedSummaryItemMouseButton == 3) {
this._summaryBoxPointer.bin.child = this._clickedSummaryItem.rightClickMenu;
this._summaryBoxPointerCloseClickedId = 0;
}
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
@ -2530,6 +2601,10 @@ const MessageTray = new Lang.Class({
this._summaryBoxPointer.bin.child = null;
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
this._summaryBoxPointerContentUpdatedId = 0;
if (this._summaryBoxPointerCloseClickedId != 0) {
this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
this._summaryBoxPointerCloseClickedId = 0;
}
this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
this._summaryBoxPointerDoneDisplayingId = 0;

View File

@ -37,10 +37,12 @@ const ModalDialog = new Lang.Class({
params = Params.parse(params, { shellReactive: false,
styleClass: null,
parentActor: Main.uiGroup,
keybindingMode: Main.KeybindingMode.SYSTEM_MODAL,
shouldFadeIn: true });
this.state = State.CLOSED;
this._hasModal = false;
this._keybindingMode = params.keybindingMode;
this._shellReactive = params.shellReactive;
this._shouldFadeIn = params.shouldFadeIn;
@ -56,7 +58,7 @@ const ModalDialog = new Lang.Class({
this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
this._actionKeys = {};
this._buttonKeys = {};
this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));
this._backgroundBin = new St.Bin();
@ -93,10 +95,10 @@ const ModalDialog = new Lang.Class({
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this._buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
this.buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
visible: false,
vertical: false });
this.dialogLayout.add(this._buttonLayout,
this.dialogLayout.add(this.buttonLayout,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
@ -111,35 +113,17 @@ const ModalDialog = new Lang.Class({
this._group.destroy();
},
setActionKey: function(key, action) {
this._actionKeys[key] = action;
clearButtons: function() {
this.buttonLayout.destroy_all_children();
this._buttonKeys = {};
},
setButtons: function(buttons) {
this._buttonLayout.destroy_all_children();
this._actionKeys = {};
this._buttonLayout.visible = (buttons.length > 0);
this.clearButtons();
this.buttonLayout.visible = (buttons.length > 0);
for (let i = 0; i < buttons.length; i++) {
let buttonInfo = buttons[i];
let label = buttonInfo['label'];
let action = buttonInfo['action'];
let key = buttonInfo['key'];
let isDefault = buttonInfo['default'];
if (isDefault && !key) {
this._actionKeys[Clutter.KEY_KP_Enter] = action;
this._actionKeys[Clutter.KEY_ISO_Enter] = action;
key = Clutter.KEY_Return;
}
buttonInfo.button = new St.Button({ style_class: 'modal-dialog-button',
reactive: true,
can_focus: true,
label: label });
if (isDefault)
buttonInfo.button.add_style_pseudo_class('default');
let x_alignment;
if (buttons.length == 1)
@ -151,29 +135,62 @@ const ModalDialog = new Lang.Class({
else
x_alignment = St.Align.MIDDLE;
if (!this._initialKeyFocusDestroyId)
this._initialKeyFocus = buttonInfo.button;
this._buttonLayout.add(buttonInfo.button,
{ expand: true,
x_fill: false,
y_fill: false,
x_align: x_alignment,
y_align: St.Align.MIDDLE });
buttonInfo.button.connect('clicked', action);
if (key)
this._actionKeys[key] = action;
this.addButton(buttonInfo, { expand: true,
x_fill: false,
y_fill: false,
x_align: x_alignment,
y_align: St.Align.MIDDLE });
}
},
this.emit('buttons-set');
addButton: function(buttonInfo, layoutInfo) {
let label = buttonInfo['label'];
let action = buttonInfo['action'];
let key = buttonInfo['key'];
let isDefault = buttonInfo['default'];
let keys;
if (key)
keys = [key];
else if (isDefault)
keys = [Clutter.KEY_Return, Clutter.KEY_KP_Enter, Clutter.KEY_ISO_Enter];
else
keys = [];
let button = new St.Button({ style_class: 'modal-dialog-button',
reactive: true,
can_focus: true,
label: label });
button.connect('clicked', action);
buttonInfo['button'] = button;
if (isDefault)
button.add_style_pseudo_class('default');
if (!this._initialKeyFocusDestroyId)
this._initialKeyFocus = button;
for (let i in keys)
this._buttonKeys[keys[i]] = buttonInfo;
this.buttonLayout.add(button, layoutInfo);
return button;
},
_onKeyReleaseEvent: function(object, event) {
let symbol = event.get_key_symbol();
let action = this._actionKeys[symbol];
let buttonInfo = this._buttonKeys[symbol];
if (action) {
if (!buttonInfo)
return false;
let button = buttonInfo['button'];
let action = buttonInfo['action'];
if (action && button.reactive) {
action();
return true;
}
@ -226,7 +243,7 @@ const ModalDialog = new Lang.Class({
if (this.state == State.OPENED || this.state == State.OPENING)
return true;
if (!this.pushModal(timestamp))
if (!this.pushModal({ timestamp: timestamp }))
return false;
this._fadeOpen(onPrimary);
@ -276,7 +293,8 @@ const ModalDialog = new Lang.Class({
pushModal: function (timestamp) {
if (this._hasModal)
return true;
if (!Main.pushModal(this._group, timestamp))
if (!Main.pushModal(this._group, { timestamp: timestamp,
keybindingMode: this._keybindingMode }))
return false;
this._hasModal = true;

View File

@ -23,22 +23,25 @@ const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode
const ANIMATION_TIME = 0.25;
// XXX -- grab this automatically. Hard to do.
const DASH_MAX_WIDTH = 96;
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
const SwipeScrollDirection = {
NONE: 0,
HORIZONTAL: 1,
VERTICAL: 2
};
const SwipeScrollResult = {
CANCEL: 0,
SWIPE: 1,
CLICK: 2
};
const GLSL_DIM_EFFECT_DECLARATIONS = '';
const GLSL_DIM_EFFECT_CODE = '\
vec2 dist = cogl_tex_coord_in[0].xy - vec2(0.5, 0.5); \
float elipse_radius = 0.5; \
/* from https://bugzilla.gnome.org/show_bug.cgi?id=669798: \
the alpha on the gradient goes from 250 at its darkest to 180 at its most transparent. */ \
float y = 250.0 / 255.0; \
float x = 180.0 / 255.0; \
/* interpolate darkening value, based on distance from screen center */ \
float val = min(length(dist), elipse_radius); \
float a = mix(x, y, val / elipse_radius); \
/* dim_factor varies from [1.0 -> 0.5] when overview is showing \
We use it to smooth value, then we clamp it to valid color interval */ \
a = clamp(a - cogl_color_in.r + 0.5, 0.0, 1.0); \
/* We\'re blending between: color and black color (obviously omitted in the equation) */ \
cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
cogl_color_out.a = 1.0;';
const ShellInfo = new Lang.Class({
Name: 'ShellInfo',
@ -57,7 +60,14 @@ const ShellInfo = new Lang.Class({
this._source.destroy();
},
setMessage: function(text, undoCallback, undoLabel) {
setMessage: function(text, options) {
options = Params.parse(options, { undoCallback: null,
forFeedback: false
});
let undoCallback = options.undoCallback;
let forFeedback = options.forFeedback;
if (this._source == null) {
this._source = new MessageTray.SystemNotificationSource();
this._source.connect('destroy', Lang.bind(this,
@ -71,6 +81,7 @@ const ShellInfo = new Lang.Class({
if (this._source.notifications.length == 0) {
notification = new MessageTray.Notification(this._source, text, null);
notification.setTransient(true);
notification.setForFeedback(forFeedback);
} else {
notification = this._source.notifications[0];
notification.update(text, null, { clear: true });
@ -78,10 +89,8 @@ const ShellInfo = new Lang.Class({
this._undoCallback = undoCallback;
if (undoCallback) {
notification.addButton('system-undo',
undoLabel ? undoLabel : _("Undo"));
notification.connect('action-invoked',
Lang.bind(this, this._onUndoClicked));
notification.addButton('system-undo', _("Undo"));
notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked));
}
this._source.notify(notification);
@ -93,6 +102,7 @@ const Overview = new Lang.Class({
_init: function() {
this._overviewCreated = false;
this._initCalled = false;
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated();
@ -113,32 +123,26 @@ const Overview = new Lang.Class({
// scenes which allows us to show the background with different
// rendering options without duplicating the texture data.
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
this._background.add_glsl_snippet(Meta.SnippetHook.FRAGMENT,
GLSL_DIM_EFFECT_DECLARATIONS,
GLSL_DIM_EFFECT_CODE,
false);
this._background.hide();
global.overlay_group.add_actor(this._background);
this._desktopFade = new St.Bin();
global.overlay_group.add_actor(this._desktopFade);
this._spacing = 0;
/* Translators: This is the main view to select
activities. See also note for "Activities" string. */
this._group = new St.Widget({ name: 'overview',
accessible_name: _("Overview"),
reactive: true });
this._group._delegate = this;
this._group.connect('style-changed',
Lang.bind(this, function() {
let node = this._group.get_theme_node();
let spacing = node.get_length('spacing');
if (spacing != this._spacing) {
this._spacing = spacing;
this._relayout();
}
}));
this._overview = new St.BoxLayout({ name: 'overview',
accessible_name: _("Overview"),
reactive: true,
vertical: true });
this._overview._delegate = this;
this._group = new St.BoxLayout({ name: 'overview-group' });
this._scrollDirection = SwipeScrollDirection.NONE;
this._scrollAdjustment = null;
this._capturedEventId = 0;
this._buttonPressId = 0;
@ -154,12 +158,11 @@ const Overview = new Lang.Class({
// Dash elements, or mouseover handlers in the workspaces.
this._coverPane = new Clutter.Rectangle({ opacity: 0,
reactive: true });
this._group.add_actor(this._coverPane);
this._overview.add_actor(this._coverPane);
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
this._group.hide();
global.overlay_group.add_actor(this._group);
this._overview.hide();
global.overlay_group.add_actor(this._overview);
this._coverPane.hide();
@ -171,11 +174,16 @@ const Overview = new Lang.Class({
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
global.screen.connect('restacked', Lang.bind(this, this._onRestacked));
this._windowSwitchTimeoutId = 0;
this._windowSwitchTimestamp = 0;
this._lastActiveWorkspaceIndex = -1;
this._lastHoveredWindow = null;
this._needsFakePointerEvent = false;
if (this._initCalled)
this.init();
},
_sessionUpdated: function() {
@ -188,11 +196,20 @@ const Overview = new Lang.Class({
// signal handlers and so forth. So we create them after
// construction in this init() method.
init: function() {
this._initCalled = true;
if (this.isDummy)
return;
this._shellInfo = new ShellInfo();
// Add a clone of the panel to the overview so spacing and such is
// automatic
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel.actor }),
reactive: false,
opacity: 0 });
this._overview.add_actor(this._panelGhost);
this._searchEntry = new St.Entry({ name: 'searchEntry',
/* Translators: this is the text displayed
in the search entry when no search is
@ -201,16 +218,13 @@ const Overview = new Lang.Class({
hint_text: _("Type to search..."),
track_hover: true,
can_focus: true });
this._group.add_actor(this._searchEntry);
this._dash = new Dash.Dash();
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
this._dash.showAppsButton);
this._group.add_actor(this._viewSelector.actor);
this._group.add_actor(this._dash.actor);
this._searchEntryBin = new St.Bin({ child: this._searchEntry,
x_align: St.Align.MIDDLE });
this._overview.add_actor(this._searchEntryBin);
// TODO - recalculate everything when desktop size changes
this._dash.actor.add_constraint(this._viewSelector.constrainHeight);
this._dash = new Dash.Dash();
this._group.add_actor(this._dash.actor);
this.dashIconSize = this._dash.iconSize;
this._dash.connect('icon-size-changed',
Lang.bind(this, function() {
@ -221,6 +235,23 @@ const Overview = new Lang.Class({
// the left of the overview
Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks-symbolic');
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
this._dash.showAppsButton);
this._group.add(this._viewSelector.actor, { x_fill: true,
expand: true });
// Add our same-line elements after the search entry
this._overview.add(this._group, { y_fill: true,
expand: true });
// Then account for message tray
this._messageTrayGhost = new St.Bin({ style_class: 'message-tray-summary',
reactive: false,
opacity: 0,
x_fill: true,
y_fill: true });
this._overview.add_actor(this._messageTrayGhost);
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
this._relayout();
},
@ -233,11 +264,16 @@ const Overview = new Lang.Class({
this._viewSelector.removeSearchProvider(provider);
},
setMessage: function(text, undoCallback, undoLabel) {
//
// options:
// - undoCallback (function): the callback to be called if undo support is needed
// - forFeedback (boolean): whether the message is for direct feedback of a user action
//
setMessage: function(text, options) {
if (this.isDummy)
return;
this._shellInfo.setMessage(text, undoCallback, undoLabel);
this._shellInfo.setMessage(text, options);
},
_onDragBegin: function() {
@ -308,159 +344,11 @@ const Overview = new Lang.Class({
return DND.DragMotionResult.CONTINUE;
},
setScrollAdjustment: function(adjustment, direction) {
addAction: function(action) {
if (this.isDummy)
return;
this._scrollAdjustment = adjustment;
if (this._scrollAdjustment == null)
this._scrollDirection = SwipeScrollDirection.NONE;
else
this._scrollDirection = direction;
},
_onButtonPress: function(actor, event) {
if (this._scrollDirection == SwipeScrollDirection.NONE
|| event.get_button() != 1)
return;
let [stageX, stageY] = event.get_coords();
this._dragStartX = this._dragX = stageX;
this._dragStartY = this._dragY = stageY;
this._dragStartValue = this._scrollAdjustment.value;
this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
this._capturedEventId = global.stage.connect('captured-event',
Lang.bind(this, this._onCapturedEvent));
this.emit('swipe-scroll-begin');
},
_onCapturedEvent: function(actor, event) {
let stageX, stageY;
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
switch(event.type()) {
case Clutter.EventType.BUTTON_RELEASE:
[stageX, stageY] = event.get_coords();
// default to snapping back to the original value
let newValue = this._dragStartValue;
let minValue = this._scrollAdjustment.lower;
let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
let direction;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
direction = stageX > this._dragStartX ? -1 : 1;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
direction *= -1;
} else {
direction = stageY > this._dragStartY ? -1 : 1;
}
// We default to scroll a full page size; both the first
// and the last page may be smaller though, so we need to
// adjust difference in those cases.
let difference = direction * this._scrollAdjustment.page_size;
if (this._dragStartValue + difference > maxValue)
difference = maxValue - this._dragStartValue;
else if (this._dragStartValue + difference < minValue)
difference = minValue - this._dragStartValue;
// If the user has moved more than half the scroll
// difference, we want to "settle" to the new value
// even if the user stops dragging rather "throws" by
// releasing during the drag.
let distance = this._dragStartValue - this._scrollAdjustment.value;
let noStop = Math.abs(distance / difference) > 0.5;
// We detect if the user is stopped by comparing the
// timestamp of the button release with the timestamp of
// the last motion. Experimentally, a difference of 0 or 1
// millisecond indicates that the mouse is in motion, a
// larger difference indicates that the mouse is stopped.
if ((this._lastMotionTime > 0 &&
this._lastMotionTime > event.get_time() - 2) ||
noStop) {
if (this._dragStartValue + difference >= minValue &&
this._dragStartValue + difference <= maxValue)
newValue += difference;
}
let result;
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold) {
// no motion? It's a click!
result = SwipeScrollResult.CLICK;
this.emit('swipe-scroll-end', result);
} else {
if (newValue == this._dragStartValue)
result = SwipeScrollResult.CANCEL;
else
result = SwipeScrollResult.SWIPE;
// The event capture handler is disconnected
// while scrolling to the final position, so
// to avoid undesired prelights we raise
// the cover pane.
this._coverPane.raise_top();
this._coverPane.show();
Tweener.addTween(this._scrollAdjustment,
{ value: newValue,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onCompleteScope: this,
onComplete: function() {
this._coverPane.hide();
this.emit('swipe-scroll-end',
result);
}
});
}
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
return result != SwipeScrollResult.CLICK;
case Clutter.EventType.MOTION:
[stageX, stageY] = event.get_coords();
let dx = this._dragX - stageX;
let dy = this._dragY - stageY;
let primary = Main.layoutManager.primaryMonitor;
this._dragX = stageX;
this._dragY = stageY;
this._lastMotionTime = event.get_time();
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold)
return true;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
else
this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
} else {
this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
}
return true;
// Block enter/leave events to avoid prelights
// during swipe-scroll
case Clutter.EventType.ENTER:
case Clutter.EventType.LEAVE:
return true;
}
return false;
this._overview.add_action(action);
},
_getDesktopClone: function() {
@ -486,41 +374,27 @@ const Overview = new Lang.Class({
this.hide();
let primary = Main.layoutManager.primaryMonitor;
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
let contentY = Main.panel.actor.height;
let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
this._group.set_position(primary.x, primary.y);
this._group.set_size(primary.width, primary.height);
this._overview.set_position(primary.x, primary.y);
this._overview.set_size(primary.width, primary.height);
this._coverPane.set_position(0, contentY);
this._coverPane.set_size(primary.width, contentHeight);
},
let searchWidth = this._searchEntry.get_width();
let searchHeight = this._searchEntry.get_height();
let searchX = (primary.width - searchWidth) / 2;
let searchY = contentY + this._spacing;
_onRestacked: function() {
let stack = global.get_window_actors();
let stackIndices = {};
let dashWidth = DASH_MAX_WIDTH;
let dashY = searchY + searchHeight + this._spacing;
let dashX;
if (rtl) {
this._dash.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
dashX = primary.width;
} else {
dashX = 0;
for (let i = 0; i < stack.length; i++) {
// Use the stable sequence for an integer to use as a hash key
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
}
let viewX = rtl ? 0 : dashWidth + this._spacing;
let viewY = searchY + searchHeight + this._spacing;
let viewWidth = primary.width - dashWidth - this._spacing;
let viewHeight = contentHeight - this._spacing - viewY;
this._searchEntry.set_position(searchX, searchY);
this._dash.actor.set_position(dashX, dashY);
this._viewSelector.actor.set_position(viewX, viewY);
this._viewSelector.actor.set_size(viewWidth, viewHeight);
this.emit('windows-restacked', stackIndices);
},
//// Public methods ////
@ -557,15 +431,11 @@ const Overview = new Lang.Class({
return;
if (this._shown)
return;
// Do this manually instead of using _syncInputMode, to handle failure
if (!Main.pushModal(this._group))
return;
this._modal = true;
this._animateVisible();
this._shown = true;
this._buttonPressId = this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this._syncInputMode();
if (!this._modal)
return;
this._animateVisible();
},
fadeInDesktop: function() {
@ -608,12 +478,12 @@ const Overview = new Lang.Class({
// Disable unredirection while in the overview
Meta.disable_unredirect_for_screen(global.screen);
global.window_group.hide();
this._group.show();
this._overview.show();
this._background.show();
this._viewSelector.show();
this._group.opacity = 0;
Tweener.addTween(this._group,
this._overview.opacity = 0;
Tweener.addTween(this._overview,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
@ -622,7 +492,7 @@ const Overview = new Lang.Class({
});
Tweener.addTween(this._background,
{ dim_factor: 0.4,
{ dim_factor: 0.8,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
@ -665,10 +535,6 @@ const Overview = new Lang.Class({
this._shown = false;
this._syncInputMode();
if (this._buttonPressId > 0)
this._group.disconnect(this._buttonPressId);
this._buttonPressId = 0;
},
// hideTemporarily:
@ -692,7 +558,7 @@ const Overview = new Lang.Class({
if (this.isDummy)
return;
if (this._shown)
if (this.visible)
this.hide();
else
this.show();
@ -709,20 +575,21 @@ const Overview = new Lang.Class({
if (this._shown) {
if (!this._modal) {
if (Main.pushModal(this._group))
if (Main.pushModal(this._overview,
{ keybindingMode: Main.KeybindingMode.OVERVIEW }))
this._modal = true;
else
this.hide();
}
} else if (this._shownTemporarily) {
if (this._modal) {
Main.popModal(this._group);
Main.popModal(this._overview);
this._modal = false;
}
global.stage_input_mode = Shell.StageInputMode.FULLSCREEN;
} else {
if (this._modal) {
Main.popModal(this._group);
Main.popModal(this._overview);
this._modal = false;
}
else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN)
@ -740,7 +607,7 @@ const Overview = new Lang.Class({
this._viewSelector.zoomFromOverview();
// Make other elements fade out.
Tweener.addTween(this._group,
Tweener.addTween(this._overview,
{ opacity: 0,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
@ -782,7 +649,7 @@ const Overview = new Lang.Class({
this._viewSelector.hide();
this._desktopFade.hide();
this._background.hide();
this._group.hide();
this._overview.hide();
this.visible = false;
this.animationInProgress = false;

View File

@ -75,33 +75,41 @@ function _unpremultiply(color) {
blue: blue, alpha: color.alpha });
};
const Animation = new Lang.Class({
Name: 'Animation',
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
_init: function(name, size) {
this.actor = new St.Bin({ visible: false });
_init: function(filename, width, height, speed) {
this.actor = new St.Bin();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('notify::visible', Lang.bind(this, this._onVisibleNotify));
this._speed = speed;
this._isLoaded = false;
this._isPlaying = false;
this._timeoutId = 0;
this._frame = 0;
this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size);
this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height,
Lang.bind(this, this._animationsLoaded));
this.actor.set_child(this._animations);
},
_disconnectTimeout: function() {
play: function() {
if (this._isLoaded && this._timeoutId == 0) {
if (this._frame == 0)
this._showFrame(0);
this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
}
this._isPlaying = true;
},
stop: function() {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
},
_onVisibleNotify: function() {
if (this.actor.visible)
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
else
this._disconnectTimeout();
this._isPlaying = false;
},
_showFrame: function(frame) {
@ -121,8 +129,24 @@ const AnimatedIcon = new Lang.Class({
return true;
},
_animationsLoaded: function() {
this._isLoaded = true;
if (this._isPlaying)
this.play();
},
_onDestroy: function() {
this._disconnectTimeout();
this.stop();
}
});
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
Extends: Animation,
_init: function(name, size) {
this.parent(global.datadir + '/theme/' + name, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});
@ -247,6 +271,10 @@ const AppMenuButton = new Lang.Class({
this._container.connect('get-preferred-height', Lang.bind(this, this._getContentPreferredHeight));
this._container.connect('allocate', Lang.bind(this, this._contentAllocate));
let textureCache = St.TextureCache.get_default();
textureCache.connect('icon-theme-changed',
Lang.bind(this, this._onIconThemeChanged));
this._iconBox = new Shell.Slicer({ name: 'appMenuIcon' });
this._iconBox.connect('style-changed',
Lang.bind(this, this._onIconBoxStyleChanged));
@ -273,6 +301,7 @@ const AppMenuButton = new Lang.Class({
this._spinner = new AnimatedIcon('process-working.svg',
PANEL_ICON_SIZE);
this._container.add_actor(this._spinner.actor);
this._spinner.actor.hide();
this._spinner.actor.lower_bottom();
let tracker = Shell.WindowTracker.get_default();
@ -332,6 +361,15 @@ const AppMenuButton = new Lang.Class({
this._updateIconBoxClip();
},
_onIconThemeChanged: function() {
if (this._iconBox.child == null)
return;
this._iconBox.child.destroy();
let icon = this._targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
this._iconBox.set_child(icon);
},
_updateIconBoxClip: function() {
let allocation = this._iconBox.allocation;
if (this._iconBottomClip > 0)
@ -354,6 +392,7 @@ const AppMenuButton = new Lang.Class({
transition: "easeOutQuad",
onCompleteScope: this,
onComplete: function() {
this._spinner.stop();
this._spinner.actor.opacity = 255;
this._spinner.actor.hide();
}
@ -363,6 +402,7 @@ const AppMenuButton = new Lang.Class({
startAnimation: function() {
this._stop = false;
this.actor.reactive = false;
this._spinner.play();
this._spinner.actor.show();
},
@ -559,11 +599,12 @@ const AppMenuButton = new Lang.Class({
menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
} else {
if (this.menu && !(this.menu instanceof PopupMenu.RemoteMenu))
if (this.menu.isDummyQuitMenu)
return;
// fallback to older menu
menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
menu.isDummyQuitMenu = true;
menu.addAction(_("Quit"), Lang.bind(this, function() {
this._targetApp.request_quit();
}));
@ -576,15 +617,12 @@ const AppMenuButton = new Lang.Class({
Signals.addSignalMethods(AppMenuButton.prototype);
// Activities button. Because everything else in the top bar is a
// PanelMenu.Button, it simplifies some things to make this be one too.
// We just hack it up to not actually have a menu attached to it.
const ActivitiesButton = new Lang.Class({
Name: 'ActivitiesButton',
Extends: PanelMenu.Button,
_init: function() {
this.parent(0.0);
this.parent(0.0, null, true);
this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON;
let container = new Shell.GenericContainer();
@ -604,27 +642,27 @@ const ActivitiesButton = new Lang.Class({
this.hotCorner = new Layout.HotCorner();
container.add_actor(this.hotCorner.actor);
// Hack up our menu...
this.menu.open = Lang.bind(this, this._onMenuOpenRequest);
this.menu.close = Lang.bind(this, this._onMenuCloseRequest);
this.menu.toggle = Lang.bind(this, this._onMenuToggleRequest);
this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
Main.overview.connect('showing', Lang.bind(this, function() {
this.actor.add_style_pseudo_class('overview');
this._escapeMenuGrab();
this.actor.add_accessible_state (Atk.StateType.CHECKED);
}));
Main.overview.connect('hiding', Lang.bind(this, function() {
this.actor.remove_style_pseudo_class('overview');
this._escapeMenuGrab();
this.actor.remove_accessible_state (Atk.StateType.CHECKED);
}));
this._xdndTimeOut = 0;
// Since the hot corner uses stage coordinates, Clutter won't
// queue relayouts for us when the panel moves. Queue a relayout
// when that happens.
Main.layoutManager.connect('panel-box-changed', Lang.bind(this, function() {
container.queue_relayout();
}));
},
_containerGetPreferredWidth: function(actor, forHeight, alloc) {
@ -670,11 +708,6 @@ const ActivitiesButton = new Lang.Class({
return DND.DragMotionResult.CONTINUE;
},
_escapeMenuGrab: function() {
if (this.menu.isOpen)
this.menu.close();
},
_onCapturedEvent: function(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
if (!this.hotCorner.shouldToggleOverviewOnClick())
@ -683,33 +716,13 @@ const ActivitiesButton = new Lang.Class({
return false;
},
_onMenuOpenRequest: function() {
this.menu.isOpen = true;
this.menu.emit('open-state-changed', true);
},
_onMenuCloseRequest: function() {
this.menu.isOpen = false;
this.menu.emit('open-state-changed', false);
},
_onMenuToggleRequest: function() {
this.menu.isOpen = !this.menu.isOpen;
this.menu.emit('open-state-changed', this.menu.isOpen);
},
_onButtonRelease: function() {
if (this.menu.isOpen) {
this.menu.close();
Main.overview.toggle();
}
Main.overview.toggle();
},
_onKeyRelease: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
if (this.menu.isOpen)
this.menu.close();
Main.overview.toggle();
}
},
@ -850,10 +863,13 @@ const PanelCorner = new Lang.Class({
let backgroundColor = node.get_color('-panel-corner-background-color');
let borderColor = node.get_color('-panel-corner-border-color');
let noOverlap = borderColor.alpha == 0;
let offsetY = noOverlap ? borderWidth : 0;
let cr = this.actor.get_context();
cr.setOperator(Cairo.Operator.SOURCE);
cr.moveTo(0, 0);
cr.moveTo(0, offsetY);
if (this._side == St.Side.LEFT)
cr.arc(cornerRadius,
borderWidth + cornerRadius,
@ -862,7 +878,7 @@ const PanelCorner = new Lang.Class({
cr.arc(0,
borderWidth + cornerRadius,
cornerRadius, 3 * Math.PI / 2, 2 * Math.PI);
cr.lineTo(cornerRadius, 0);
cr.lineTo(cornerRadius, offsetY);
cr.closePath();
let savedPath = cr.copyPath();
@ -872,6 +888,9 @@ const PanelCorner = new Lang.Class({
Clutter.cairo_set_source_color(cr, over);
cr.fill();
if (noOverlap)
return;
let offset = borderWidth;
Clutter.cairo_set_source_color(cr, backgroundColor);
@ -901,6 +920,7 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
'logo': imports.gdm.loginDialog.LogoMenuButton,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton,
'userMenu': imports.ui.userMenu.UserMenuButton
@ -925,14 +945,9 @@ const Panel = new Lang.Class({
reactive: true });
this.actor._delegate = this;
this.statusArea = {};
this._sessionStyle = null;
Main.overview.connect('shown', Lang.bind(this, function () {
this.actor.add_style_class_name('in-overview');
}));
Main.overview.connect('hiding', Lang.bind(this, function () {
this.actor.remove_style_class_name('in-overview');
}));
this.statusArea = {};
this.menuManager = new PopupMenu.PopupMenuManager(this);
@ -962,7 +977,7 @@ const Panel = new Lang.Class({
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
Main.layoutManager.panelBox.add(this.actor);
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here-symbolic',
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP });
Main.sessionMode.connect('updated', Lang.bind(this, this._updatePanel));
@ -1119,6 +1134,13 @@ const Panel = new Lang.Class({
this._updateBox(panel.left, this._leftBox);
this._updateBox(panel.center, this._centerBox);
this._updateBox(panel.right, this._rightBox);
if (this._sessionStyle)
this._removeStyleClassName(this._sessionStyle);
this._sessionStyle = Main.sessionMode.panelStyle;
if (this._sessionStyle)
this._addStyleClassName(this._sessionStyle);
},
_initBox: function(elements, box) {
@ -1207,5 +1229,17 @@ const Panel = new Lang.Class({
this.statusArea[role] = indicator;
this._addToPanelBox(role, indicator, position, boxContainer);
return indicator;
},
_addStyleClassName: function(className) {
this.actor.add_style_class_name(className);
this._rightCorner.actor.add_style_class_name(className);
this._leftCorner.actor.add_style_class_name(className);
},
_removeStyleClassName: function(className) {
this.actor.remove_style_class_name(className);
this._rightCorner.actor.remove_style_class_name(className);
this._leftCorner.actor.remove_style_class_name(className);
}
});

View File

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

View File

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

View File

@ -29,91 +29,163 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
</method>
</interface>;
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
const SearchProvider2Iface = <interface name="org.gnome.Shell.SearchProvider2">
<method name="GetInitialResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetSubsearchResultSet">
<arg type="as" direction="in" />
<arg type="as" direction="in" />
<arg type="as" direction="out" />
</method>
<method name="GetResultMetas">
<arg type="as" direction="in" />
<arg type="aa{sv}" direction="out" />
</method>
<method name="ActivateResult">
<arg type="s" direction="in" />
<arg type="as" direction="in" />
<arg type="u" direction="in" />
</method>
<method name="LaunchSearch">
<arg type="as" direction="in" />
<arg type="u" direction="in" />
</method>
</interface>;
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
function loadRemoteSearchProviders(addProviderCallback) {
let dataDirs = GLib.get_system_data_dirs();
let loadedProviders = {};
for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
let dir = Gio.file_new_for_path(path);
if (!dir.query_exists(null))
continue;
loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback);
let data = { loadedProviders: [],
objectPaths: {},
addProviderCallback: addProviderCallback };
FileUtils.collectFromDatadirsAsync('search-providers',
{ loadedCallback: remoteProvidersLoaded,
processFile: loadRemoteSearchProvider,
data: data
});
}
function loadRemoteSearchProvider(file, info, data) {
let keyfile = new GLib.KeyFile();
let path = file.get_path();
try {
keyfile.load_from_file(path, 0);
} catch(e) {
return;
}
};
function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback) {
let dirPath = dir.get_path();
FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
for (let i = 0; i < files.length; i++) {
let keyfile = new GLib.KeyFile();
let path = GLib.build_filenamev([dirPath, files[i].get_name()]);
if (!keyfile.has_group(KEY_FILE_GROUP))
return;
try {
keyfile.load_from_file(path, 0);
} catch(e) {
continue;
}
let remoteProvider;
try {
let group = KEY_FILE_GROUP;
let busName = keyfile.get_string(group, 'BusName');
let objectPath = keyfile.get_string(group, 'ObjectPath');
if (!keyfile.has_group(KEY_FILE_GROUP))
continue;
if (data.objectPaths[objectPath])
return;
let remoteProvider, title;
try {
let group = KEY_FILE_GROUP;
let busName = keyfile.get_string(group, 'BusName');
let objectPath = keyfile.get_string(group, 'ObjectPath');
if (loadedProviders[objectPath])
continue;
let appInfo = null;
try {
let desktopId = keyfile.get_string(group, 'DesktopId');
appInfo = Gio.DesktopAppInfo.new(desktopId);
} catch (e) {
}
let icon;
if (appInfo) {
icon = appInfo.get_icon();
title = appInfo.get_name();
} else {
let iconName = keyfile.get_string(group, 'Icon');
icon = new Gio.ThemedIcon({ name: iconName });
title = keyfile.get_locale_string(group, 'Title', null);
}
remoteProvider = new RemoteSearchProvider(title,
icon,
busName,
objectPath);
loadedProviders[objectPath] = remoteProvider;
} catch(e) {
log('Failed to add search provider "%s": %s'.format(title, e.toString()));
continue;
}
addProviderCallback(remoteProvider);
let appInfo = null;
try {
let desktopId = keyfile.get_string(group, 'DesktopId');
appInfo = Gio.DesktopAppInfo.new(desktopId);
} catch (e) {
log('Ignoring search provider ' + path + ': missing DesktopId');
return;
}
}));
};
let version = '1';
try {
version = keyfile.get_string(group, 'Version');
} catch (e) {
// ignore error
}
if (version >= 2)
remoteProvider = new RemoteSearchProvider2(appInfo, busName, objectPath);
else
remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath);
data.objectPaths[objectPath] = remoteProvider;
data.loadedProviders.push(remoteProvider);
} catch(e) {
log('Failed to add search provider %s: %s'.format(path, e.toString()));
}
}
function remoteProvidersLoaded(loadState) {
let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
let sortOrder = searchSettings.get_strv('sort-order');
let numSorted = sortOrder.length;
loadState.loadedProviders.sort(
function(providerA, providerB) {
let idxA, idxB;
let appIdA, appIdB;
appIdA = providerA.appInfo.get_id();
appIdB = providerB.appInfo.get_id();
idxA = sortOrder.indexOf(appIdA);
idxB = sortOrder.indexOf(appIdB);
// if no provider is found in the order, use alphabetical order
if ((idxA == -1) && (idxB == -1))
return GLib.utf8_collate(providerA.title, providerB.title);
if (numSorted > 1) {
// if providerA is the last, it goes after everything
if ((idxA + 1) == numSorted)
return 1;
// if providerB is the last, it goes after everything
else if ((idxB + 1) == numSorted)
return -1;
}
// if providerA isn't found, it's sorted after providerB
if (idxA == -1)
return 1;
// if providerB isn't found, it's sorted after providerA
if (idxB == -1)
return -1;
// finally, if both providers are found, return their order in the list
return (idxA - idxB);
});
loadState.loadedProviders.forEach(
function(provider) {
loadState.addProviderCallback(provider);
});
}
const RemoteSearchProvider = new Lang.Class({
Name: 'RemoteSearchProvider',
Extends: Search.SearchProvider,
_init: function(title, icon, dbusName, dbusPath) {
this._proxy = new SearchProviderProxy(Gio.DBus.session,
dbusName, dbusPath);
_init: function(appInfo, dbusName, dbusPath, proxyType) {
if (!proxyType)
proxyType = SearchProviderProxy;
this.proxy = new proxyType(Gio.DBus.session,
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
this.appInfo = appInfo;
this.id = appInfo.get_id();
this.isRemoteProvider = true;
this.parent(title.toUpperCase());
this._cancellable = new Gio.Cancellable();
},
_onProxyConstructed: function(proxy) {
// Do nothing
},
createIcon: function(size, meta) {
if (meta['gicon']) {
return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
@ -126,9 +198,7 @@ const RemoteSearchProvider = new Lang.Class({
width, height, rowStride, size);
}
// Ugh, but we want to fall back to something ...
return new St.Icon({ icon_name: 'text-x-generic',
icon_size: size });
return null;
},
_getResultsFinished: function(results, error) {
@ -141,9 +211,9 @@ const RemoteSearchProvider = new Lang.Class({
this._cancellable.cancel();
this._cancellable.reset();
try {
this._proxy.GetInitialResultSetRemote(terms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
this.proxy.GetInitialResultSetRemote(terms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
this.searchSystem.pushResults(this, []);
@ -154,9 +224,9 @@ const RemoteSearchProvider = new Lang.Class({
this._cancellable.cancel();
this._cancellable.reset();
try {
this._proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
this.searchSystem.pushResults(this, []);
@ -185,9 +255,9 @@ const RemoteSearchProvider = new Lang.Class({
this._cancellable.cancel();
this._cancellable.reset();
try {
this._proxy.GetResultMetasRemote(ids,
Lang.bind(this, this._getResultMetasFinished, callback),
this._cancellable);
this.proxy.GetResultMetasRemote(ids,
Lang.bind(this, this._getResultMetasFinished, callback),
this._cancellable);
} catch(e) {
log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
callback([]);
@ -195,8 +265,32 @@ const RemoteSearchProvider = new Lang.Class({
},
activateResult: function(id) {
this._proxy.ActivateResultRemote(id);
this.proxy.ActivateResultRemote(id);
},
launchSearch: function(terms) {
// the provider is not compatible with the new version of the interface, launch
// the app itself but warn so we can catch the error in logs
log('Search provider ' + this.appInfo.get_id() + ' does not implement LaunchSearch');
this.appInfo.launch([], global.create_app_launch_context());
}
});
const RemoteSearchProvider2 = new Lang.Class({
Name: 'RemoteSearchProvider2',
Extends: RemoteSearchProvider,
_init: function(appInfo, dbusName, dbusPath) {
this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy);
this.canLaunchSearch = true;
},
activateResult: function(id, terms) {
this.proxy.ActivateResultRemote(id, terms, global.get_current_time());
},
launchSearch: function(terms) {
this.proxy.LaunchSearchRemote(terms, global.get_current_time());
}
});

View File

@ -202,11 +202,12 @@ const RunDialog = new Lang.Class({
let label = new St.Label({ style_class: 'run-dialog-label',
text: _("Please enter a command:") });
text: _("Enter a Command") });
this.contentLayout.add(label, { y_align: St.Align.START });
let entry = new St.Entry({ style_class: 'run-dialog-entry' });
let entry = new St.Entry({ style_class: 'run-dialog-entry',
can_focus: true });
ShellEntry.addContextMenu(entry);
entry.label_actor = label;
@ -236,6 +237,10 @@ const RunDialog = new Lang.Class({
this._errorBox.hide();
this.setButtons([{ action: Lang.bind(this, this.close),
label: _("Close"),
key: Clutter.Escape }]);
this._pathCompleter = new Gio.FilenameCompleter();
this._commandCompleter = new CommandCompleter();
this._group.connect('notify::visible', Lang.bind(this._commandCompleter, this._commandCompleter.update));
@ -246,20 +251,12 @@ const RunDialog = new Lang.Class({
let symbol = e.get_key_symbol();
if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
this.popModal();
if (e.get_state() & Clutter.ModifierType.CONTROL_MASK)
this._run(o.get_text(), true);
else
this._run(o.get_text(), false);
if (!this._commandError)
this._run(o.get_text(),
e.get_state() & Clutter.ModifierType.CONTROL_MASK);
if (!this._commandError ||
!this.pushModal())
this.close();
else {
if (!this.pushModal())
this.close();
}
return true;
}
if (symbol == Clutter.Escape) {
this.close();
return true;
}
if (symbol == Clutter.slash) {

View File

@ -26,7 +26,7 @@ const Util = imports.misc.util;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
const CURTAIN_SLIDE_TIME = 0.5;
const CURTAIN_SLIDE_TIME = 0.3;
// fraction of screen height the arrow must reach before completing
// the slide up automatically
const ARROW_DRAG_THRESHOLD = 0.1;
@ -47,7 +47,39 @@ const SUMMARY_ICON_SIZE = 48;
// STANDARD_FADE_TIME is used when the session goes idle, while
// SHORT_FADE_TIME is used when requesting lock explicitly from the user menu
const STANDARD_FADE_TIME = 10;
const SHORT_FADE_TIME = 0.8;
const SHORT_FADE_TIME = 0.3;
function sample(offx, offy) {
return 'texel += texture2D (sampler, tex_coord.st + pixel_step * ' +
'vec2 (' + offx + ',' + offy + '));\n'
}
const GLSL_BLUR_EFFECT_DECLARATIONS = ' \
uniform vec2 pixel_step;\n \
uniform float desaturation;\n \
vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
vec4 texel;\n \
texel = texture2D (sampler, tex_coord.st);\n'
+ sample(-1.0, -1.0)
+ sample( 0.0, -1.0)
+ sample(+1.0, -1.0)
+ sample(-1.0, 0.0)
+ sample(+1.0, 0.0)
+ sample(-1.0, +1.0)
+ sample( 0.0, +1.0)
+ sample(+1.0, +1.0) + ' \
texel /= 9.0;\n \
return texel;\n \
}\n \
vec3 desaturate (const vec3 color)\n \
{\n \
const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n \
vec3 gray = vec3 (dot (gray_conv, color));\n \
return vec3 (mix (color.rgb, gray, desaturation));\n \
}';
const GLSL_BLUR_EFFECT_CODE = ' \
cogl_texel = apply_blur(cogl_sampler, cogl_tex_coord.st);\n \
cogl_texel.rgb = desaturate(cogl_texel.rgb);\n';
const Clock = new Lang.Class({
Name: 'ScreenShieldClock',
@ -186,7 +218,7 @@ const NotificationsBox = new Lang.Class({
if (obj.resident) {
this._residentNotificationBox.add(item.notificationStackWidget);
item.closeButtonVisible = false;
item.closeButton.hide();
item.prepareNotificationStackForShowing();
} else {
[obj.sourceBox, obj.countLabel] = this._makeNotificationSource(item.source);
@ -244,7 +276,7 @@ const NotificationsBox = new Lang.Class({
obj.resident = true;
this._residentNotificationBox.add(obj.item.notificationStackWidget);
obj.item.closeButtonVisible = false;
obj.item.closeButton.hide();
obj.item.prepareNotificationStackForShowing();
} else {
// just update the counter
@ -276,6 +308,7 @@ const NotificationsBox = new Lang.Class({
obj.item.disconnect(obj.contentUpdatedId);
obj.source.disconnect(obj.sourceDestroyId);
obj.source.disconnect(obj.sourceCountChangedId);
obj.source.disconnect(obj.sourceTitleChangedId);
},
});
@ -335,6 +368,10 @@ const Arrow = new Lang.Class({
}
});
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
/**
* To test screen shield, make sure to kill gnome-screensaver.
*
@ -362,13 +399,25 @@ const ScreenShield = new Lang.Class({
Lang.bind(this, this._onLockScreenKeyRelease));
this._lockScreenGroup.connect('scroll-event',
Lang.bind(this, this._onLockScreenScroll));
Main.ctrlAltTabManager.addGroup(this._lockScreenGroup, _("Lock"), 'changes-prevent-symbolic');
this._lockScreenContents = new St.Widget({ layout_manager: new Clutter.BinLayout(),
name: 'lockScreenContents' });
this._lockScreenContents.add_constraint(new Layout.MonitorConstraint({ primary: true }));
let backgroundActor = Meta.BackgroundActor.new_for_screen(global.screen);
backgroundActor.add_glsl_snippet(Meta.SnippetHook.TEXTURE_LOOKUP,
GLSL_BLUR_EFFECT_DECLARATIONS,
GLSL_BLUR_EFFECT_CODE,
true);
backgroundActor.set_uniform_float('desaturation',
1, 1, [0.6]);
backgroundActor.connect('notify::size', function(actor) {
actor.set_uniform_float('pixel_step', 2, 1, [1/actor.width, 1/actor.height]);
});
this._background = new St.Bin({ style_class: 'screen-shield-background',
child: Meta.BackgroundActor.new_for_screen(global.screen) });
child: backgroundActor });
this._lockScreenGroup.add_actor(this._background);
this._lockScreenGroup.add_actor(this._lockScreenContents);
@ -387,14 +436,11 @@ const ScreenShield = new Lang.Class({
}
this._lockScreenContents.add_actor(this._arrowContainer);
let dragArea = new Clutter.Rect({ origin: new Clutter.Point({ x: 0, y: -global.screen_height, }),
size: new Clutter.Size({ width: global.screen_width,
height: global.screen_height }) });
let action = new Clutter.DragAction({ drag_axis: Clutter.DragAxis.Y_AXIS,
drag_area: dragArea });
action.connect('drag-begin', Lang.bind(this, this._onDragBegin));
action.connect('drag-end', Lang.bind(this, this._onDragEnd));
this._lockScreenGroup.add_action(action);
this._dragAction = new Clutter.GestureAction();
this._dragAction.connect('gesture-begin', Lang.bind(this, this._onDragBegin));
this._dragAction.connect('gesture-progress', Lang.bind(this, this._onDragMotion));
this._dragAction.connect('gesture-end', Lang.bind(this, this._onDragEnd));
this._lockScreenGroup.add_action(this._dragAction);
this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: true,
@ -436,6 +482,8 @@ const ScreenShield = new Lang.Class({
{ inhibitEvents: true,
fadeInTime: STANDARD_FADE_TIME,
fadeFactor: 1 });
this.idleMonitor = new GnomeDesktop.IdleMonitor();
},
_onLockScreenKeyRelease: function(actor, event) {
@ -455,8 +503,8 @@ const ScreenShield = new Lang.Class({
if (symbol == Clutter.KEY_Escape ||
symbol == Clutter.KEY_Return ||
symbol == Clutter.KEY_KP_Enter) {
this._ensureUnlockDialog(true);
this._hideLockScreen(true);
this._ensureUnlockDialog(true, true);
this._hideLockScreen(true, 0);
return true;
}
@ -478,8 +526,8 @@ const ScreenShield = new Lang.Class({
// 7 standard scrolls to lift up
if (this._lockScreenScrollCounter > 35) {
this._ensureUnlockDialog(false);
this._hideLockScreen(true);
this._ensureUnlockDialog(false, true);
this._hideLockScreen(true, 0);
}
return true;
@ -510,13 +558,29 @@ const ScreenShield = new Lang.Class({
_onDragBegin: function() {
Tweener.removeTweens(this._lockScreenGroup);
this._lockScreenState = MessageTray.State.HIDING;
this._ensureUnlockDialog(false);
this._ensureUnlockDialog(false, false);
return true;
},
_onDragMotion: function() {
let [origX, origY] = this._dragAction.get_press_coords(0);
let [currentX, currentY] = this._dragAction.get_motion_coords(0);
let newY = currentY - origY;
newY = clamp(newY, -global.stage.height, 0);
this._lockScreenGroup.y = newY;
return true;
},
_onDragEnd: function(action, actor, eventX, eventY, modifiers) {
if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) {
// Complete motion automatically
this._hideLockScreen(true);
let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
this._hideLockScreen(true, -velocityY);
this._ensureUnlockDialog(false, true);
} else {
// restore the lock screen to its original place
// try to use the same speed as the normal animation
@ -526,7 +590,7 @@ const ScreenShield = new Lang.Class({
Tweener.addTween(this._lockScreenGroup,
{ y: 0,
time: time,
transition: 'linear',
transition: 'easeInQuad',
onComplete: function() {
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenState = MessageTray.State.SHOWN;
@ -545,55 +609,62 @@ const ScreenShield = new Lang.Class({
},
_onStatusChanged: function(status) {
if (status == GnomeSession.PresenceStatus.IDLE) {
if (this._dialog) {
this._dialog.cancel();
if (!this._isGreeter) {
this._dialog = null;
if (status != GnomeSession.PresenceStatus.IDLE)
return;
if (this._dialog) {
this._dialog.cancel();
if (!this._isGreeter) {
this._dialog = null;
}
}
if (!this._isModal) {
Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
this._isModal = true;
}
if (!this._isActive) {
this._lightbox.show();
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
this._becameActiveId = this.idleMonitor.connect('became-active', Lang.bind(this, function() {
this.idleMonitor.disconnect(this._becameActiveId);
let lightboxWasShown = this._lightbox.shown;
this._lightbox.hide();
let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
if (shouldLock || this._isLocked) {
this.lock(false);
} else if (this._isActive) {
this.unlock();
}
}
}));
if (!this._isModal) {
Main.pushModal(this.actor);
this._isModal = true;
}
if (!this._isActive) {
this._lightbox.show();
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
}
} else {
let lightboxWasShown = this._lightbox.shown;
this._lightbox.hide();
let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
if (shouldLock || this._isActive) {
this.lock(false);
} else if (this._isModal) {
this.unlock();
}
this._isActive = true;
this.emit('lock-status-changed');
}
},
showDialog: function() {
// Ensure that the stage window is mapped, before taking a grab
// otherwise X errors out
let actorShownId = 0;
actorShownId = this.actor.connect('show', Lang.bind(this, function() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
if (!this._isModal) {
Main.pushModal(this.actor);
this._isModal = true;
}
this.actor.disconnect(actorShownId);
return false;
}));
this.actor.show();
this._isGreeter = Main.sessionMode.isGreeter;
this._ensureUnlockDialog(true);
this._hideLockScreen(false);
this._ensureUnlockDialog(true, true);
this._hideLockScreen(false, 0);
},
_bumpLockScreen: function() {
@ -611,19 +682,26 @@ const ScreenShield = new Lang.Class({
});
},
_hideLockScreen: function(animate) {
_hideLockScreen: function(animate, velocity) {
this._lockScreenState = MessageTray.State.HIDING;
if (animate) {
// Tween the lock screen out of screen
// try to use the same speed regardless of original position
// if velocity is not specified (i.e. we come here from pressing ESC),
// use the same speed regardless of original position
// if velocity is specified, it's in pixels per milliseconds
let h = global.stage.height;
let time = CURTAIN_SLIDE_TIME * (h + this._lockScreenGroup.y) / h;
let delta = (h + this._lockScreenGroup.y);
let min_velocity = global.stage.height / (CURTAIN_SLIDE_TIME * 1000);
velocity = Math.max(min_velocity, velocity);
let time = (delta / velocity) / 1000;
Tweener.removeTweens(this._lockScreenGroup);
Tweener.addTween(this._lockScreenGroup,
{ y: -h,
time: time,
transition: 'linear',
transition: 'easeInQuad',
onComplete: function() {
this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup.hide();
@ -635,20 +713,24 @@ const ScreenShield = new Lang.Class({
this._lockScreenGroup.hide();
}
global.stage.show_cursor();
if (Main.sessionMode.currentMode == 'lock-screen')
Main.sessionMode.popMode('lock-screen');
},
_ensureUnlockDialog: function(onPrimary) {
_ensureUnlockDialog: function(onPrimary, allowCancel) {
if (!this._dialog) {
let constructor = Main.sessionMode.unlockDialog;
this._dialog = new constructor(this._lockDialogGroup);
if (!this._dialog) {
if (!constructor) {
// This session mode has no locking capabilities
this.unlock();
return;
}
this._dialog = new constructor(this._lockDialogGroup);
let time = global.get_current_time();
this._dialog.connect('loaded', Lang.bind(this, function() {
if (!this._dialog.open(time, onPrimary)) {
@ -660,6 +742,8 @@ const ScreenShield = new Lang.Class({
this._dialog.connect('failed', Lang.bind(this, this._onUnlockFailed));
this._dialog.connect('unlocked', Lang.bind(this, this._onUnlockSucceded));
}
this._dialog.allowCancel = allowCancel;
},
_onUnlockFailed: function() {
@ -684,7 +768,7 @@ const ScreenShield = new Lang.Class({
Tweener.addTween(this._lockScreenGroup,
{ y: 0,
time: SHORT_FADE_TIME,
transition: 'linear',
transition: 'easeOutQuad',
onComplete: function() {
this._lockScreenShown();
},
@ -723,6 +807,16 @@ const ScreenShield = new Lang.Class({
this._arrowAnimationId = Mainloop.timeout_add(6000, Lang.bind(this, this._animateArrows));
this._animateArrows();
let motionId = global.stage.connect('captured-event', function(stage, event) {
if (event.type() == Clutter.EventType.MOTION) {
global.stage.show_cursor();
global.stage.disconnect(motionId);
}
return false;
});
global.stage.hide_cursor();
this._lockScreenState = MessageTray.State.SHOWN;
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenScrollCounter = 0;
@ -831,12 +925,13 @@ const ScreenShield = new Lang.Class({
this._activationTime = 0;
this._isActive = false;
this._isLocked = false;
this.emit('lock-status-changed');
},
lock: function(animate) {
if (!this._isModal) {
Main.pushModal(this.actor);
Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
this._isModal = true;
}
@ -855,6 +950,7 @@ const ScreenShield = new Lang.Class({
this._resetLockScreen(animate, animate);
this._isActive = true;
this._isLocked = true;
this.emit('lock-status-changed');
},
});

View File

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

View File

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

34
js/ui/separator.js Normal file
View File

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

View File

@ -1,8 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const Params = imports.misc.params;
@ -10,11 +14,12 @@ const DEFAULT_MODE = 'restrictive';
const _modes = {
'restrictive': {
parentMode: null,
hasOverview: false,
showCalendarEvents: false,
allowSettings: false,
allowExtensions: false,
allowKeybindingsWhenModal: false,
enabledExtensions: [],
hasRunDialog: false,
hasWorkspaces: false,
hasWindows: false,
@ -29,21 +34,22 @@ const _modes = {
center: [],
right: []
},
panelStyle: null
},
'gdm': {
allowKeybindingsWhenModal: true,
hasNotifications: true,
isGreeter: true,
isPrimary: true,
unlockDialog: imports.gdm.loginDialog.LoginDialog,
components: ['polkitAgent'],
panel: {
left: [],
left: ['logo'],
center: ['dateMenu'],
right: ['a11y', 'display', 'keyboard',
'volume', 'battery', 'powerMenu']
}
},
panelStyle: 'login-screen'
},
'lock-screen': {
@ -56,6 +62,7 @@ const _modes = {
center: [],
right: ['lockScreen']
},
panelStyle: 'lock-screen'
},
'unlock-dialog': {
@ -67,6 +74,7 @@ const _modes = {
center: [],
right: ['a11y', 'keyboard', 'lockScreen']
},
panelStyle: 'unlock-screen'
},
'initial-setup': {
@ -102,11 +110,48 @@ const _modes = {
}
};
function _getModes(modesLoadedCallback) {
FileUtils.collectFromDatadirsAsync('modes',
{ processFile: _loadMode,
loadedCallback: modesLoadedCallback,
data: _modes });
}
function _loadMode(file, info, loadedData) {
let name = info.get_name();
let suffix = name.indexOf('.json');
let modeName = suffix == -1 ? name : name.slice(name, suffix);
if (loadedData.hasOwnProperty(modeName))
return;
let fileContent, success, tag, newMode;
try {
[success, fileContent, tag] = file.load_contents(null);
newMode = JSON.parse(fileContent);
} catch(e) {
return;
}
loadedData[modeName] = {};
let propBlacklist = ['unlockDialog'];
for (let prop in loadedData[DEFAULT_MODE]) {
if (newMode[prop] !== undefined &&
propBlacklist.indexOf(prop) == -1)
loadedData[modeName][prop]= newMode[prop];
}
loadedData[modeName]['isPrimary'] = true;
}
function listModes() {
let modes = Object.getOwnPropertyNames(_modes);
for (let i = 0; i < modes.length; i++)
if (_modes[modes[i]].isPrimary)
print(modes[i]);
_getModes(function(modes) {
let names = Object.getOwnPropertyNames(modes);
for (let i = 0; i < names.length; i++)
if (_modes[names[i]].isPrimary)
print(names[i]);
Mainloop.quit('listModes');
});
Mainloop.run('listModes');
}
const SessionMode = new Lang.Class({
@ -114,10 +159,18 @@ const SessionMode = new Lang.Class({
_init: function() {
global.connect('notify::session-mode', Lang.bind(this, this._sync));
let mode = _modes[global.session_mode].isPrimary ? global.session_mode
: 'user';
this._modeStack = [mode];
this._modes = _modes;
this._modeStack = [DEFAULT_MODE];
this._sync();
_getModes(Lang.bind(this, function(modes) {
this._modes = modes;
let primary = modes[global.session_mode] &&
modes[global.session_mode].isPrimary;
let mode = primary ? global.session_mode : 'user';
this._modeStack = [mode];
this._sync();
}));
},
pushMode: function(mode) {
@ -144,8 +197,14 @@ const SessionMode = new Lang.Class({
},
_sync: function() {
let params = _modes[this.currentMode];
params = Params.parse(params, _modes[DEFAULT_MODE]);
let params = this._modes[this.currentMode];
let defaults;
if (params.parentMode)
defaults = Params.parse(this._modes[params.parentMode],
this._modes[DEFAULT_MODE]);
else
defaults = this._modes[DEFAULT_MODE];
params = Params.parse(params, defaults);
// A simplified version of Lang.copyProperties, handles
// undefined as a special case for "no change / inherit from previous mode"

View File

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

View File

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

View File

@ -27,6 +27,7 @@ const KEY_VISUAL_BELL = 'visual-bell';
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
const KEY_GTK_THEME = 'gtk-theme';
const KEY_ICON_THEME = 'icon-theme';
const KEY_WM_THEME = 'theme';
const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
const HIGH_CONTRAST_THEME = 'HighContrast';
@ -101,28 +102,35 @@ const ATIndicator = new Lang.Class({
},
_buildHCItem: function() {
let settings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
let gtkTheme = settings.get_string(KEY_GTK_THEME);
let iconTheme = settings.get_string(KEY_ICON_THEME);
let interfaceSettings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
let wmSettings = new Gio.Settings({ schema: WM_SCHEMA });
let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME);
let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME);
let wmTheme = wmSettings.get_string(KEY_WM_THEME);
let hasHC = (gtkTheme == HIGH_CONTRAST_THEME);
let highContrast = this._buildItemExtended(
_("High Contrast"),
hasHC,
settings.is_writable(KEY_GTK_THEME) && settings.is_writable(KEY_ICON_THEME),
interfaceSettings.is_writable(KEY_GTK_THEME) &&
interfaceSettings.is_writable(KEY_ICON_THEME) &&
wmSettings.is_writable(KEY_WM_THEME),
function (enabled) {
if (enabled) {
settings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
settings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
wmSettings.set_string(KEY_WM_THEME, HIGH_CONTRAST_THEME);
} else if(!hasHC) {
settings.set_string(KEY_GTK_THEME, gtkTheme);
settings.set_string(KEY_ICON_THEME, iconTheme);
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
wmSettings.set_string(KEY_WM_THEME, wmTheme);
} else {
settings.reset(KEY_GTK_THEME);
settings.reset(KEY_ICON_THEME);
interfaceSettings.reset(KEY_GTK_THEME);
interfaceSettings.reset(KEY_ICON_THEME);
wmSettings.reset(KEY_WM_THEME);
}
});
settings.connect('changed::' + KEY_GTK_THEME, function() {
let value = settings.get_string(KEY_GTK_THEME);
interfaceSettings.connect('changed::' + KEY_GTK_THEME, function() {
let value = interfaceSettings.get_string(KEY_GTK_THEME);
if (value == HIGH_CONTRAST_THEME) {
highContrast.setToggleState(true);
} else {
@ -130,11 +138,16 @@ const ATIndicator = new Lang.Class({
gtkTheme = value;
}
});
settings.connect('changed::' + KEY_ICON_THEME, function() {
let value = settings.get_string(KEY_ICON_THEME);
interfaceSettings.connect('changed::' + KEY_ICON_THEME, function() {
let value = interfaceSettings.get_string(KEY_ICON_THEME);
if (value != HIGH_CONTRAST_THEME)
iconTheme = value;
});
wmSettings.connect('changed::' + KEY_WM_THEME, function() {
let value = wmSettings.get_string(KEY_WM_THEME);
if (value != HIGH_CONTRAST_THEME)
wmTheme = value;
});
return highContrast;
},

View File

@ -80,7 +80,7 @@ const Indicator = new Lang.Class({
this._applet.connect('notify::show-full-menu', Lang.bind(this, this._updateFullMenu));
this._updateFullMenu();
this.menu.addSettingsAction(_("Bluetooth Settings"), 'bluetooth-properties.desktop');
this.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest));
this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest));
@ -239,22 +239,6 @@ const Indicator = new Lang.Class({
this._applet.send_to_address(device.bdaddr, device.alias);
}));
}
if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_FILE_TRANSFER) {
item.menu.addAction(_("Browse Files..."), Lang.bind(this, function(event) {
this._applet.browse_address(device.bdaddr, event.get_time(),
Lang.bind(this, function(applet, result) {
try {
applet.browse_address_finish(result);
} catch (e) {
this._ensureSource();
this._source.notify(new MessageTray.Notification(this._source,
_("Bluetooth"),
_("Error browsing device"),
{ body: _("The requested device cannot be browsed, error is '%s'").format(e) }));
}
}));
}));
}
switch (device.type) {
case GnomeBluetoothApplet.Type.KEYBOARD:
@ -369,6 +353,7 @@ const ConfirmNotification = new Lang.Class({
_init: function(source, applet, device_path, name, long_name, pin) {
this.parent(source,
_("Bluetooth"),
/* Translators: argument is the device short name */
_("Pairing confirmation for %s").format(name),
{ customContent: true });
this.setResident(true);
@ -378,6 +363,7 @@ const ConfirmNotification = new Lang.Class({
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
this.addBody(_("Please confirm whether the PIN '%06d' matches the one on the device.").format(pin));
/* Translators: this is the verb, not the noun */
this.addButton('matches', _("Matches"));
this.addButton('does-not-match', _("Does not match"));

View File

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

View File

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

View File

@ -233,20 +233,11 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
}
});
const NMDevice = new Lang.Class({
Name: 'NMDevice',
const NMConnectionBased = new Lang.Class({
Name: 'NMConnectionBased',
Abstract: true,
_init: function(client, device, connections) {
this.device = device;
if (device) {
this.device._delegate = this;
this._stateChangedId = this.device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
} else
this._stateChangedId = 0;
// protected
this._client = client;
_init: function(connections) {
this._connections = [ ];
for (let i = 0; i < connections.length; i++) {
if (!connections[i].get_uuid())
@ -264,26 +255,115 @@ const NMDevice = new Lang.Class({
this._connections.push(obj);
}
this._connections.sort(this._connectionSortFunction);
},
checkConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
let exists = pos != -1;
let valid = this.connectionValid(connection);
let similar = false;
if (exists) {
let existing = this._connections[pos];
// Check if connection changed name or id
similar = existing.name == connection.get_id() &&
existing.timestamp == connection._timestamp;
}
if (exists && valid && similar) {
// Nothing to do
return;
}
if (exists)
this.removeConnection(connection);
if (valid)
this.addConnection(connection);
},
addConnection: function(connection) {
// record the connection
let obj = {
connection: connection,
name: connection.get_id(),
uuid: connection.get_uuid(),
timestamp: connection._timestamp,
item: null,
};
Util.insertSorted(this._connections, obj, this._connectionSortFunction);
this._queueCreateSection();
},
removeConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
if (pos == -1) {
// this connection was never added, nothing to do here
return;
}
let obj = this._connections[pos];
if (obj.item)
obj.item.destroy();
this._connections.splice(pos, 1);
if (this._connections.length <= 1) {
// We need to show the automatic connection again
// (or in the case of NMDeviceWired, we want to hide
// the only explicit connection)
this._queueCreateSection();
}
},
_findConnection: function(uuid) {
for (let i = 0; i < this._connections.length; i++) {
let obj = this._connections[i];
if (obj.uuid == uuid)
return i;
}
return -1;
},
_connectionSortFunction: function(one, two) {
if (one.timestamp == two.timestamp)
return GLib.utf8_collate(one.name, two.name);
return two.timestamp - one.timestamp;
},
});
Signals.addSignalMethods(NMConnectionBased.prototype);
const NMDevice = new Lang.Class({
Name: 'NMDevice',
Abstract: true,
Extends: NMConnectionBased,
_init: function(client, device, connections) {
this.device = device;
this.device._delegate = this;
this._stateChangedId = this.device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
// protected
this._client = client;
this.parent(connections);
this._activeConnection = null;
this._activeConnectionItem = null;
this._autoConnectionItem = null;
this._overflowItem = null;
if (this.device) {
this.statusItem = new PopupMenu.PopupSwitchMenuItem(this._getDescription(), this.connected, { style_class: 'popup-subtitle-menu-item' });
this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
let ok;
if (state)
ok = this.activate();
else
ok = this.deactivate();
this.statusItem = new PopupMenu.PopupSwitchMenuItem(this._getDescription(), this.connected, { style_class: 'popup-subtitle-menu-item' });
this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
let ok;
if (state)
ok = this.activate();
else
ok = this.deactivate();
if (!ok)
item.setToggleState(!state);
}));
if (!ok)
item.setToggleState(!state);
}));
this._updateStatusItem();
}
this._updateStatusItem();
this.section = new PopupMenu.PopupMenuSection();
this._deferredWorkId = Main.initializeDeferredWork(this.section.actor, Lang.bind(this, this._createSection));
@ -352,6 +432,10 @@ const NMDevice = new Lang.Class({
return this.device.state == NetworkManager.DeviceState.ACTIVATED;
},
clearActiveConnection: function(activeConnection) {
this.setActiveConnection(null);
},
setActiveConnection: function(activeConnection) {
if (activeConnection == this._activeConnection)
// nothing to do
@ -369,80 +453,13 @@ const NMDevice = new Lang.Class({
this._queueCreateSection();
},
checkConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
let exists = pos != -1;
let valid = this.connectionValid(connection);
let similar = false;
if (exists) {
let existing = this._connections[pos];
// Check if connection changed name or id
similar = existing.name == connection.get_id() &&
existing.timestamp == connection._timestamp;
}
if (exists && valid && similar) {
// Nothing to do
return;
}
if (exists)
this.removeConnection(connection);
if (valid)
this.addConnection(connection);
},
addConnection: function(connection) {
// record the connection
let obj = {
connection: connection,
name: connection.get_id(),
uuid: connection.get_uuid(),
timestamp: connection._timestamp,
item: null,
};
Util.insertSorted(this._connections, obj, this._connectionSortFunction);
this._clearSection();
this._queueCreateSection();
},
removeConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
if (pos == -1) {
// this connection was never added, nothing to do here
return;
}
let obj = this._connections[pos];
if (obj.item)
obj.item.destroy();
this._connections.splice(pos, 1);
if (this._connections.length <= 1) {
// We need to show the automatic connection again
// (or in the case of NMDeviceWired, we want to hide
// the only explicit connection)
this._clearSection();
this._queueCreateSection();
}
},
connectionValid: function(connection) {
return this.device.connection_valid(connection);
},
_connectionSortFunction: function(one, two) {
if (one.timestamp == two.timestamp)
return GLib.utf8_collate(one.name, two.name);
return two.timestamp - one.timestamp;
},
setEnabled: function(enabled) {
// do nothing by default, we want to keep the conneciton list visible
// in the majority of cases (wired, wwan, vpn)
// in the majority of cases (wired, wwan)
},
getStatusLabel: function() {
@ -500,15 +517,6 @@ const NMDevice = new Lang.Class({
throw new TypeError('Invoking pure virtual function NMDevice.createAutomaticConnection');
},
_findConnection: function(uuid) {
for (let i = 0; i < this._connections.length; i++) {
let obj = this._connections[i];
if (obj.uuid == uuid)
return i;
}
return -1;
},
_queueCreateSection: function() {
this._clearSection();
Main.queueDeferredWork(this._deferredWorkId);
@ -601,7 +609,11 @@ const NMDevice = new Lang.Class({
this.emit('network-lost');
}
if (newstate == NetworkManager.DeviceState.FAILED) {
/* Emit a notification if activation fails, but don't do it
if the reason is no secrets, as that indicates the user
cancelled the agent dialog */
if (newstate == NetworkManager.DeviceState.FAILED &&
reason != NetworkManager.DeviceStateReason.NO_SECRETS) {
this.emit('activation-failed', reason);
}
@ -652,15 +664,12 @@ const NMDevice = new Lang.Class({
return out;
}
});
Signals.addSignalMethods(NMDevice.prototype);
const NMDeviceWired = new Lang.Class({
Name: 'NMDeviceWired',
const NMDeviceSimple = new Lang.Class({
Name: 'NMDeviceSimple',
Extends: NMDevice,
_init: function(client, device, connections) {
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED;
this.parent(client, device, connections);
@ -675,6 +684,18 @@ const NMDeviceWired = new Lang.Class({
// we can do it here because addConnection and removeConnection
// both call _createSection at some point
this.section.actor.visible = this._connections.length > 1;
}
});
const NMDeviceWired = new Lang.Class({
Name: 'NMDeviceWired',
Extends: NMDeviceSimple,
_init: function(client, device, connections) {
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED;
this.parent(client, device, connections);
},
_createAutomaticConnection: function() {
@ -868,95 +889,6 @@ const NMDeviceBluetooth = new Lang.Class({
}
});
// Not a real device, but I save a lot code this way
const NMDeviceVPN = new Lang.Class({
Name: 'NMDeviceVPN',
Extends: NMDevice,
_init: function(client, device, connections) {
// Disable autoconnections
this._autoConnectionName = null;
this.category = NMConnectionCategory.VPN;
this.parent(client, null, connections);
},
connectionValid: function(connection) {
return connection._type == NetworkManager.SETTING_VPN_SETTING_NAME;
},
get empty() {
return this._connections.length == 0;
},
get connected() {
if (!this._activeConnection)
return false;
return this._activeConnection.vpn_state == NetworkManager.VPNConnectionState.ACTIVATED;
},
setActiveConnection: function(activeConnection) {
if (this._stateChangeId)
this._activeConnection.disconnect(this._stateChangeId);
this._stateChangeId = 0;
this.parent(activeConnection);
if (this._activeConnection)
this._stateChangeId = this._activeConnection.connect('vpn-state-changed',
Lang.bind(this, this._connectionStateChanged));
this.emit('state-changed');
},
_shouldShowConnectionList: function() {
return true;
},
deactivate: function() {
if (this._activeConnection)
this._client.deactivate_connection(this._activeConnection);
},
getStatusLabel: function() {
if (!this._activeConnection) // Same as DISCONNECTED
return null;
switch(this._activeConnection.vpn_state) {
case NetworkManager.VPNConnectionState.DISCONNECTED:
case NetworkManager.VPNConnectionState.ACTIVATED:
return null;
case NetworkManager.VPNConnectionState.PREPARE:
case NetworkManager.VPNConnectionState.CONNECT:
case NetworkManager.VPNConnectionState.IP_CONFIG_GET:
return _("connecting...");
case NetworkManager.VPNConnectionState.NEED_AUTH:
/* Translators: this is for network connections that require some kind of key or password */
return _("authentication required");
case NetworkManager.VPNConnectionState.FAILED:
return _("connection failed");
default:
log('VPN connection state invalid, is %d'.format(this.device.state));
return 'invalid';
}
},
_connectionStateChanged: function(connection, newstate, reason) {
if (newstate == NetworkManager.VPNConnectionState.FAILED) {
// FIXME: if we ever want to show something based on reason,
// we need to convert from NetworkManager.VPNConnectionStateReason
// to NetworkManager.DeviceStateReason
this.emit('activation-failed', reason);
}
// Differently from real NMDevices, there is no need to queue
// an update of the menu section, contents wouldn't change anyway
this.emit('state-changed');
}
});
const NMDeviceWireless = new Lang.Class({
Name: 'NMDeviceWireless',
Extends: NMDevice,
@ -1557,6 +1489,152 @@ const NMDeviceWireless = new Lang.Class({
},
});
const NMVPNSection = new Lang.Class({
Name: 'NMVPNSection',
Extends: NMConnectionBased,
category: NMConnectionCategory.VPN,
_init: function(client, connections) {
this.parent(connections);
this._client = client;
this.section = new PopupMenu.PopupMenuSection();
this._deferredWorkId = Main.initializeDeferredWork(this.section.actor, Lang.bind(this, this._createSection));
},
get empty() {
return this._connections.length == 0;
},
connectionValid: function(connection) {
// filtering is done by NMApplet code
return true;
},
getStatusLabel: function(activeConnection) {
switch(activeConnection.vpn_state) {
case NetworkManager.VPNConnectionState.DISCONNECTED:
case NetworkManager.VPNConnectionState.ACTIVATED:
return null;
case NetworkManager.VPNConnectionState.PREPARE:
case NetworkManager.VPNConnectionState.CONNECT:
case NetworkManager.VPNConnectionState.IP_CONFIG_GET:
return _("connecting...");
case NetworkManager.VPNConnectionState.NEED_AUTH:
/* Translators: this is for network connections that require some kind of key or password */
return _("authentication required");
case NetworkManager.VPNConnectionState.FAILED:
return _("connection failed");
default:
log('VPN connection state invalid, is %d'.format(this.device.state));
return 'invalid';
}
},
clearActiveConnection: function(activeConnection) {
let pos = this._findConnection(activeConnection.uuid);
if (pos < 0)
return;
let obj = this._connections[pos];
obj.active.disconnect(obj.stateChangedId);
obj.active = null;
if (obj.item) {
obj.item.setToggleState(false);
obj.item.setStatus(null);
}
},
setActiveConnection: function(activeConnection) {
let pos = this._findConnection(activeConnection.uuid);
if (pos < 0)
return;
let obj = this._connections[pos];
obj.active = activeConnection;
obj.stateChangedId = obj.active.connect('vpn-state-changed',
Lang.bind(this, this._connectionStateChanged));
if (obj.item) {
obj.item.setToggleState(obj.active.vpn_state ==
NetworkManager.VPNConnectionState.ACTIVATED);
obj.item.setStatus(this.getStatusLabel(obj.active));
}
},
_queueCreateSection: function() {
this.section.removeAll();
Main.queueDeferredWork(this._deferredWorkId);
},
_createConnectionItem: function(obj) {
let menuItem = new PopupMenu.PopupSwitchMenuItem(obj.name, false,
{ style_class: 'popup-subtitle-menu-item' });
menuItem.connect('toggled', Lang.bind(this, function(menuItem) {
if (menuItem.state) {
this._client.activate_connection(obj.connection, null, null, null);
// Immediately go back to disconnected, until NM tells us to change
menuItem.setToggleState(false);
} else if (obj.active) {
this._client.deactivate_connection(obj.active);
}
}));
if (obj.active) {
menuItem.setToggleState(obj.active.vpn_state ==
NetworkManager.VPNConnectionState.ACTIVATED);
menuItem.setStatus(this.getStatusLabel(obj.active));
}
return menuItem;
},
_createSection: function() {
if (this._connections.length > 0) {
this.section.actor.show();
for(let j = 0; j < this._connections.length; ++j) {
let obj = this._connections[j];
obj.item = this._createConnectionItem(obj);
if (j >= NUM_VISIBLE_NETWORKS) {
if (!this._overflowItem) {
this._overflowItem = new PopupMenu.PopupSubMenuMenuItem(_("More..."));
this.section.addMenuItem(this._overflowItem);
}
this._overflowItem.menu.addMenuItem(obj.item);
} else
this.section.addMenuItem(obj.item);
}
} else {
this.section.actor.hide()
}
},
_connectionStateChanged: function(vpnConnection, newstate, reason) {
if (newstate == NetworkManager.VPNConnectionState.FAILED &&
reason != NetworkManager.VPNConnectionStateReason.NO_SECRETS) {
// FIXME: if we ever want to show something based on reason,
// we need to convert from NetworkManager.VPNConnectionStateReason
// to NetworkManager.DeviceStateReason
this.emit('activation-failed', reason);
}
let pos = this._findConnection(vpnConnection.uuid);
if (pos >= 0) {
let obj = this._connections[pos];
if (obj.item) {
obj.item.setToggleState(vpnConnection.vpn_state ==
NetworkManager.VPNConnectionState.ACTIVATED);
obj.item.setStatus(this.getStatusLabel(vpnConnection));
}
} else {
log('Could not find connection for vpn-state-changed handler');
}
},
});
const NMApplet = new Lang.Class({
Name: 'NMApplet',
Extends: PanelMenu.SystemStatusButton,
@ -1622,15 +1700,9 @@ const NMApplet = new Lang.Class({
this.menu.addMenuItem(this._devices.wwan.section);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._devices.vpn = {
section: new PopupMenu.PopupMenuSection(),
device: this._makeWrapperDevice(NMDeviceVPN, null),
item: new NMWiredSectionTitleMenuItem(_("VPN Connections"))
};
this._devices.vpn.section.addMenuItem(this._devices.vpn.item);
this._devices.vpn.section.addMenuItem(this._devices.vpn.device.section);
this._devices.vpn.section.actor.hide();
this.menu.addMenuItem(this._devices.vpn.section);
this._vpnSection = new NMVPNSection(this._client, this._connections);
this._vpnSection.connect('activation-failed', Lang.bind(this, this._onActivationFailed));
this.menu.addMenuItem(this._vpnSection.section);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
@ -1640,6 +1712,7 @@ const NMApplet = new Lang.Class({
this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth;
this._dtypes[NetworkManager.DeviceType.INFINIBAND] = NMDeviceSimple;
// TODO: WiMax support
// Connection types
@ -1651,6 +1724,7 @@ const NMApplet = new Lang.Class({
this._ctypes[NetworkManager.SETTING_BLUETOOTH_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_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED;
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
this._settings = NMClient.RemoteSettings.new(null);
@ -1699,18 +1773,6 @@ const NMApplet = new Lang.Class({
},
_syncSectionTitle: function(category) {
if (category == NMConnectionCategory.VPN) {
// Special case VPN: it's only one device (and a fake one
// actually), and we don't show it if empty
let device = this._devices.vpn.device;
let section = this._devices.vpn.section;
let item = this._devices.vpn.item;
section.actor.visible = !device.empty;
item.updateForDevice(device);
return;
}
let devices = this._devices[category].devices;
let item = this._devices[category].item;
let section = this._devices[category].section;
@ -1758,17 +1820,20 @@ const NMApplet = new Lang.Class({
this._source.notify(device._notification);
},
_onActivationFailed: function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
this._notifyForDevice(device, 'network-error-symbolic',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
},
_makeWrapperDevice: function(wrapperClass, device) {
let wrapper = new wrapperClass(this._client, device, this._connections);
wrapper._activationFailedId = wrapper.connect('activation-failed', Lang.bind(this, function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
this._notifyForDevice(device, 'network-error-symbolic',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
}));
wrapper._activationFailedId = wrapper.connect('activation-failed',
Lang.bind(this, this._onActivationFailed));
wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
this._syncSectionTitle(dev.category);
}));
@ -1851,7 +1916,7 @@ const NMApplet = new Lang.Class({
for (let i = 0; i < closedConnections.length; i++) {
let active = closedConnections[i];
if (active._primaryDevice) {
active._primaryDevice.setActiveConnection(null);
active._primaryDevice.clearActiveConnection(active);
active._primaryDevice = null;
}
if (active._inited) {
@ -1918,7 +1983,7 @@ const NMApplet = new Lang.Class({
}
}
} else
a._primaryDevice = this._devices.vpn.device
a._primaryDevice = this._vpnSection;
if (a._primaryDevice)
a._primaryDevice.setActiveConnection(a);
@ -2000,8 +2065,7 @@ const NMApplet = new Lang.Class({
let section = connection._section;
if (section == NMConnectionCategory.VPN) {
this._devices.vpn.device.removeConnection(connection);
this._syncSectionTitle(section);
this._vpnSection.removeConnection(connection);
} else if (section != NMConnectionCategory.INVALID) {
let devices = this._devices[section].devices;
for (let i = 0; i < devices.length; i++)
@ -2024,8 +2088,7 @@ const NMApplet = new Lang.Class({
if (section == NMConnectionCategory.INVALID)
return;
if (section == NMConnectionCategory.VPN) {
this._devices.vpn.device.checkConnection(connection);
this._syncSectionTitle(section);
this._vpnSection.checkConnection(connection);
} else {
let devices = this._devices[section].devices;
for (let i = 0; i < devices.length; i++) {
@ -2051,7 +2114,6 @@ const NMApplet = new Lang.Class({
this._syncSectionTitle(NMConnectionCategory.WIRED);
this._syncSectionTitle(NMConnectionCategory.WIRELESS);
this._syncSectionTitle(NMConnectionCategory.WWAN);
this._syncSectionTitle(NMConnectionCategory.VPN);
},
_syncNMState: function() {

View File

@ -96,7 +96,7 @@ const Indicator = new Lang.Class({
let minutes = time % 60;
let hours = Math.floor(time / 60);
let timestring;
if (time > 60) {
if (time >= 60) {
if (minutes == 0) {
timestring = ngettext("%d hour remaining", "%d hours remaining", hours).format(hours);
} else {

View File

@ -2,6 +2,7 @@
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Gvc = imports.gi.Gvc;
const St = imports.gi.St;
@ -32,6 +33,8 @@ const VolumeMenu = new Lang.Class({
_init: function(control) {
this.parent();
this.hasHeadphones = false;
this._control = control;
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
this._control.connect('default-sink-changed', Lang.bind(this, this._readOutput));
@ -98,20 +101,47 @@ const VolumeMenu = new Lang.Class({
}
},
_findHeadphones: function(sink) {
// This only works for external headphones (e.g. bluetooth)
if (sink.get_form_factor() == 'headset' ||
sink.get_form_factor() == 'headphone')
return true;
// a bit hackish, but ALSA/PulseAudio have a number
// of different identifiers for headphones, and I could
// not find the complete list
let port = sink.get_port();
if (port)
return port.port.indexOf('headphone') >= 0;
return false;
},
_portChanged: function() {
this.hasHeadphones = this._findHeadphones(this._output);
this.emit('headphones-changed');
},
_readOutput: function() {
if (this._outputVolumeId) {
this._output.disconnect(this._outputVolumeId);
this._output.disconnect(this._outputMutedId);
this._output.disconnect(this._outputPortId);
this._outputVolumeId = 0;
this._outputMutedId = 0;
this._outputPortId = 0;
}
this._output = this._control.get_default_sink();
if (this._output) {
this._outputMutedId = this._output.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_output'));
this._outputVolumeId = this._output.connect('notify::volume', Lang.bind(this, this._volumeChanged, '_output'));
this._mutedChanged (null, null, '_output');
this._volumeChanged (null, null, '_output');
this._outputPortId = this._output.connect('notify::port', Lang.bind(this, this._portChanged));
this._mutedChanged(null, null, '_output');
this._volumeChanged(null, null, '_output');
this._portChanged();
} else {
this.hasHeadphones = false;
this._outputSlider.setValue(0);
this.emit('icon-changed', 'audio-volume-muted-symbolic');
}
@ -227,6 +257,12 @@ const Indicator = new Lang.Class({
this.setIcon(icon);
this._syncVisibility();
}));
this._volumeMenu.connect('headphones-changed', Lang.bind(this, function() {
this._syncVisibility();
}));
this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' }));
this._headphoneIcon.visible = false;
this.menu.addMenuItem(this._volumeMenu);
@ -239,6 +275,7 @@ const Indicator = new Lang.Class({
_syncVisibility: function() {
this.actor.visible = this._hasPulseAudio;
this.mainIcon.visible = this._hasPulseAudio;
this._headphoneIcon.visible = this._hasPulseAudio && this._volumeMenu.hasHeadphones;
},
_onScrollEvent: function(actor, event) {

641
js/ui/switcherPopup.js Normal file
View File

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

View File

@ -14,12 +14,14 @@ const St = imports.gi.St;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Panel = imports.ui.panel;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu;
const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util;
const LoginDialog = imports.gdm.loginDialog;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
@ -113,6 +115,7 @@ const UnlockDialog = new Lang.Class({
_init: function(parentActor) {
this.parent({ shellReactive: true,
styleClass: 'login-dialog',
keybindingMode: Main.KeybindingMode.UNLOCK_SCREEN,
parentActor: parentActor
});
@ -150,7 +153,9 @@ const UnlockDialog = new Lang.Class({
this._promptEntry.clutter_text.set_password_char('\u25cf');
ShellEntry.addContextMenu(this._promptEntry, { isPassword: true });
this.setInitialKeyFocus(this._promptEntry);
this._promptEntry.clutter_text.connect('activate', Lang.bind(this, this._doUnlock));
this._promptEntry.clutter_text.connect('text-changed', Lang.bind(this, function() {
this._updateOkButtonSensitivity(this._promptEntry.text.length > 0);
}));
this._promptLayout.add(this._promptEntry,
{ expand: true,
@ -165,15 +170,33 @@ const UnlockDialog = new Lang.Class({
this._promptLoginHint.hide();
this.contentLayout.add_actor(this._promptLoginHint);
let cancelButton = { label: _("Cancel"),
action: Lang.bind(this, this._escape),
key: Clutter.KEY_Escape };
this._okButton = { label: _("Unlock"),
action: Lang.bind(this, this._doUnlock),
default: true };
this.setButtons([cancelButton, this._okButton]);
this._workSpinner = new Panel.AnimatedIcon('process-working.svg', LoginDialog.WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._updateSensitivity(true);
this.allowCancel = false;
this.buttonLayout.visible = true;
this.addButton({ label: _("Cancel"),
action: Lang.bind(this, this._escape),
key: Clutter.KEY_Escape },
{ expand: true,
x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this.buttonLayout.add(this._workSpinner.actor,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._okButton = this.addButton({ label: _("Unlock"),
action: Lang.bind(this, this._doUnlock),
default: true },
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
style_class: 'login-dialog-not-listed-label' });
@ -188,6 +211,8 @@ const UnlockDialog = new Lang.Class({
{ x_align: St.Align.START,
x_fill: false });
this._updateSensitivity(true);
let batch = new Batch.Hold();
this._userVerifier.begin(this._userName, batch);
@ -196,6 +221,8 @@ const UnlockDialog = new Lang.Class({
return false;
}));
Main.ctrlAltTabManager.addGroup(this.dialogLayout, _("Unlock Window"), 'dialog-password-symbolic');
this._idleMonitor = new GnomeDesktop.IdleMonitor();
this._idleWatchId = this._idleMonitor.add_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
},
@ -203,14 +230,46 @@ const UnlockDialog = new Lang.Class({
_updateSensitivity: function(sensitive) {
this._promptEntry.reactive = sensitive;
this._promptEntry.clutter_text.editable = sensitive;
this._okButton.button.reactive = sensitive;
this._okButton.button.can_focus = sensitive;
this._updateOkButtonSensitivity(sensitive && this._promptEntry.text.length > 0);
this._otherUserButton.reactive = sensitive;
this._otherUserButton.can_focus = sensitive;
},
_updateOkButtonSensitivity: function(sensitive) {
this._okButton.reactive = sensitive;
this._okButton.can_focus = sensitive;
},
_setWorking: function(working) {
if (working) {
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: LoginDialog.WORK_SPINNER_ANIMATION_DELAY,
time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
this._workSpinner.stop();
}
});
}
},
_showMessage: function(userVerifier, message, styleClass) {
this._promptMessage.text = message;
this._promptMessage.styleClass = styleClass;
GdmUtil.fadeInActor(this._promptMessage);
if (message) {
this._promptMessage.text = message;
this._promptMessage.styleClass = styleClass;
GdmUtil.fadeInActor(this._promptMessage);
} else {
GdmUtil.fadeOutActor(this._promptMessage);
}
},
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
@ -233,6 +292,7 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = serviceName;
this._updateSensitivity(true);
this._setWorking(false);
},
_showLoginHint: function(verifier, message) {
@ -251,6 +311,7 @@ const UnlockDialog = new Lang.Class({
// the actual reply to GDM will be sent as soon as asked
this._firstQuestionAnswer = this._promptEntry.text;
this._updateSensitivity(false);
this._setWorking(true);
return;
}
@ -261,6 +322,7 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = null;
this._updateSensitivity(false);
this._setWorking(true);
this._userVerifier.answerQuery(query, this._promptEntry.text);
},
@ -278,15 +340,19 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = null;
this._firstQuestion = true;
this._promptEntry.text = '';
this._promptEntry.clutter_text.set_password_char('\u25cf');
this._promptEntry.menu.isPassword = true;
this._updateSensitivity(false);
this._setWorking(false);
},
_escape: function() {
this._userVerifier.cancel();
this.emit('failed');
if (this.allowCancel) {
this._userVerifier.cancel();
this.emit('failed');
}
},
_otherUserClicked: function(button, event) {

View File

@ -26,6 +26,8 @@ const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
const LOCK_ENABLED_KEY = 'lock-enabled';
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
const SHOW_FULL_NAME_KEY = 'show-full-name';
const DIALOG_ICON_SIZE = 64;
@ -187,7 +189,7 @@ const IMStatusChooserItem = new Lang.Class({
item = new IMStatusItem(_("Idle"), 'user-idle-symbolic');
this._combo.addMenuItem(item, IMStatus.IDLE);
item = new IMStatusItem(_("Unavailable"), 'user-offline-symbolic');
item = new IMStatusItem(_("Offline"), 'user-offline-symbolic');
this._combo.addMenuItem(item, IMStatus.OFFLINE);
this._combo.connect('active-item-changed',
@ -549,9 +551,12 @@ const UserMenuButton = new Lang.Class({
Lang.bind(this, this._updateSwitchUser));
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
Lang.bind(this, this._updateLogout));
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
Lang.bind(this, this._updateLockScreen));
this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_KEY,
Lang.bind(this, this._updateUserName));
global.settings.connect('changed::' + SHOW_FULL_NAME_KEY,
Lang.bind(this, this._updateUserName));
this._updateSwitchUser();
this._updateLogout();
this._updateLockScreen();
@ -588,6 +593,7 @@ const UserMenuButton = new Lang.Class({
this.setSensitive(!Main.sessionMode.isLocked);
this._updatePresenceIcon();
this._updateUserName();
},
_onDestroy: function() {
@ -596,7 +602,10 @@ const UserMenuButton = new Lang.Class({
},
_updateUserName: function() {
if (this._user.is_loaded)
let settings = global.settings;
if (Main.sessionMode.isLocked)
settings = this._screenSaverSettings;
if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_KEY))
this._name.set_text(this._user.get_real_name());
else
this._name.set_text("");
@ -616,10 +625,13 @@ const UserMenuButton = new Lang.Class({
_updateLogout: function() {
let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY);
let alwaysShow = global.settings.get_boolean(ALWAYS_SHOW_LOG_OUT_KEY);
let systemAccount = this._user.system_account;
let localAccount = this._user.local_account;
let multiUser = this._userManager.has_multiple_users;
let multiSession = Gdm.get_session_ids().length > 1;
this._logoutItem.actor.visible = allowLogout && (multiUser || multiSession);
this._logoutItem.actor.visible = allowLogout && (alwaysShow || multiUser || multiSession || systemAccount || !localAccount);
},
_updateLockScreen: function() {
@ -748,7 +760,7 @@ const UserMenuButton = new Lang.Class({
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
item = new PopupMenu.PopupMenuItem(_("System Settings"));
item = new PopupMenu.PopupMenuItem(_("Settings"));
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
this.menu.addMenuItem(item);
this._systemSettings = item;

View File

@ -39,17 +39,11 @@ const ViewSelector = new Lang.Class({
Name: 'ViewSelector',
_init : function(searchEntry, showAppsButton) {
this.actor = new St.BoxLayout({ name: 'viewSelector',
vertical: true });
this.actor = new Shell.Stack({ name: 'viewSelector' });
this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
this._pageArea = new Shell.Stack();
this.actor.add(this._pageArea, { x_fill: true,
y_fill: true,
expand: true });
this._activePage = null;
this.active = false;
@ -84,16 +78,21 @@ const ViewSelector = new Lang.Class({
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this._workspacesPage = this._addPage(this._workspacesDisplay.actor, null,
_("Windows"), 'text-x-generic-symbolic');
_("Windows"), 'emblem-documents-symbolic');
this._appDisplay = new AppDisplay.AllAppDisplay();
this._appsPage = this._addPage(this._appDisplay.actor, null,
_("Applications"), 'system-run-symbolic');
_("Applications"), 'view-grid-symbolic');
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
_("Search"), 'edit-find-symbolic');
this._searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
// Default search providers
// Wanda comes obviously first
this.addSearchProvider(new Wanda.WandaSearchProvider());
@ -133,26 +132,17 @@ const ViewSelector = new Lang.Class({
}
}));
// Public constraints which may be used to tie actors' height or
// vertical position to the current tab's content; as the content's
// height and position depend on the view selector's style properties
// (e.g. font size, padding, spacing, ...) it would be extremely hard
// and ugly to get these from the outside. While it would be possible
// to use position and height properties directly, outside code would
// need to ensure that the content is properly allocated before
// accessing the properties.
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
coordinate: Clutter.BindCoordinate.HEIGHT });
global.display.add_keybinding('toggle-application-view',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Lang.bind(this, this._showWithAppsPage));
Main.wm.addKeybinding('toggle-application-view',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._toggleAppsPage));
},
_showWithAppsPage: function() {
_toggleAppsPage: function() {
Main.overview.show();
this._showAppsButton.set_checked(true);
this._showAppsButton.checked = !this._showAppsButton.checked;
},
show: function() {
@ -195,8 +185,8 @@ const ViewSelector = new Lang.Class({
this._a11yFocusPage(page);
})
});;
this._pageArea.add_actor(page);
return page
this.actor.add_actor(page);
return page;
},
_showPage: function(page) {
@ -242,6 +232,11 @@ const ViewSelector = new Lang.Class({
},
_onStageKeyPress: function(actor, event) {
// Ignore events while anything but the overview has
// pushed a modal (system modals, looking glass, ...)
if (Main.modalCount > 1)
return false;
let modifiers = event.get_state();
let symbol = event.get_key_symbol();
@ -433,7 +428,32 @@ const ViewSelector = new Lang.Class({
this._showPage(this._searchPage);
},
_shouldUseSearchProvider: function(provider) {
// the disable-external GSetting only affects remote providers
if (!provider.isRemoteProvider)
return true;
if (this._searchSettings.get_boolean('disable-external'))
return false;
let appId = provider.appInfo.get_id();
let disable = this._searchSettings.get_strv('disabled');
return disable.indexOf(appId) == -1;
},
_reloadRemoteProviders: function() {
// removeSearchProvider() modifies the provider list we iterate on,
// so make a copy first
let remoteProviders = this._searchSystem.getRemoteProviders().slice(0);
remoteProviders.forEach(Lang.bind(this, this.removeSearchProvider));
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
},
addSearchProvider: function(provider) {
if (!this._shouldUseSearchProvider(provider))
return;
this._searchSystem.registerProvider(provider);
this._searchResults.createProviderMeta(provider);
},

View File

@ -9,7 +9,7 @@ const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Search = imports.ui.search;
const Panel = imports.ui.panel;
// we could make these gsettings
const FISH_NAME = 'wanda';
@ -53,20 +53,9 @@ const WandaIcon = new Lang.Class({
icon_size: iconSize });
}
this._animations = St.TextureCache.get_default().load_sliced_image(this._imageFile, this._imgWidth, this._imgHeight);
this._animations.connect('notify::mapped', Lang.bind(this, function() {
if (this._animations.mapped && !this._timeoutId) {
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, FISH_SPEED, Lang.bind(this, this._update));
this._i = 0;
this._update();
} else if (!this._animations.mapped && this._timeoutId) {
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
}));
return this._animations;
this._animations = new Panel.Animation(this._imageFile, this._imgWidth, this._imgHeight, FISH_SPEED);
this._animations.play();
return this._animations.actor;
},
_createIconTexture: function(size) {
@ -74,28 +63,14 @@ const WandaIcon = new Lang.Class({
return;
this.parent(size);
},
_update: function() {
let n = this._animations.get_n_children();
if (n == 0) {
return true;
}
this._animations.get_child_at_index(this._i).hide();
this._i = (this._i + 1) % n;
this._animations.get_child_at_index(this._i).show();
return true;
},
}
});
const WandaIconBin = new Lang.Class({
Name: 'WandaIconBin',
_init: function(fish, label, params) {
this.actor = new St.Bin({ style_class: 'search-result-content',
reactive: true,
this.actor = new St.Bin({ reactive: true,
track_hover: true });
this.icon = new WandaIcon(fish, label, params);
@ -156,10 +131,9 @@ function capitalize(str) {
const WandaSearchProvider = new Lang.Class({
Name: 'WandaSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
this.parent(_("Your favorite Easter Egg"));
this.id = 'wanda';
},
getResultMetas: function(fish, callback) {
@ -185,7 +159,7 @@ const WandaSearchProvider = new Lang.Class({
this.getInitialResultSet(terms);
},
activateResult: function(fish, params) {
activateResult: function(fish) {
if (this._dialog)
this._dialog.destroy();
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);

View File

@ -39,6 +39,8 @@ const WindowAttentionHandler = new Lang.Class({
let [title, banner] = this._getTitleAndBanner(app, window);
let notification = new MessageTray.Notification(source, title, banner);
notification.setForFeedback(true);
source.notify(notification);
source.signalIDs.push(window.connect('notify::title', Lang.bind(this, function() {

View File

@ -83,6 +83,8 @@ const WindowManager = new Lang.Class({
this._animationBlockCount = 0;
this._allowedKeybindings = {};
this._switchData = null;
this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
this._shellwm.connect('kill-window-effects', Lang.bind(this, function (shellwm, actor) {
@ -99,38 +101,79 @@ const WindowManager = new Lang.Class({
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
this._workspaceSwitcherPopup = null;
Meta.keybindings_set_custom_handler('switch-to-workspace-left',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-right',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-up',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-down',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-left',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-right',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-up',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-down',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-windows',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-windows-backward',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group-backward',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-panels',
Lang.bind(this, this._startA11ySwitcher));
global.display.add_keybinding('open-application-menu',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Lang.bind(this, this._openAppMenu));
this.setCustomKeybindingHandler('switch-to-workspace-left',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-right',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-up',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-down',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-left',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-right',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-up',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-down',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-applications',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-group',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-applications-backward',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-group-backward',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher));
this.setCustomKeybindingHandler('switch-windows',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('switch-windows-backward',
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('switch-panels',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW |
Main.KeybindingMode.LOCK_SCREEN |
Main.KeybindingMode.UNLOCK_SCREEN |
Main.KeybindingMode.LOGIN_SCREEN,
Lang.bind(this, this._startA11ySwitcher));
this.setCustomKeybindingHandler('switch-panels-backward',
Main.KeybindingMode.NORMAL |
Main.KeybindingMode.OVERVIEW |
Main.KeybindingMode.LOCK_SCREEN |
Main.KeybindingMode.UNLOCK_SCREEN |
Main.KeybindingMode.LOGIN_SCREEN,
Lang.bind(this, this._startA11ySwitcher));
this.addKeybinding('open-application-menu',
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Main.KeybindingMode.NORMAL,
Lang.bind(this, this._openAppMenu));
Main.overview.connect('showing', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++)
@ -142,6 +185,27 @@ const WindowManager = new Lang.Class({
}));
},
setCustomKeybindingHandler: function(name, modes, handler) {
if (Meta.keybindings_set_custom_handler(name, handler))
this.allowKeybinding(name, modes);
},
addKeybinding: function(name, settings, flags, modes, handler) {
let action = global.display.add_keybinding(name, settings, flags, handler);
if (action != Meta.KeyBindingAction.NONE)
this.allowKeybinding(name, modes);
return action;
},
removeKeybinding: function(name) {
if (global.display.remove_keybinding(name))
this.allowKeybinding(name, Main.KeybindingMode.NONE);
},
allowKeybinding: function(name, modes) {
this._allowedKeybindings[name] = modes;
},
blockAnimations: function() {
this._animationBlockCount++;
},
@ -157,7 +221,9 @@ const WindowManager = new Lang.Class({
_shouldAnimateActor: function(actor) {
if (!this._shouldAnimate())
return false;
return actor.meta_window.get_window_type() == Meta.WindowType.NORMAL;
let windowType = actor.meta_window.get_window_type();
return windowType == Meta.WindowType.NORMAL ||
windowType == Meta.WindowType.MODAL_DIALOG;
},
_removeEffect : function(list, actor) {
@ -183,16 +249,17 @@ const WindowManager = new Lang.Class({
*/
this._minimizing.push(actor);
let primary = Main.layoutManager.primaryMonitor;
let xDest = primary.x;
let monitor = Main.layoutManager.findMonitorForWindow(actor.meta_window);
let xDest = monitor.x;
let yDest = monitor.y;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
xDest += primary.width;
xDest += monitor.width;
Tweener.addTween(actor,
{ scale_x: 0.0,
scale_y: 0.0,
x: xDest,
y: 0,
y: yDest,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone,
@ -307,57 +374,56 @@ const WindowManager = new Lang.Class({
actor._windowType = type;
}));
if (actor.meta_window.is_attached_dialog()) {
this._checkDimming(actor.get_meta_window().get_transient_for());
if (this._shouldAnimate()) {
actor.set_scale(1.0, 0.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_y: 1,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
return;
}
shellwm.completed_map(actor);
return;
}
if (!this._shouldAnimateActor(actor)) {
shellwm.completed_map(actor);
return;
}
actor.opacity = 0;
actor.show();
if (actor.meta_window.is_attached_dialog()) {
/* Scale the window from the center of the parent */
this._checkDimming(actor.get_meta_window().get_transient_for());
actor.set_scale(1.0, 0.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show();
this._mapping.push(actor);
/* Fade window in */
this._mapping.push(actor);
Tweener.addTween(actor,
{ opacity: 255,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
Tweener.addTween(actor,
{ scale_y: 1,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
} else {
/* Fade window in */
actor.opacity = 0;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ opacity: 255,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
}
},
_mapWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
Tweener.removeTweens(actor);
actor.opacity = 255;
actor.scale_y = 1;
shellwm.completed_map(actor);
}
},
@ -379,18 +445,21 @@ const WindowManager = new Lang.Class({
return win != window;
});
}
if (!this._shouldAnimateActor(actor)) {
shellwm.completed_destroy(actor);
return;
}
this._destroying.push(actor);
if (window.is_attached_dialog()) {
let parent = window.get_transient_for();
this._checkDimming(parent, window);
if (!this._shouldAnimate()) {
shellwm.completed_destroy(actor);
return;
}
actor.set_scale(1.0, 1.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show();
this._destroying.push(actor);
actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
Tweener.removeTweens(actor);
@ -424,6 +493,21 @@ const WindowManager = new Lang.Class({
}
},
_filterKeybinding: function(shellwm, binding) {
if (Main.keybindingMode == Main.KeybindingMode.NONE)
return true;
// There's little sense in implementing a keybinding in mutter and
// not having it work in NORMAL mode; handle this case generically
// so we don't have to explicitly allow all builtin keybindings in
// NORMAL mode.
if (Main.keybindingMode == Main.KeybindingMode.NORMAL &&
binding.is_builtin())
return false;
return !(this._allowedKeybindings[binding.get_name()] & Main.keybindingMode);
},
_switchWorkspace : function(shellwm, from, to, direction) {
if (!this._shouldAnimate()) {
shellwm.completed_switch_workspace();
@ -546,7 +630,20 @@ const WindowManager = new Lang.Class({
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.AltTabPopup();
let tabPopup = new AltTab.AppSwitcherPopup();
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
_startWindowSwitcher : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.WindowSwitcherPopup();
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
@ -557,7 +654,7 @@ const WindowManager = new Lang.Class({
_startA11ySwitcher : function(display, screen, window, binding) {
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask());
},
_openAppMenu : function(display, screen, window, event, binding) {

View File

@ -124,6 +124,8 @@ const WindowClone = new Lang.Class({
this.actor._delegate = this;
this._slot = [0, 0, 0, 0];
this._dragSlot = [0, 0, 0, 0];
this._stackAbove = null;
this._sizeChangedId = this.realWindow.connect('size-changed',
@ -159,6 +161,17 @@ const WindowClone = new Lang.Class({
this._selected = false;
},
set slot(slot) {
this._slot = slot;
},
get slot() {
if (this.inDrag)
return this._dragSlot;
else
return this._slot;
},
setStackAbove: function (actor) {
this._stackAbove = actor;
if (this.inDrag || this._zooming)
@ -374,6 +387,7 @@ const WindowClone = new Lang.Class({
if (this._zooming)
this._zoomEnd();
this._dragSlot = this._slot;
[this.dragOrigX, this.dragOrigY] = this.actor.get_position();
this.dragOrigScale = this.actor.scale_x;
this.inDrag = true;
@ -427,6 +441,11 @@ const WindowOverlay = new Lang.Class({
this._parentActor = parentActor;
this._hidden = false;
this._settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
this.borderSize = 0;
this.border = new St.Bin({ style_class: 'window-clone-border' });
let title = new St.Label({ style_class: 'window-caption',
text: metaWindow.title });
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
@ -435,6 +454,7 @@ const WindowOverlay = new Lang.Class({
this._updateCaptionId = metaWindow.connect('notify::title',
Lang.bind(this, function(w) {
this.title.text = w.title;
this.relayout(false);
}));
let button = new St.Button({ style_class: 'window-close' });
@ -459,11 +479,13 @@ const WindowOverlay = new Lang.Class({
this.closeButton = button;
parentActor.add_actor(this.title);
parentActor.add_actor(this.border);
parentActor.add_actor(this.closeButton);
title.connect('style-changed',
Lang.bind(this, this._onStyleChanged));
button.connect('style-changed',
Lang.bind(this, this._onStyleChanged));
this.border.connect('style-changed', Lang.bind(this, this._onStyleChanged));
// force a style change if we are already on a stage - otherwise
// the signal will be emitted normally when we are added
if (parentActor.get_stage())
@ -472,15 +494,17 @@ const WindowOverlay = new Lang.Class({
hide: function() {
this._hidden = true;
this.closeButton.hide();
this.title.hide();
this.hideCloseButton();
},
show: function() {
this._hidden = false;
if (this._windowClone.actor.has_pointer)
this.closeButton.show();
this.title.show();
if (this._windowClone.actor.has_pointer)
this._animateVisible();
},
fadeIn: function() {
@ -497,26 +521,21 @@ const WindowOverlay = new Lang.Class({
},
chromeHeights: function () {
return [this.closeButton.height - this.closeButton._overlap,
return [Math.max(this.borderSize, this.closeButton.height - this.closeButton._overlap),
this.title.height + this.title._spacing];
},
/**
* @cloneX: x position of windowClone
* @cloneY: y position of windowClone
* @cloneWidth: width of windowClone
* @cloneHeight height of windowClone
*/
// These parameters are not the values retrieved with
// get_transformed_position() and get_transformed_size(),
// as windowClone might be moving.
// See Workspace._showWindowOverlay
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, animate) {
chromeWidths: function () {
return [this.borderSize, this.borderSize];
},
relayout: function(animate) {
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
let button = this.closeButton;
let title = this.title;
let settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
let layout = settings.get_string(BUTTON_LAYOUT_KEY);
let layout = this._settings.get_string(BUTTON_LAYOUT_KEY);
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
let split = layout.split(":");
@ -538,9 +557,16 @@ const WindowOverlay = new Lang.Class({
else
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
if (!title.fullWidth)
title.fullWidth = title.width;
let titleWidth = Math.min(title.fullWidth, cloneWidth);
// Clutter.Actor.get_preferred_width() will return the fixed width if one
// is set, so we need to reset the width by calling set_width(-1), to forward
// the call down to StLabel.
// We also need to save and restore the current width, otherwise the animation
// starts from the wrong point.
let prevTitleWidth = title.width;
title.set_width(-1);
let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1);
let titleWidth = Math.max(titleMinWidth, Math.min(titleNatWidth, cloneWidth));
title.width = prevTitleWidth;
let titleX = cloneX + (cloneWidth - titleWidth) / 2;
let titleY = cloneY + cloneHeight + title._spacing;
@ -551,16 +577,32 @@ const WindowOverlay = new Lang.Class({
title.width = titleWidth;
title.set_position(Math.floor(titleX), Math.floor(titleY));
}
let borderX = cloneX - this.borderSize;
let borderY = cloneY - this.borderSize;
let borderWidth = cloneWidth + 2 * this.borderSize;
let borderHeight = cloneHeight + 2 * this.borderSize;
if (animate) {
this._animateOverlayActor(this.border, borderX, borderY,
borderWidth, borderHeight);
} else {
this.border.set_position(borderX, borderY);
this.border.set_size(borderWidth, borderHeight);
}
},
_animateOverlayActor: function(actor, x, y, width) {
Tweener.addTween(actor,
{ x: x,
y: y,
width: width,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad'
});
_animateOverlayActor: function(actor, x, y, width, height) {
let params = { x: x,
y: y,
width: width,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' };
if (height !== undefined)
params.height = height;
Tweener.addTween(actor, params);
},
_closeWindow: function(actor) {
@ -603,6 +645,43 @@ const WindowOverlay = new Lang.Class({
this._windowClone.metaWindow.disconnect(this._updateCaptionId);
this.title.destroy();
this.closeButton.destroy();
this.border.destroy();
},
_animateVisible: function() {
this._parentActor.raise_top();
this.closeButton.show();
this.closeButton.opacity = 0;
Tweener.addTween(this.closeButton,
{ opacity: 255,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeOutQuad' });
this.border.show();
this.border.opacity = 0;
Tweener.addTween(this.border,
{ opacity: 255,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeOutQuad' });
this.title.add_style_pseudo_class('hover');
},
_animateInvisible: function() {
this.closeButton.opacity = 255;
Tweener.addTween(this.closeButton,
{ opacity: 0,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeInQuad' });
this.border.opacity = 255;
Tweener.addTween(this.border,
{ opacity: 0,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeInQuad' });
this.title.remove_style_pseudo_class('hover');
},
_onEnter: function() {
@ -612,8 +691,8 @@ const WindowOverlay = new Lang.Class({
// are shown again
if (this._hidden)
return;
this._parentActor.raise_top();
this.closeButton.show();
this._animateVisible();
this.emit('show-close-button');
},
@ -624,9 +703,10 @@ const WindowOverlay = new Lang.Class({
_idleToggleCloseButton: function() {
this._idleToggleCloseId = 0;
if (!this._windowClone.actor.has_pointer &&
!this.closeButton.has_pointer)
this.closeButton.hide();
this._animateInvisible();
return false;
},
@ -637,6 +717,8 @@ const WindowOverlay = new Lang.Class({
this._idleToggleCloseId = 0;
}
this.closeButton.hide();
this.border.hide();
this.title.remove_style_pseudo_class('hover');
},
_onStyleChanged: function() {
@ -646,6 +728,9 @@ const WindowOverlay = new Lang.Class({
let closeNode = this.closeButton.get_theme_node();
this.closeButton._overlap = closeNode.get_length('-shell-close-overlap');
let borderNode = this.border.get_theme_node();
this.borderSize = borderNode.get_border_width(St.Side.TOP);
this._parentActor.queue_relayout();
}
});
@ -1087,8 +1172,8 @@ const Workspace = new Lang.Class({
let slot = slots[i];
let clone = clones[i];
let metaWindow = clone.metaWindow;
let mainIndex = this._lookupIndex(metaWindow);
let overlay = this._windowOverlays[mainIndex];
let overlay = clone.overlay;
clone.slotId = i;
// Positioning a window currently being dragged must be avoided;
// we'll just leave a blank spot in the layout for it.
@ -1096,6 +1181,7 @@ const Workspace = new Lang.Class({
continue;
let [x, y, scale] = slot;
clone.slot = [x, y, clone.actor.width * scale, clone.actor.height * scale];
if (overlay && initialPositioning)
overlay.hide();
@ -1127,7 +1213,7 @@ const Workspace = new Lang.Class({
Tweener.removeTweens(clone.actor);
clone.actor.set_position(x, y);
clone.actor.set_scale(scale, scale);
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
clone.overlay.relayout(false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
}
}
@ -1162,15 +1248,7 @@ const Workspace = new Lang.Class({
})
});
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, true);
},
_updateWindowOverlayPositions: function(clone, overlay, x, y, scale, animate) {
if (!overlay)
return;
let [cloneWidth, cloneHeight] = clone.actor.get_size();
overlay.updatePositions(x, y, cloneWidth * scale, cloneHeight * scale, animate);
clone.overlay.relayout(true);
},
_showWindowOverlay: function(clone, overlay, fade) {
@ -1305,9 +1383,10 @@ const Workspace = new Lang.Class({
let scale = win._overviewHint.scale;
delete win._overviewHint;
clone.slot = [x, y, clone.actor.width * scale, clone.actor.height * scale];
clone.actor.set_position (x, y);
clone.actor.set_scale (scale, scale);
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
clone.overlay.relayout(false);
} else {
// Position new windows at the top corner of the workspace rather
// than where they were placed for real to avoid the window
@ -1472,6 +1551,7 @@ const Workspace = new Lang.Class({
_addWindowClone : function(win) {
let clone = new WindowClone(win, this);
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
clone.overlay = overlay;
clone.connect('selected',
Lang.bind(this, this._onCloneSelected));
@ -1596,20 +1676,25 @@ const Workspace = new Lang.Class({
return [];
let closeButtonHeight, captionHeight;
let leftBorder, rightBorder;
if (this._windowOverlays.length) {
// All of the overlays have the same chrome sizes,
// so just pick the first one.
let overlay = this._windowOverlays[0];
[closeButtonHeight, captionHeight] = overlay.chromeHeights();
[leftBorder, rightBorder] = overlay.chromeWidths();
} else {
[closeButtonHeight, captionHeight] = [0, 0];
}
rowSpacing += captionHeight;
columnSpacing += rightBorder;
let area = { x: this._x, y: this._y, width: this._width, height: this._height };
area.y += closeButtonHeight;
area.height -= closeButtonHeight;
area.x += leftBorder;
area.width -= leftBorder;
if (!this._currentLayout)
this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing, captionHeight);

View File

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

View File

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

View File

@ -1 +1,19 @@
dist_man_MANS = gnome-shell.1
XSLTPROC_FLAGS = \
--nonet \
--stringparam man.output.quietly 1 \
--stringparam funcsynopsis.style ansi \
--stringparam man.th.extra1.suppress 1 \
--stringparam man.authors.section.enabled 0 \
--stringparam man.copyright.section.enabled 0
.xml.1:
$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
man_MANS = \
gnome-shell.1
xml_files = $(man_MANS:.1=.xml)
EXTRA_DIST = $(xml_files)
DISTCLEANFILES = $(man_MANS)

View File

@ -1,94 +0,0 @@
.\" Copyright (c) 2009, Marcelo Jorge Vieira (metal) <metal@alucinados.com>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
.\" Boston, MA 02111-1301 USA.
.TH GNOME-SHELL 1
.SH NAME
gnome-shell \- Graphical shell for the GNOME desktop
.SH SYNOPSIS
.B gnome-shell [options]
.SH DESCRIPTION
GNOME Shell provides core user interface functions for the GNOME 3
desktop, like switching to windows and launching applications. GNOME
Shell takes advantage of the capabilities of modern graphics hardware
and introduces innovative user interface concepts to provide a
visually attractive and easy to use experience.
.SH OPTIONS
.TP
.B \-\-replace
Replace the running window manager
.br
.TP
.B \-\-sm-disable
Disable connection to the session manager
.br
.TP
.B \-\-sm-client-id=ID
Specify session management ID
.br
.TP
.B \-\-sm-save-file=FILE
Initialize session from savefile
.br
.TP
.B \-\-screen=SCREEN
X screen to use
.br
.TP
.B \-d, \-\-display=DISPLAY
X display to use
.br
.TP
.B \-\-sync
Make X calls synchronous
.br
.TP
.B \-\-version
Print version and exit
.br
.TP
.B \-\-help
Display help and exit
.br
.SH BUGS
The bug tracker can be reached by visiting the website
\fIhttps://bugzilla.gnome.org/buglist.cgi?product=gnome-shell\fR
Before sending a bug report, please verify that you have the latest
version of gnome-shell. Many bugs (major and minor) are fixed at each
release, and if yours is out of date, the problem may already have
been solved.
.SH ADDITIONAL INFORMATION
For further information, visit the website \fIhttp://live.gnome.org/GnomeShell\fR

159
man/gnome-shell.xml Normal file
View File

@ -0,0 +1,159 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<refentry id="gnome-shell">
<refentryinfo>
<title>gnome-shell</title>
<productname>gnome-shell</productname>
<authorgroup>
<author>
<contrib>wrote the original gnome-shell man page</contrib>
<firstname>Marcelo Jorge</firstname>
<surname>Vieira</surname>
<email>metal@alucinados.com</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>gnome-shell</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>gnome-shell</refname>
<refpurpose>Graphical shell for the GNOME desktop</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>gnome-shell <arg choice="opt" rep="repeat">OPTION</arg></command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>GNOME shell provides core user
interface functions for the GNOME 3 desktop, like switching
to windows and launching applications. GNOME shell takes
advantage of the capabilities of modern graphics hardware
and introduces innovative user interface concepts to provide
a visually attractive and easy to use experience.</para>
<para>gnome-shell is a required component of
the GNOME desktop, i.e. it is listed in the
RequiredComponents field of
<filename>/usr/share/gnome-session/sessions/gnome.session</filename>.
It is started in the window manager phase of the session.
</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term><option>-r</option>, <option>--replace</option></term>
<listitem><para>Replace the running window manager</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sm-disable</option></term>
<listitem><para>Disable connection to the session manager</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sm-client-id=<replaceable>ID</replaceable></option></term>
<listitem><para>Specify session management <replaceable>ID</replaceable></para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sm-save-file=<replaceable>FILE</replaceable></option></term>
<listitem><para>Initialize session from <replaceable>FILE</replaceable></para></listitem>
</varlistentry>
<varlistentry>
<term><option>--screen=<replaceable>SCREEN</replaceable></option></term>
<listitem><para>X screen to use</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-d</option>, <option>--display=<replaceable>DISPLAY</replaceable></option></term>
<listitem><para>X Display to use</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sync</option></term>
<listitem><para>Make X calls synchronous</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>Print version and exit</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--help</option></term>
<listitem><para>Display help and exit</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--mode=<replaceable>MODE</replaceable></option></term>
<listitem><para>Use a specific mode, e.g. "gdm" for login screen</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--list-modes</option></term>
<listitem><para>List possible modes and exit</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Files</title>
<para>
<filename>/usr/share/gnome-session/sessions/gnome.session</filename>,
<filename>/usr/share/applications/gnome-shell.desktop</filename>.</para>
</refsect1>
<refsect1>
<title>Bugs</title>
<para>The bug tracker can be reached by visiting the
website <ulink url="https://bugzilla.gnome.org/buglist.cgi?product=gnome-shell">https://bugzilla.gnome.org/buglist.cgi?product=gnome-shell</ulink>.
Before sending a bug report, please verify that you have
the latest version of gnome-shell. Many bugs (major and
minor) are fixed at each release, and if yours is out of
date, the problem may already have been solved.</para>
</refsect1>
<refsect1>
<title>Additional Information</title>
<para>For further information, visit the website
<ulink url="http://live.gnome.org/GnomeShell">http://live.gnome.org/GnomeShell</ulink>.</para>
</refsect1>
</refentry>

View File

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

796
po/ar.po

File diff suppressed because it is too large Load Diff

858
po/as.po

File diff suppressed because it is too large Load Diff

481
po/cs.po

File diff suppressed because it is too large Load Diff

194
po/de.po
View File

@ -19,9 +19,9 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-10-14 16:48+0000\n"
"PO-Revision-Date: 2012-10-10 23:10+0100\n"
"Last-Translator: Tobias Endrigkeit <tobiasendrigkeit@googlemail.com>\n"
"POT-Creation-Date: 2012-11-06 04:39+0000\n"
"PO-Revision-Date: 2012-11-06 20:04+0100\n"
"Last-Translator: Wolfgang Stoeggl <c72578@yahoo.de>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
@ -148,56 +148,68 @@ msgstr ""
"Aufzählung entnommen."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
msgid "Always show the 'Log out' menuitem in the user menu."
msgstr "Den Menüeintrag »Abmelden« immer im Benutzermenü anzeigen."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
msgid ""
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
"user, single-session situations."
msgstr ""
"Dieser Schlüssel überschreibt das automatische Verbergen des Menüeintrags "
"»Abmelden« in Einzelbenutzer, Einzelsitzungssituationen."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
msgid "Show the week date in the calendar"
msgstr "Wochentag im Kalender anzeigen"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
msgid "If true, display the ISO week date in the calendar."
msgstr ""
"Wenn dieser Wert gesetzt ist, wird der ISO-Wochentag im Kalender angezeigt."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid "Keybinding to open the application menu"
msgstr "Tastenkombination zum Öffnen des Anwendungsmenüs"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid "Keybinding to open the application menu."
msgstr "Tastenkombination zum Öffnen des Anwendungsmenüs."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Keybinding to toggle the visibility of the message tray"
msgstr ""
"Tastenkombination zum Umschalten der Sichtbarkeit des Benachrichtigungsfeldes"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
msgid "Keybinding to toggle the visibility of the message tray."
msgstr ""
"Tastenkombination zum Umschalten der Sichtbarkeit des "
"Benachrichtigungsfeldes."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
msgid "Keybinding to toggle the screen recorder"
msgstr "Tastenkombination zum Umschalten des Bildschirmaufzeichners"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "Keybinding to start/stop the builtin screen recorder."
msgstr ""
"Tastenkombination zum Starten/Entfernen des eingebauten "
"Bildschirmaufzeichners."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "Which keyboard to use"
msgstr "Zu verwendende Tastatur"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "The type of keyboard to use."
msgstr "Der Typ der zu verwendenden Tastatur"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "Framerate used for recording screencasts."
msgstr "Bildwiederholungsrate zur Aufnahme von Screencasts"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second."
@ -206,11 +218,11 @@ msgstr ""
"der GNOME-Shell aufgezeichnet werden soll, in Einzelbildern pro Sekunde."
# hmm Enkodieren oder Kodieren?
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "The gstreamer pipeline used to encode the screencast"
msgstr "Die GStreamer-Weiterleitung zur Enkodierung des Screencasts"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
#, no-c-format
msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@ -238,11 +250,11 @@ msgstr ""
"aufzeichnet. %T wird als Platzhalter für die vermutete optimale Thread-"
"Anzahl auf dem System verwendet."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
msgid "File extension used for storing the screencast"
msgstr "Die Dateiendung zum Speichern des Screencast"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
msgid ""
"The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to "
@ -303,8 +315,8 @@ msgstr "Anmeldefenster"
msgid "Power"
msgstr "Ausschalten"
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:660 ../js/ui/userMenu.js:664
#: ../js/ui/userMenu.js:775
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:664 ../js/ui/userMenu.js:668
#: ../js/ui/userMenu.js:779
msgid "Suspend"
msgstr "Bereitschaft"
@ -312,8 +324,8 @@ msgstr "Bereitschaft"
msgid "Restart"
msgstr "Neu starten"
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:662 ../js/ui/userMenu.js:664
#: ../js/ui/userMenu.js:774
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:666 ../js/ui/userMenu.js:668
#: ../js/ui/userMenu.js:778
msgid "Power Off"
msgstr "Ausschalten"
@ -698,35 +710,35 @@ msgstr "Stumm"
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/components/telepathyClient.js:948
#: ../js/ui/components/telepathyClient.js:952
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Gesendet am <b>%A</b> um <b>%X</b> "
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/components/telepathyClient.js:954
#: ../js/ui/components/telepathyClient.js:958
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Gesendet am <b>%A</b>, <b>%d. %B</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/components/telepathyClient.js:959
#: ../js/ui/components/telepathyClient.js:963
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Gesendet am <b>%A</b>, <b>%d. %B</b> %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/components/telepathyClient.js:988
#: ../js/ui/components/telepathyClient.js:992
#, c-format
msgid "%s is now known as %s"
msgstr "%s heißt jetzt %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1088
#: ../js/ui/components/telepathyClient.js:1092
#, c-format
msgid "Invitation to %s"
msgstr "Einladung zum Betreten von %s"
@ -734,42 +746,42 @@ msgstr "Einladung zum Betreten von %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/components/telepathyClient.js:1096
#: ../js/ui/components/telepathyClient.js:1100
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s lädt Sie ein, %s beizutreten"
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1177
#: ../js/ui/components/telepathyClient.js:1240
#: ../js/ui/components/telepathyClient.js:1102
#: ../js/ui/components/telepathyClient.js:1181
#: ../js/ui/components/telepathyClient.js:1244
msgid "Decline"
msgstr "Ablehnen"
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1241
#: ../js/ui/components/telepathyClient.js:1103
#: ../js/ui/components/telepathyClient.js:1182
#: ../js/ui/components/telepathyClient.js:1245
msgid "Accept"
msgstr "Annehmen"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1129
#: ../js/ui/components/telepathyClient.js:1133
#, c-format
msgid "Video call from %s"
msgstr "Video-Anruf von %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1132
#: ../js/ui/components/telepathyClient.js:1136
#, c-format
msgid "Call from %s"
msgstr "Anruf von %s"
#: ../js/ui/components/telepathyClient.js:1137
#: ../js/ui/components/telepathyClient.js:1141
#: ../js/ui/status/bluetooth.js:346
msgid "Reject"
msgstr "Abweisen"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1143
msgid "Answer"
msgstr "Antworten"
@ -778,113 +790,113 @@ msgstr "Antworten"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/components/telepathyClient.js:1171
#: ../js/ui/components/telepathyClient.js:1175
#, c-format
msgid "%s is sending you %s"
msgstr "%s sendet Ihnen %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1206
#: ../js/ui/components/telepathyClient.js:1210
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s bittet um das Recht, Ihre Online-Verfügbarkeit sehen zu dürfen"
#: ../js/ui/components/telepathyClient.js:1298
#: ../js/ui/components/telepathyClient.js:1302
msgid "Network error"
msgstr "Netzwerkfehler"
#: ../js/ui/components/telepathyClient.js:1300
#: ../js/ui/components/telepathyClient.js:1304
msgid "Authentication failed"
msgstr "Legitimierung fehlgeschlagen"
#: ../js/ui/components/telepathyClient.js:1302
#: ../js/ui/components/telepathyClient.js:1306
msgid "Encryption error"
msgstr "Verschlüsselungsfehler"
#: ../js/ui/components/telepathyClient.js:1304
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate not provided"
msgstr "Zertifikat wurde nicht bereitgestellt"
#: ../js/ui/components/telepathyClient.js:1306
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate untrusted"
msgstr "Zertifikat nicht vertrauenswürdig"
#: ../js/ui/components/telepathyClient.js:1308
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate expired"
msgstr "Zertifikat abgelaufen"
#: ../js/ui/components/telepathyClient.js:1310
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate not activated"
msgstr "Zertifikat nicht aktiviert"
#: ../js/ui/components/telepathyClient.js:1312
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate hostname mismatch"
msgstr "Rechnername des Zertifikats stimmt nicht überein"
#: ../js/ui/components/telepathyClient.js:1314
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate fingerprint mismatch"
msgstr "Fingerabdruck des Zertifikats stimmt nicht überein"
#: ../js/ui/components/telepathyClient.js:1316
#: ../js/ui/components/telepathyClient.js:1320
msgid "Certificate self-signed"
msgstr "Selbstsigniertes Zertifikat"
#: ../js/ui/components/telepathyClient.js:1318
#: ../js/ui/components/telepathyClient.js:1322
msgid "Status is set to offline"
msgstr "Der Status ist auf »Abgemeldet« gesetzt"
#: ../js/ui/components/telepathyClient.js:1320
#: ../js/ui/components/telepathyClient.js:1324
msgid "Encryption is not available"
msgstr "Verschlüsselung ist nicht verfügbar"
#: ../js/ui/components/telepathyClient.js:1322
#: ../js/ui/components/telepathyClient.js:1326
msgid "Certificate is invalid"
msgstr "Zertifikat ist ungültig"
#: ../js/ui/components/telepathyClient.js:1324
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection has been refused"
msgstr "Verbindungsaufbau wurde verweigert"
#: ../js/ui/components/telepathyClient.js:1326
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection can't be established"
msgstr "Verbindung kann nicht hergestellt werden"
#: ../js/ui/components/telepathyClient.js:1328
#: ../js/ui/components/telepathyClient.js:1332
msgid "Connection has been lost"
msgstr "Verbindung wurde unterbrochen"
#: ../js/ui/components/telepathyClient.js:1330
#: ../js/ui/components/telepathyClient.js:1334
msgid "This account is already connected to the server"
msgstr "Dieses Konto ist bereits mit dem Server verbunden"
#: ../js/ui/components/telepathyClient.js:1332
#: ../js/ui/components/telepathyClient.js:1336
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Die Verbindung wurde durch eine neue Verbindung mit der gleichen Ressource "
"ersetzt"
#: ../js/ui/components/telepathyClient.js:1334
#: ../js/ui/components/telepathyClient.js:1338
msgid "The account already exists on the server"
msgstr "Dieses Konto ist bereits auf dem Server vorhanden"
#: ../js/ui/components/telepathyClient.js:1336
#: ../js/ui/components/telepathyClient.js:1340
msgid "Server is currently too busy to handle the connection"
msgstr ""
"Der Server ist derzeit überlastet und kann die Verbindung nicht annehmen"
#: ../js/ui/components/telepathyClient.js:1338
#: ../js/ui/components/telepathyClient.js:1342
msgid "Certificate has been revoked"
msgstr "Zertifikat wurde zurückgezogen"
#: ../js/ui/components/telepathyClient.js:1340
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Das Zertifikat verwendet einen unsicheren Chiffrier-Algorithmus oder ist "
"kryptografisch schwach"
#: ../js/ui/components/telepathyClient.js:1342
#: ../js/ui/components/telepathyClient.js:1346
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -893,26 +905,26 @@ msgstr ""
"überschreiten die durch die kryptografische Bibliothek gegebenen "
"Beschränkungen"
#: ../js/ui/components/telepathyClient.js:1344
#: ../js/ui/components/telepathyClient.js:1348
msgid "Internal error"
msgstr "Interner Fehler"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1354
#: ../js/ui/components/telepathyClient.js:1358
#, c-format
msgid "Connection to %s failed"
msgstr "Verbindung zu %s ist fehlgeschlagen"
#: ../js/ui/components/telepathyClient.js:1363
#: ../js/ui/components/telepathyClient.js:1367
msgid "Reconnect"
msgstr "Erneut verbinden"
#: ../js/ui/components/telepathyClient.js:1364
#: ../js/ui/components/telepathyClient.js:1368
msgid "Edit account"
msgstr "Konto bearbeiten"
#: ../js/ui/components/telepathyClient.js:1409
#: ../js/ui/components/telepathyClient.js:1413
msgid "Unknown reason"
msgstr "Unbekannter Grund"
@ -1095,23 +1107,23 @@ msgstr "Quelle zeigen"
msgid "Web Page"
msgstr "Webseite"
#: ../js/ui/messageTray.js:1081
#: ../js/ui/messageTray.js:1084
msgid "Open"
msgstr "Öffnen"
#: ../js/ui/messageTray.js:1088
#: ../js/ui/messageTray.js:1091
msgid "Remove"
msgstr "Entfernen"
#: ../js/ui/messageTray.js:1540
#: ../js/ui/messageTray.js:1543
msgid "Message Tray"
msgstr "Benachrichtigungsfeld"
#: ../js/ui/messageTray.js:2547
#: ../js/ui/messageTray.js:2549
msgid "System Information"
msgstr "Systeminformationen"
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:373
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374
msgctxt "program"
msgid "Unknown"
msgstr "Unbekannt"
@ -1171,18 +1183,18 @@ msgstr "Bitte geben Sie einen Befehl ein:"
# %B - ausgeschriebener Name des Monats, abhängig von der gesetzten Umgebung
#. Translators: This is a time format for a date in
#. long format
#: ../js/ui/screenShield.js:79
#: ../js/ui/screenShield.js:80
msgid "%A, %B %d"
msgstr "%A, %d. %B"
#: ../js/ui/screenShield.js:143
#: ../js/ui/screenShield.js:144
#, c-format
msgid "%d new message"
msgid_plural "%d new messages"
msgstr[0] "%d neue Nachricht"
msgstr[1] "%d neue Nachrichten"
#: ../js/ui/screenShield.js:145
#: ../js/ui/screenShield.js:146
#, c-format
msgid "%d new notification"
msgid_plural "%d new notifications"
@ -1638,59 +1650,59 @@ msgstr "Mikrofon"
msgid "Log in as another user"
msgstr "Als anderer Benutzer anmelden"
#: ../js/ui/userMenu.js:180
#: ../js/ui/userMenu.js:181
msgid "Available"
msgstr "Verfügbar"
#: ../js/ui/userMenu.js:183
#: ../js/ui/userMenu.js:184
msgid "Busy"
msgstr "Beschäftigt"
#: ../js/ui/userMenu.js:186
#: ../js/ui/userMenu.js:187
msgid "Invisible"
msgstr "Unsichtbar"
#: ../js/ui/userMenu.js:189
#: ../js/ui/userMenu.js:190
msgid "Away"
msgstr "Abwesend"
#: ../js/ui/userMenu.js:192
#: ../js/ui/userMenu.js:193
msgid "Idle"
msgstr "Untätig"
#: ../js/ui/userMenu.js:195
#: ../js/ui/userMenu.js:196
msgid "Unavailable"
msgstr "Nicht verfügbar"
#: ../js/ui/userMenu.js:740
#: ../js/ui/userMenu.js:744
msgid "Notifications"
msgstr "Benachrichtigungen"
#: ../js/ui/userMenu.js:748
#: ../js/ui/userMenu.js:752
msgid "System Settings"
msgstr "Systemeinstellungen"
#: ../js/ui/userMenu.js:756
#: ../js/ui/userMenu.js:760
msgid "Switch User"
msgstr "Benutzer wechseln"
#: ../js/ui/userMenu.js:761
#: ../js/ui/userMenu.js:765
msgid "Log Out"
msgstr "Abmelden"
#: ../js/ui/userMenu.js:766
#: ../js/ui/userMenu.js:770
msgid "Lock"
msgstr "Sperren"
#: ../js/ui/userMenu.js:781
#: ../js/ui/userMenu.js:785
msgid "Install Updates & Restart"
msgstr "Aktualisierungen installieren und neustarten"
#: ../js/ui/userMenu.js:799
#: ../js/ui/userMenu.js:803
msgid "Your chat status will be set to busy"
msgstr "Ihr Anwesenheitsstatus wird auf »Beschäftigt« gesetzt"
#: ../js/ui/userMenu.js:800
#: ../js/ui/userMenu.js:804
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1777,7 +1789,7 @@ msgstr ""
msgid "List possible modes"
msgstr "Die möglichen Modi auflisten"
#: ../src/shell-app.c:621
#: ../src/shell-app.c:622
#, c-format
msgid "Failed to launch '%s'"
msgstr "»%s« konnte nicht gestartet werden"

805
po/es.po

File diff suppressed because it is too large Load Diff

299
po/et.po
View File

@ -13,8 +13,8 @@ msgstr ""
"Project-Id-Version: gnome-shell MASTER\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-09-22 22:24+0000\n"
"PO-Revision-Date: 2012-09-23 08:48+0300\n"
"POT-Creation-Date: 2012-12-09 13:03+0000\n"
"PO-Revision-Date: 2012-12-18 17:13+0300\n"
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
"Language-Team: Estonian <>\n"
"Language: et\n"
@ -37,6 +37,15 @@ msgstr "Arvuti"
msgid "Show the message tray"
msgstr "Teateala näitamine"
msgid "Focus the active notification"
msgstr "Aktiivse märguande fokuseerimine"
msgid "Show all applications"
msgstr "Kõigi rakenduste kuvamine"
msgid "Open the application menu"
msgstr "Rakenduste menüü avamine"
msgid "GNOME Shell"
msgstr "GNOME Shell"
@ -116,6 +125,38 @@ msgstr ""
"Kasutatakse kasutaja poolt viimati vahetult määratud kiirsuhtluse oleku "
"salvestamiseks. See väärtus pärineb GsmPresenceStatus nummerdusest."
msgid "Always show the 'Log out' menuitem in the user menu."
msgstr "Kasutajamenüüs näidatakse alati 'Logi välja' menüükirjet."
msgid ""
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
"user, single-session situations."
msgstr ""
"See võti keelab automaatse 'Logi välja' menüükirje peitmise, kui arvutis on "
"üks kasutaja ning avatud üks seanss."
msgid "Show full name in the user menu"
msgstr "Kasutajamenüüs näidatakse kasutaja tervet nime"
msgid "Whether the users full name is shown in the user menu or not."
msgstr "Kas kasutajamenüüs näidatakse kasutaja kogu nime või mitte."
msgid ""
"Whether to remember password for mounting encrypted or remote filesystems"
msgstr ""
"Kas pidada meeles krüpteeritud või kaugfailisüsteemide haakimise paroole."
msgid ""
"The shell will request a password when an encrypted device or a remote "
"filesystem is mounted. If the password can be saved for future use a "
"'Remember Password' checkbox will be present. This key sets the default "
"state of the checkbox."
msgstr ""
"Shell küsib parooli, kui haagitakse krüpteeritud seade või kaugfailisüsteem. "
"Kui parooli on võimalik salvestada järgmise kasutuse jaoks, näidatakse "
"\"Jäta parool meelde\" märkeruutu. See võti määrab märkeruudu vaikimisi "
"oleku."
msgid "Show the week date in the calendar"
msgstr "Kalendris näidatakse kuupäeva nädalavormingus"
@ -128,12 +169,25 @@ msgstr "Rakenduste menüü avamise kiirklahv"
msgid "Keybinding to open the application menu."
msgstr "Kiirklahv rakenduste menüü avamiseks."
msgid "Keybinding to open the \"Show Applications\" view"
msgstr "\"Rakenduste vaate\" avamise kiirklahv"
msgid ""
"Keybinding to open the \"Show Applications\" view of the Activities Overview."
msgstr "\"Rakenduste vaate\" avamise kiirklahv tegevuste ülevaates."
msgid "Keybinding to toggle the visibility of the message tray"
msgstr "Teateala nähtavuse muutmise kiirklahv"
msgid "Keybinding to toggle the visibility of the message tray."
msgstr "Kiirklahv teateala nähtavuse muutmiseks."
msgid "Keybinding to focus the active notification"
msgstr "Aktiivse teate fokuseerimise kiirklahv"
msgid "Keybinding to focus the active notification."
msgstr "Aktiivse teate fokuseerimise kiirklahv."
msgid "Keybinding to toggle the screen recorder"
msgstr "Erkaanilindistaja lülitamise kiirklahv"
@ -195,6 +249,46 @@ msgstr ""
"konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend "
"määrata."
msgid "The application icon mode."
msgstr "Rakenduste ikooni režiim."
msgid ""
"Configures how the windows are shown in the switcher. Valid possibilities "
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
"only' (shows only the application icon) or 'both'."
msgstr ""
"Seadistab, kuidas aknaid akendevahetajas kuvatakse. Sobivad väärtused on "
"'thumbnail-only' (näidatakse ainult pisipilti), 'app-icon-only' (näidatakse "
"ainult rakenduse ikooni) või 'both' (näidatakse mõlemaid)."
msgid "Attach modal dialog to the parent window"
msgstr "Modaaldialoog kuulub vanemakna juurde"
msgid ""
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
msgstr ""
"See võti on ülimuslik võtme org.gnome.mutter suhtes, kui kasutatakse GNOME "
"Shelli."
msgid "Arrangement of buttons on the titlebar"
msgstr "Nuppude järjekord tiitliribal"
msgid ""
"This key overrides the key in org.gnome.desktop.wm.preferences when running "
"GNOME Shell."
msgstr ""
"See võti on ülimuslik võtme org.gnome.desktop.wm.preferences suhtes, kui "
"kasutatakse GNOME Shelli."
msgid "Enable edge tiling when dropping windows on screen edges"
msgstr "Akende lohistamisel ekraani serva lubatakse serva paigutamine"
msgid "Workspaces are managed dynamically"
msgstr "Tööalasid hallatakse dünaamiliselt"
msgid "Workspaces only on primary monitor"
msgstr "Tööalad peamisel monitoril"
#, c-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "%s jaoks eelistuste dialoogi laadimisel esines viga:"
@ -225,9 +319,22 @@ msgctxt "button"
msgid "Sign In"
msgstr "Logi sisse"
msgid "Next"
msgstr "Järgmine"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
msgid "Username: "
msgstr "Kasutajanimi: "
msgid "Login Window"
msgstr "Sisselogimisaken"
#. Translators: accessible name of the power menu in the login screen
msgid "Power"
msgstr "Vool"
msgid "Suspend"
msgstr "Uinak"
@ -437,12 +544,6 @@ msgstr "Parool: "
msgid "Key: "
msgstr "Võti: "
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
msgid "Username: "
msgstr "Kasutajanimi: "
msgid "Identity: "
msgstr "Identiteet: "
@ -521,11 +622,8 @@ msgstr "Helista"
msgid "File Transfer"
msgstr "Failiülekanne"
msgid "Subscription request"
msgstr "Tellimuse päring"
msgid "Connection error"
msgstr "Ühenduse viga"
msgid "Chat"
msgstr "Vestlus"
msgid "Unmute"
msgstr "Heli peale"
@ -533,24 +631,25 @@ msgstr "Heli peale"
msgid "Mute"
msgstr "Heli maha"
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Saadetud: <b>%A</b>, <b>%X</b>"
msgid "<b>Yesterday</b>, <b>%H:%M</b>"
msgstr "<b>Eile</b> <b>%H:%M</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Saadeti <b>%A</b>, <b>%B %d</b>"
msgid "<b>%A</b>, <b>%H:%M</b>"
msgstr "<b>%A</b>, <b>%H:%M</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Saadeti <b>%A</b>, <b>%B %d</b>, %Y"
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>"
msgstr "<b>%d. %B</b>, <b>%H:%M</b>"
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"
#, no-c-format
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "
msgstr "<b>%d. %B %Y</b>, <b>%H:%M</b>"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
@ -587,9 +686,6 @@ msgstr "%s tahab alustada videokõnet"
msgid "Call from %s"
msgstr "%s helistab"
msgid "Reject"
msgstr "Lükka tagasi"
#. translators: this is a button label (verb), not a noun
msgid "Answer"
msgstr "Vasta"
@ -690,18 +786,18 @@ msgstr "Sisemine viga"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#, c-format
msgid "Connection to %s failed"
msgstr "Ühendus %s nurjus"
msgid "Unable to connect to %s"
msgstr "Pole võimalik ühenduda võrguga %s"
msgid "Reconnect"
msgstr "Ühendu uuesti"
msgid "Edit account"
msgstr "Konto muutmine"
msgid "View account"
msgstr "Konto kuvamine"
msgid "Unknown reason"
msgstr "Põhjus teadmata"
msgid "Windows"
msgstr "Aknad"
msgid "Show Applications"
msgstr "Rakenduste kuvamine"
@ -824,8 +920,6 @@ msgstr "Näita vigu"
msgid "Enabled"
msgstr "Lubatud"
#. translators:
#. * The device has been disabled
msgid "Disabled"
msgstr "Keelatud"
@ -850,6 +944,9 @@ msgstr "Ava"
msgid "Remove"
msgstr "Eemalda"
msgid "No Messages"
msgstr "Teateid pole"
msgid "Message Tray"
msgstr "Teateala"
@ -897,8 +994,11 @@ msgstr "Ülemine riba"
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
msgid "Please enter a command:"
msgstr "Palun sisesta käsk:"
msgid "Enter a Command"
msgstr "Palun sisesta käsk"
msgid "Close"
msgstr "Sulge"
#. Translators: This is a time format for a date in
#. long format
@ -917,6 +1017,9 @@ msgid_plural "%d new notifications"
msgstr[0] "%d uus märguanne"
msgstr[1] "%d uut märguannet"
msgid "Lock"
msgstr "Lukusta"
msgid "Searching..."
msgstr "Otsimine..."
@ -1011,16 +1114,6 @@ msgstr "ühendumine..."
msgid "Send Files..."
msgstr "Failide saatmine..."
msgid "Browse Files..."
msgstr "Failide sirvimine..."
msgid "Error browsing device"
msgstr "Viga seadme sirvimisel"
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr "Küsitud seadet pole võimalik sirvida, viga on '%s'"
msgid "Keyboard Settings"
msgstr "Klaviatuurisätted"
@ -1044,6 +1137,10 @@ msgstr "Luba alati"
msgid "Grant this time only"
msgstr "Luba ainult seekord"
msgid "Reject"
msgstr "Lükka tagasi"
#. Translators: argument is the device short name
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Paardumise kinnitus seadmele %s"
@ -1056,6 +1153,7 @@ msgstr "Seade '%s' tahab selle arvutiga paarduda"
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "Palun kontrolli, kas PIN-kood '%06d' kattub seadme parooliga."
#. Translators: this is the verb, not the noun
msgid "Matches"
msgstr "Kattub"
@ -1145,17 +1243,8 @@ msgstr "Automaatne juhtmeta ühendus"
msgid "Enable networking"
msgstr "Luba võrguühendused"
msgid "Wired"
msgstr "Juhtmega"
msgid "Wireless"
msgstr "Juhtmeta"
msgid "Mobile broadband"
msgstr "Mobiiliühendus"
msgid "VPN Connections"
msgstr "VPN-ühendused"
msgid "Wi-Fi"
msgstr "Wi-Fi"
msgid "Network Settings"
msgstr "Võrgusätted"
@ -1259,6 +1348,9 @@ msgstr "Mikrofon"
msgid "Log in as another user"
msgstr "Logi sisse teise kasutajana"
msgid "Unlock Window"
msgstr "Võta aken lukust lahti"
msgid "Available"
msgstr "Saadaval"
@ -1274,27 +1366,21 @@ msgstr "Eemal"
msgid "Idle"
msgstr "Jõude"
msgid "Unavailable"
msgstr "Pole saadaval"
msgid "Switch User"
msgstr "Vaheta kasutajat"
msgid "Switch Session"
msgstr "Vaheta seanssi"
msgid "Offline"
msgstr "Ühendamata"
msgid "Notifications"
msgstr "Märguanded"
msgid "System Settings"
msgstr "Süsteemi sätted"
msgid "Settings"
msgstr "Sätted"
msgid "Switch User"
msgstr "Vaheta kasutajat"
msgid "Log Out"
msgstr "Logi välja"
msgid "Lock"
msgstr "Lukusta"
msgid "Install Updates & Restart"
msgstr "Paigalda uuendused ja taaskäivita"
@ -1308,9 +1394,6 @@ msgstr ""
"Märguanded on nüüd keelatud, sealhulgas vestlusteated. Sinu netiolekut "
"muudeti, et teised teaksid, et sa ei pruugi nende teateid näha."
msgid "Windows"
msgstr "Aknad"
msgid "Applications"
msgstr "Rakendused"
@ -1339,25 +1422,6 @@ msgstr "'%s' on valmis"
msgid "Evolution Calendar"
msgstr "Evolutioni kalender"
#. translators:
#. * The number of sound outputs on a particular device
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
msgstr[0] "%u väljund"
msgstr[1] "%u väljundit"
#. translators:
#. * The number of sound inputs on a particular device
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "%u sisend"
msgstr[1] "%u sisendit"
msgid "System Sounds"
msgstr "Süsteemi helid"
msgid "Print version"
msgstr "Printimise versioon"
@ -1389,6 +1453,46 @@ msgstr "Vaikimisi"
msgid "Authentication dialog was dismissed by the user"
msgstr "Kasutaja katkestas autentimisdialoogi"
#~ msgid "Subscription request"
#~ msgstr "Tellimuse päring"
#~ msgid "Connection error"
#~ msgstr "Ühenduse viga"
#~ msgid "<b>%H:%M</b> on Yesterday"
#~ msgstr "Eile <b>%H:%M</b>"
#~ msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
#~ msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b> %Y"
#~ msgid "Connection to %s failed"
#~ msgstr "Ühendus %s nurjus"
#~ msgid "Reconnect"
#~ msgstr "Ühendu uuesti"
#~ msgid "Wired"
#~ msgstr "Juhtmega"
#~ msgid "Wireless"
#~ msgstr "Juhtmeta"
#~ msgid "Mobile broadband"
#~ msgstr "Mobiiliühendus"
#~ msgid "%u Output"
#~ msgid_plural "%u Outputs"
#~ msgstr[0] "%u väljund"
#~ msgstr[1] "%u väljundit"
#~ msgid "%u Input"
#~ msgid_plural "%u Inputs"
#~ msgstr[0] "%u sisend"
#~ msgstr[1] "%u sisendit"
#~ msgid "System Sounds"
#~ msgstr "Süsteemi helid"
#~ msgid "disabled OpenSearch providers"
#~ msgstr "keelatud OpenSearch pakkujad"
@ -1404,9 +1508,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
#~ msgid "If true, display date in the clock, in addition to time."
#~ msgstr "Kui määratud, siis kuvatakse kellaaja kõrval ka kuupäeva."
#~ msgid "Offline"
#~ msgstr "Ühendamata"
#~ msgid "CONTACTS"
#~ msgstr "KONTAKTID"

View File

@ -708,7 +708,7 @@ msgstr "ارسال در <b>%A</b>, <b>%B %d</b>, %Y"
#: ../js/ui/components/telepathyClient.js:988
#, c-format
msgid "%s is now known as %s"
msgstr "%s با عنوان %s شناخته می‌شود"
msgstr "%s با عنوان %s شناخته می‌شود"
#. translators: argument is a room name like
#. * room@jabber.org for example.
@ -723,7 +723,7 @@ msgstr "دعوتنامه به %s"
#: ../js/ui/components/telepathyClient.js:1096
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s از شما دعوت می‌کند که به %s بپیوندید"
msgstr "%s از شما دعوت می‌کند که به %s بپیوندید"
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1177
@ -767,13 +767,13 @@ msgstr "پاسخگویی"
#: ../js/ui/components/telepathyClient.js:1171
#, c-format
msgid "%s is sending you %s"
msgstr "%s در حال ارسال %s به شما است"
msgstr "%s در حال ارسال %s به شما است"
#. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1206
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s اجازه دسترسی برای دیدن زمان‌هایی که شما برخط هستید را دارد"
msgstr "%s اجازه دسترسی برای دیدن زمان‌هایی که شما برخط هستید را دارد"
#: ../js/ui/components/telepathyClient.js:1298
msgid "Network error"
@ -938,8 +938,8 @@ msgstr ""
#, c-format
msgid "%s will be logged out automatically in %d second."
msgid_plural "%s will be logged out automatically in %d seconds."
msgstr[0] "%s به طور خودکار در مدت %Id ثانیه از سیستم خارج خواهد شد."
msgstr[1] "%s به طور خودکار در مدت %Id ثانیه از سیستم خارج خواهد شد."
msgstr[0] "%s به طور خودکار در مدت %Id ثانیه از سیستم خارج خواهد شد."
msgstr[1] "%s به طور خودکار در مدت %Id ثانیه از سیستم خارج خواهد شد."
#: ../js/ui/endSessionDialog.js:70
#, c-format
@ -1698,7 +1698,7 @@ msgstr ""
#: ../js/ui/wanda.js:121
#, c-format
msgid "%s the Oracle says"
msgstr "%s پیشگو می‌گوید"
msgstr "%s پیشگو می‌گوید"
#: ../js/ui/wanda.js:162
msgid "Your favorite Easter Egg"
@ -1852,16 +1852,16 @@ msgstr "محاوره تایید هویت از طرف کاربر رد شد"
#~ msgstr "شبکه"
#~ msgid "%s is online."
#~ msgstr "%s بر خط است."
#~ msgstr "%s بر خط است."
#~ msgid "%s is offline."
#~ msgstr "%s برون خط است."
#~ msgstr "%s برون خط است."
#~ msgid "%s is away."
#~ msgstr "%s غایب است."
#~ msgstr "%s غایب است."
#~ msgid "%s is busy."
#~ msgstr "%s مشغول است."
#~ msgstr "%s مشغول است."
#~ msgid "Hidden"
#~ msgstr "نامرئی"

551
po/gl.po

File diff suppressed because it is too large Load Diff

843
po/he.po

File diff suppressed because it is too large Load Diff

412
po/kn.po
View File

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

111
po/ml.po
View File

@ -11,15 +11,15 @@ msgstr ""
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
"cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-09-20 16:11+0000\n"
"PO-Revision-Date: 2012-09-20 22:56+0000\n"
"Last-Translator: Ani Peter <apeter@redhat.com>\n"
"PO-Revision-Date: 2012-11-26 15:02+0530\n"
"Last-Translator: Ani Peter <peter.ani@gmail.com>\n"
"Language-Team: Malayalam <discuss@lists.smc.org.in>\n"
"Language: ml\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.0\n"
"X-Generator: Lokalize 1.5\n"
"X-DamnedLies-Scope: partial\n"
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
@ -61,7 +61,8 @@ msgstr "ഗ്നോം ഷെല്‍ എക്സ്റ്റെന്‍ഷ
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1
msgid "Enable internal tools useful for developers and testers from Alt-F2"
msgstr ""
"Alt-F2-ല്‍ ഡവലപ്പര്‍മാര്‍ക്കും ടെസ്റ്റേര്‍സിനും പ്രയോജനകരമായ ആന്തരിക പ്രയോഗങ്ങള്‍ പ്രവര്‍ത്തന "
"Alt-F2-ല്‍ ഡവലപ്പര്‍മാര്‍ക്കും ടെസ്റ്റേര്‍സിനും പ്രയോജനകരമായ ആന്തരിക "
"പ്രയോഗങ്ങള്‍ പ്രവര്‍ത്തന "
"സജ്ജമാക്കുന്നു"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:2
@ -69,7 +70,8 @@ msgid ""
"Allows access to internal debugging and monitoring tools using the Alt-F2 "
"dialog."
msgstr ""
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും പ്രവേശനം "
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും "
"പ്രവേശനം "
"അനുവദിയ്ക്കുക."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:3
@ -83,14 +85,19 @@ msgid ""
"list. You can also manipulate this list with the EnableExtension and "
"DisableExtension DBus methods on org.gnome.Shell."
msgstr ""
"ഗ്നോം ഷെല്‍ എക്സ്റ്റെന്‍ഷനുകള്‍ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട എക്സ്റ്റെന്‍ഷനുകള്‍ ഈ കീ പട്ടിക "
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്‍ഷനും ഈ പട്ടികയിലുണ്ടാവണം. org.gnome.Shell-ല്‍ "
"നിങ്ങള്‍ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ പട്ടിക "
"ഗ്നോം ഷെല്‍ എക്സ്റ്റെന്‍ഷനുകള്‍ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട "
"എക്സ്റ്റെന്‍ഷനുകള്‍ ഈ കീ പട്ടിക "
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്‍ഷനും ഈ പട്ടികയിലുണ്ടാവണം. "
"org.gnome.Shell-ല്‍ "
"നിങ്ങള്‍ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ "
"പട്ടിക "
"കൈകാര്യം ചെയ്യുവാനും സാധിയ്ക്കുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5
msgid "Whether to collect stats about applications usage"
msgstr "പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള്‍ ശേഖരിയ്ക്കണമോ എന്നു്"
msgstr ""
"പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള്‍ ശേഖരിയ്ക്കണമോ "
"എന്നു്"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:6
msgid ""
@ -99,9 +106,12 @@ msgid ""
"want to disable this for privacy reasons. Please note that doing so won't "
"remove already saved data."
msgstr ""
"ഏറ്റവും കൂടുതല്‍ തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള്‍ ലഭ്യമാക്കുന്നതിനായി ഷെല്‍ സാധാരണയായി സജീവമായ "
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്‍സ്). ഈ ഡേറ്റാ സ്വകാര്യമായി "
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല്‍ ഇതു് പ്രവര്‍ത്തന രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
"ഏറ്റവും കൂടുതല്‍ തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള്‍ ലഭ്യമാക്കുന്നതിനായി ഷെല്‍ "
"സാധാരണയായി സജീവമായ "
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്‍സ്). ഈ ഡേറ്റാ "
"സ്വകാര്യമായി "
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല്‍ ഇതു് പ്രവര്‍ത്തന "
"രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
"നിങ്ങള്‍ സൂക്ഷിച്ച ഡേറ്റയെ ബാധിയ്ക്കുന്നതല്ല."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7
@ -112,7 +122,8 @@ msgstr "ഇഷ്ടമുള്ള പ്രയോഗങ്ങള്‍ക്
msgid ""
"The applications corresponding to these identifiers will be displayed in the "
"favorites area."
msgstr "ഈ ഐഡന്റിഫയറുകള്‍ക്കുള്ള പ്രയോഗങ്ങള്‍ ഉചിതമായ സ്ഥലങ്ങളില്‍ കാണിയ്ക്കുന്നു."
msgstr ""
"ഈ ഐഡന്റിഫയറുകള്‍ക്കുള്ള പ്രയോഗങ്ങള്‍ ഉചിതമായ സ്ഥലങ്ങളില്‍ കാണിയ്ക്കുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9
msgid "History for command (Alt-F2) dialog"
@ -127,7 +138,8 @@ msgid ""
"Internally used to store the last IM presence explicitly set by the user. "
"The value here is from the TpConnectionPresenceType enumeration."
msgstr ""
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
"TpConnectionPresenceType തരത്തിലുള്ളതാകുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
@ -135,7 +147,8 @@ msgid ""
"Internally used to store the last session presence status for the user. The "
"value here is from the GsmPresenceStatus enumeration."
msgstr ""
"ഉപയോക്താവിനുള്ള അവസാന സെഷന്‍ അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
"ഉപയോക്താവിനുള്ള അവസാന സെഷന്‍ അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
"GsmPresenceStatus തരത്തിലുള്ളതാകുന്നു."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
@ -168,7 +181,9 @@ msgstr "സ്ക്രീന്‍ റിക്കോര്‍ഡര്‍ ട
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
msgid "Keybinding to start/stop the builtin screen recorder."
msgstr "ബിള്‍ട്ടിന്‍ സ്ക്രീന്‍ റിക്കോര്‍ഡര്‍ തുടങ്ങുവാന്‍/നിര്‍ത്തുന്നതിനുള്ള കീക്കൂട്ടം."
msgstr ""
"ബിള്‍ട്ടിന്‍ സ്ക്രീന്‍ റിക്കോര്‍ഡര്‍ തുടങ്ങുവാന്‍/നിര്‍ത്തുന്നതിനുള്ള "
"കീക്കൂട്ടം."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
msgid "Which keyboard to use"
@ -187,7 +202,8 @@ msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second."
msgstr ""
"ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്‍കാസ്റ്റ് റിക്കോര്‍ഡര്‍ റീക്കോര്‍ഡ് ചെയ്തിട്ടുള്ള സ്ക്രീന്‍കാസ്റ്റിന്റെ "
"ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്‍കാസ്റ്റ് റിക്കോര്‍ഡര്‍ റീക്കോര്‍ഡ് ചെയ്തിട്ടുള്ള "
"സ്ക്രീന്‍കാസ്റ്റിന്റെ "
"ഫ്രെയിംറേറ്റ്, ഒരു സെക്കന്‍ഡില്‍ ഒരു ഫ്രെയിം."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
@ -219,9 +235,12 @@ msgid ""
"threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is "
"used as a placeholder for a guess at the optimal thread count on the system."
msgstr ""
"റിക്കോര്‍ഡിങുകള്‍ എന്‍കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന്‍ ഉപയോഗിയ്ക്കുന്നു. "
"gst-launch-നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള്‍ കാലിയാകുന്നു."
"ഇതു് നിലവില്‍ 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 "
"റിക്കോര്‍ഡിങുകള്‍ എന്‍കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന്‍ "
"ഉപയോഗിയ്ക്കുന്നു. "
"gst-launch-നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള്‍ "
"കാലിയാകുന്നു."
"ഇതു് നിലവില്‍ 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 "
"deadline=1000000 "
"threads=%T ! queue ! webmmux' ആകുന്നുസ WEBM VP8 കോഡ് ഉപയോഗിച്ചു് റിക്കോര്‍ഡ് "
"ചെയ്യുന്നു."
@ -235,8 +254,10 @@ msgid ""
"current date, and use this extension. It should be changed when recording to "
"a different container format."
msgstr ""
"റിക്കോര്‍ഡ് ചെയ്ത സ്ക്രീന്‍കാസ്റ്റുകള്‍ക്കുള്ള ഫയല്‍നാമം നിലവിലുള്ള തീയതി, എക്സ്റ്റെന്‍ഷന്‍ എന്നിവ "
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്‍ഡ് ചെയ്യുമ്പോള്‍ ഇതു് മാറ്റണം."
"റിക്കോര്‍ഡ് ചെയ്ത സ്ക്രീന്‍കാസ്റ്റുകള്‍ക്കുള്ള ഫയല്‍നാമം നിലവിലുള്ള തീയതി, "
"എക്സ്റ്റെന്‍ഷന്‍ എന്നിവ "
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്‍ഡ് ചെയ്യുമ്പോള്‍ ഇതു് "
"മാറ്റണം."
#: ../js/extensionPrefs/main.js:124
#, c-format
@ -249,7 +270,9 @@ msgstr "എക്സ്റ്റെന്‍ഷന്‍"
#: ../js/extensionPrefs/main.js:188
msgid "Select an extension to configure using the combobox above."
msgstr "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു എക്സ്റ്റെന്‍ഷന്‍ തെര‍ഞ്ഞെടുക്കുക."
msgstr ""
"മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു "
"എക്സ്റ്റെന്‍ഷന്‍ തെര‍ഞ്ഞെടുക്കുക."
#: ../js/gdm/loginDialog.js:526
msgid "Session..."
@ -578,7 +601,8 @@ msgid ""
"Passwords or encryption keys are required to access the wireless network "
"'%s'."
msgstr ""
"വയര്‍ലെസ് നെറ്റ്‌വര്‍ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള്‍ അല്ലെങ്കില്‍ എന്‍ക്രിപ്ഷന്‍ കീകള്‍ "
"വയര്‍ലെസ് നെറ്റ്‌വര്‍ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള്‍ "
"അല്ലെങ്കില്‍ എന്‍ക്രിപ്ഷന്‍ കീകള്‍ "
"ആവശ്യമുണ്ടു്."
#: ../js/ui/components/networkAgent.js:314
@ -764,7 +788,8 @@ msgstr "%s നിങ്ങള്‍ക്കു് %s അയച്ചിരി
#: ../js/ui/components/telepathyClient.js:1206
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "നിങ്ങള്‍ ഓണ്‍ലൈന്‍ ആകുമ്പോള്‍ കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
msgstr ""
"നിങ്ങള്‍ ഓണ്‍ലൈന്‍ ആകുമ്പോള്‍ കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
#: ../js/ui/components/telepathyClient.js:1298
msgid "Network error"
@ -835,8 +860,11 @@ msgid "This account is already connected to the server"
msgstr "ഈ അക്കൌണ്ട് നിലവില്‍ സര്‍വറിലേക്കു് കണക്ട് ചെയ്തിരിയ്ക്കുന്നു"
#: ../js/ui/components/telepathyClient.js:1332
msgid "Connection has been replaced by a new connection using the same resource"
msgstr "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന്‍ ഉപയോഗിച്ചു് ഈ കണക്ഷന്‍ മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന്‍ ഉപയോഗിച്ചു് ഈ കണക്ഷന്‍ "
"മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
#: ../js/ui/components/telepathyClient.js:1334
msgid "The account already exists on the server"
@ -851,15 +879,19 @@ msgid "Certificate has been revoked"
msgstr "സമ്മതപത്രം വീണ്ടും ആവശ്യപ്പെട്ടിരിയ്ക്കുന്നു"
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര്‍ ആല്‍ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു അല്ലെങ്കില്‍ ഉചിതമല്ല"
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര്‍ ആല്‍ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു "
"അല്ലെങ്കില്‍ ഉചിതമല്ല"
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
msgstr ""
"സര്‍വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില്‍ സര്‍വര്‍ സമ്മതപത്ര ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
"സര്‍വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില്‍ സര്‍വര്‍ സമ്മതപത്ര "
"ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
"പരിധിയില്‍ കൂടുന്നു"
#: ../js/ui/components/telepathyClient.js:1344
@ -918,7 +950,8 @@ msgstr "പുറത്ത് കടക്കുക"
#: ../js/ui/endSessionDialog.js:63
msgid "Click Log Out to quit these applications and log out of the system."
msgstr ""
"ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് ചെയ്തു് സിസ്റ്റത്തില്‍ നിന്നും "
"ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് "
"ചെയ്തു് സിസ്റ്റത്തില്‍ നിന്നും "
"പുറത്തു് കടക്കുക."
#: ../js/ui/endSessionDialog.js:65
@ -952,7 +985,8 @@ msgstr "നിര്‍ത്തുക"
#: ../js/ui/endSessionDialog.js:82
msgid "Click Power Off to quit these applications and power off the system."
msgstr ""
"ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര്‍ ഓഫ് ചെയ്യുക ക്ലിക്ക് ചെയ്തു സിസ്റ്റിന്റെ പവര്‍ "
"ഈ പ്രയോഗങ്ങളില്‍ നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര്‍ ഓഫ് ചെയ്യുക ക്ലിക്ക് "
"ചെയ്തു സിസ്റ്റിന്റെ പവര്‍ "
"ഓഫ് ചെയ്യുക."
#: ../js/ui/endSessionDialog.js:84
@ -983,7 +1017,8 @@ msgstr "പുനരാരംഭിക്കുക"
#: ../js/ui/endSessionDialog.js:99
msgid "Click Restart to quit these applications and restart the system."
msgstr "ഈ പ്രയോഗങ്ങള്‍ നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന്‍ പുനരാരംഭിക്കൂ അമര്‍ത്തുക"
msgstr ""
"ഈ പ്രയോഗങ്ങള്‍ നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന്‍ പുനരാരംഭിക്കൂ അമര്‍ത്തുക"
#: ../js/ui/endSessionDialog.js:101
#, c-format
@ -1003,7 +1038,9 @@ msgstr "ഇന്‍സ്റ്റോള്‍"
#: ../js/ui/extensionDownloader.js:204
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "extensions.gnome.org ഇല്‍ നിന്നും '%s' ഡൗണ്‍ലോട് ചെയ്ത് ഇന്‍സ്റ്റോള്‍ ചെയ്യേണമോ?"
msgstr ""
"extensions.gnome.org ഇല്‍ നിന്നും '%s' ഡൗണ്‍ലോട് ചെയ്ത് ഇന്‍സ്റ്റോള്‍ "
"ചെയ്യേണമോ?"
#: ../js/ui/keyboard.js:327
msgid "tray"
@ -1660,8 +1697,10 @@ msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
msgstr ""
"ചാറ്റ് സന്ദേശങ്ങള്‍ എന്ന പോലെ അറിയിപ്പുകള്‍ പ്രവര്‍ത്തന രഹിതമാക്കുന്നു. മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള്‍ "
"നിങ്ങള്‍ക്കു് കാണുവാന്‍ സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്‍ലൈന്‍ അവസ്ഥയില്‍ വ്യക്തമാക്കുന്നു."
"ചാറ്റ് സന്ദേശങ്ങള്‍ എന്ന പോലെ അറിയിപ്പുകള്‍ പ്രവര്‍ത്തന രഹിതമാക്കുന്നു. "
"മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള്‍ "
"നിങ്ങള്‍ക്കു് കാണുവാന്‍ സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്‍ലൈന്‍ അവസ്ഥയില്‍ "
"വ്യക്തമാക്കുന്നു."
#: ../js/ui/viewSelector.js:85
msgid "Windows"

690
po/nb.po

File diff suppressed because it is too large Load Diff

1989
po/nl.po

File diff suppressed because it is too large Load Diff

730
po/pa.po

File diff suppressed because it is too large Load Diff

244
po/pl.po
View File

@ -11,8 +11,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-09-25 15:12+0200\n"
"PO-Revision-Date: 2012-09-25 15:13+0200\n"
"POT-Creation-Date: 2012-10-31 19:12+0100\n"
"PO-Revision-Date: 2012-10-31 19:13+0100\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <gnomepl@aviary.pl>\n"
"Language: pl\n"
@ -142,62 +142,74 @@ msgstr ""
"użytkownika. Wartość pochodzi ze spisu GsmPresenceStatus."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
msgid "Always show the 'Log out' menuitem in the user menu."
msgstr "Wyświetlanie elementu menu \"Wyloguj się\" w menu użytkownika."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
msgid ""
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
"user, single-session situations."
msgstr ""
"Ten klucz zastępuje automatyczne ukrywanie elementu menu \"Wyloguj się\" w "
"sytuacji, gdy istnieje tylko jeden użytkownik i jedna sesja."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
msgid "Show the week date in the calendar"
msgstr "Wyświetlanie dnia tygodnia w kalendarzu"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
msgid "If true, display the ISO week date in the calendar."
msgstr ""
"Jeśli jest ustawione na \"true\", to wyświetla w kalendarzu dzień tygodnia w "
"formacie ISO."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid "Keybinding to open the application menu"
msgstr "Skrót do otwarcia menu programu"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid "Keybinding to open the application menu."
msgstr "Skrót do otwarcia menu programu."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Keybinding to toggle the visibility of the message tray"
msgstr "Skrót do przełączenia widoczności obszaru powiadamiania"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
msgid "Keybinding to toggle the visibility of the message tray."
msgstr "Skrót do przełączenia widoczności obszaru powiadamiania."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
msgid "Keybinding to toggle the screen recorder"
msgstr "Skrót do przełączenia nagrywania ekranu"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "Keybinding to start/stop the builtin screen recorder."
msgstr "Skrót do uruchomienia/zatrzymania wbudowanego nagrywania ekranu."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "Which keyboard to use"
msgstr "Której klawiatury używać"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "The type of keyboard to use."
msgstr "Typ używanej klawiatury."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "Framerate used for recording screencasts."
msgstr "Liczba klatek na sekundę do nagrywania ekranu."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second."
msgstr "Liczba klatek na sekundę wynikowego nagrania ekranu."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "The gstreamer pipeline used to encode the screencast"
msgstr "Potok biblioteki GStreamer używany do zakodowania nagrania ekranu"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
#, no-c-format
msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@ -222,11 +234,11 @@ msgstr ""
"i nagrywa do formatu WebM używając kodeka VP8. %T jest zamieniane na "
"odgadniętą optymalną liczbę wątków dla komputera."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
msgid "File extension used for storing the screencast"
msgstr "Rozszerzenie pliku używane do przechowywania nagrań ekranu"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
msgid ""
"The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to "
@ -252,11 +264,11 @@ msgstr ""
"Proszę wybrać rozszerzenie do skonfigurowania używając powyższego pola "
"wyboru."
#: ../js/gdm/loginDialog.js:528
#: ../js/gdm/loginDialog.js:529
msgid "Session..."
msgstr "Sesja..."
#: ../js/gdm/loginDialog.js:676
#: ../js/gdm/loginDialog.js:677
msgctxt "title"
msgid "Sign In"
msgstr "Proszę się zalogować"
@ -264,23 +276,23 @@ msgstr "Proszę się zalogować"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: ../js/gdm/loginDialog.js:743
#: ../js/gdm/loginDialog.js:736
msgid "Not listed?"
msgstr "Inny użytkownik?"
#: ../js/gdm/loginDialog.js:896 ../js/ui/components/networkAgent.js:137
#: ../js/gdm/loginDialog.js:889 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:166
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:167
msgid "Cancel"
msgstr "Anuluj"
#: ../js/gdm/loginDialog.js:901
#: ../js/gdm/loginDialog.js:894
msgctxt "button"
msgid "Sign In"
msgstr "Zaloguj"
#: ../js/gdm/loginDialog.js:1240
#: ../js/gdm/loginDialog.js:1215
msgid "Login Window"
msgstr "Okno logowania"
@ -289,8 +301,8 @@ msgstr "Okno logowania"
msgid "Power"
msgstr "Zasilanie"
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:663 ../js/ui/userMenu.js:667
#: ../js/ui/userMenu.js:778
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:664 ../js/ui/userMenu.js:668
#: ../js/ui/userMenu.js:779
msgid "Suspend"
msgstr "Uśpij"
@ -298,8 +310,8 @@ msgstr "Uśpij"
msgid "Restart"
msgstr "Uruchom ponownie"
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:665 ../js/ui/userMenu.js:667
#: ../js/ui/userMenu.js:777
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:666 ../js/ui/userMenu.js:668
#: ../js/ui/userMenu.js:778
msgid "Power Off"
msgstr "Wyłącz komputer"
@ -350,7 +362,7 @@ msgstr "Ustawienia"
msgid "New Window"
msgstr "Nowe okno"
#: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:271
#: ../js/ui/appDisplay.js:678 ../js/ui/dash.js:290
msgid "Remove from Favorites"
msgstr "Usuń z ulubionych"
@ -514,16 +526,16 @@ msgstr "Ten tydzień"
msgid "Next week"
msgstr "Następny tydzień"
#: ../js/ui/components/autorunManager.js:278
#: ../js/ui/components/autorunManager.js:297
msgid "Removable Devices"
msgstr "Urządzenia wymienne"
#: ../js/ui/components/autorunManager.js:575
#: ../js/ui/components/autorunManager.js:594
#, c-format
msgid "Open with %s"
msgstr "Otwórz za pomocą %s"
#: ../js/ui/components/autorunManager.js:601
#: ../js/ui/components/autorunManager.js:620
msgid "Eject"
msgstr "Wysuń"
@ -680,35 +692,35 @@ msgstr "Wycisz"
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/components/telepathyClient.js:948
#: ../js/ui/components/telepathyClient.js:950
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Wysłano w dniu <b>%e %b</b> o godzinie <b>%H:%M</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/components/telepathyClient.js:954
#: ../js/ui/components/telepathyClient.js:956
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Wysłano w dniu <b>%d %B</b>, <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/components/telepathyClient.js:959
#: ../js/ui/components/telepathyClient.js:961
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Wysłano w dniu <b>%d %B</b> %Y, <b>%A</b>"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/components/telepathyClient.js:988
#: ../js/ui/components/telepathyClient.js:990
#, c-format
msgid "%s is now known as %s"
msgstr "Użytkownik %s jest teraz znany jako %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1088
#: ../js/ui/components/telepathyClient.js:1090
#, c-format
msgid "Invitation to %s"
msgstr "Zaproszenie do pokoju %s"
@ -716,42 +728,42 @@ msgstr "Zaproszenie do pokoju %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/components/telepathyClient.js:1096
#: ../js/ui/components/telepathyClient.js:1098
#, c-format
msgid "%s is inviting you to join %s"
msgstr "Użytkownik %s zaprasza do dołączenia do pokoju %s"
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1177
#: ../js/ui/components/telepathyClient.js:1240
#: ../js/ui/components/telepathyClient.js:1100
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
msgid "Decline"
msgstr "Odmów"
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1241
#: ../js/ui/components/telepathyClient.js:1101
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
msgid "Accept"
msgstr "Zaakceptuj"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1129
#: ../js/ui/components/telepathyClient.js:1131
#, c-format
msgid "Video call from %s"
msgstr "Wideorozmowa z użytkownikiem %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1132
#: ../js/ui/components/telepathyClient.js:1134
#, c-format
msgid "Call from %s"
msgstr "Rozmowa z użytkownikiem %s"
#: ../js/ui/components/telepathyClient.js:1137
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/status/bluetooth.js:346
msgid "Reject"
msgstr "Odrzuć"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1141
msgid "Answer"
msgstr "Odbierz"
@ -760,111 +772,111 @@ msgstr "Odbierz"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/components/telepathyClient.js:1171
#: ../js/ui/components/telepathyClient.js:1173
#, c-format
msgid "%s is sending you %s"
msgstr "Użytkownik %s przysyła plik %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1206
#: ../js/ui/components/telepathyClient.js:1208
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "Użytkownik %s prosi o uprawnienie do wyświetlania stanu"
#: ../js/ui/components/telepathyClient.js:1298
#: ../js/ui/components/telepathyClient.js:1300
msgid "Network error"
msgstr "Błąd sieci"
#: ../js/ui/components/telepathyClient.js:1300
#: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed"
msgstr "Uwierzytelnienie się nie powiodło"
#: ../js/ui/components/telepathyClient.js:1302
#: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error"
msgstr "Błąd szyfrowania"
#: ../js/ui/components/telepathyClient.js:1304
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided"
msgstr "Nie podano certyfikatu"
#: ../js/ui/components/telepathyClient.js:1306
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted"
msgstr "Certyfikat jest niezaufany"
#: ../js/ui/components/telepathyClient.js:1308
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired"
msgstr "Certyfikat wygasł"
#: ../js/ui/components/telepathyClient.js:1310
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated"
msgstr "Certyfikat nie został aktywowany"
#: ../js/ui/components/telepathyClient.js:1312
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch"
msgstr "Nazwa komputera certyfikatu się nie zgadza"
#: ../js/ui/components/telepathyClient.js:1314
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch"
msgstr "Odcisk palca certyfikatu się nie zgadza"
#: ../js/ui/components/telepathyClient.js:1316
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed"
msgstr "Certyfikat został samodzielnie podpisany"
#: ../js/ui/components/telepathyClient.js:1318
#: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline"
msgstr "Stan jest ustawiony na offline"
#: ../js/ui/components/telepathyClient.js:1320
#: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available"
msgstr "Szyfrowanie jest niedostępne"
#: ../js/ui/components/telepathyClient.js:1322
#: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid"
msgstr "Certyfikat jest nieprawidłowy"
#: ../js/ui/components/telepathyClient.js:1324
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused"
msgstr "Odrzucono połączenie"
#: ../js/ui/components/telepathyClient.js:1326
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established"
msgstr "Nie można nawiązać połączenia"
#: ../js/ui/components/telepathyClient.js:1328
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost"
msgstr "Utracono połączenie"
#: ../js/ui/components/telepathyClient.js:1330
#: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server"
msgstr "To konto jest już połączone z serwerem"
#: ../js/ui/components/telepathyClient.js:1332
#: ../js/ui/components/telepathyClient.js:1334
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Połączenie zostało zastąpione nowym z wykorzystaniem tego samego zasobu"
#: ../js/ui/components/telepathyClient.js:1334
#: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server"
msgstr "Konto już istnieje na serwerze"
#: ../js/ui/components/telepathyClient.js:1336
#: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection"
msgstr "Serwer jest obecnie zbyt zajęty, aby obsłużyć połączenie"
#: ../js/ui/components/telepathyClient.js:1338
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked"
msgstr "Certyfikat został unieważniony"
#: ../js/ui/components/telepathyClient.js:1340
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Certyfikat używa niezabezpieczonego algorytmu szyfrowania lub jest "
"kryptograficznie słaby"
#: ../js/ui/components/telepathyClient.js:1342
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -872,30 +884,30 @@ msgstr ""
"Długość certyfikatu serwera lub głębokość jego łańcucha przekracza "
"ograniczenia nałożone przez bibliotekę kryptograficzną"
#: ../js/ui/components/telepathyClient.js:1344
#: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error"
msgstr "Błąd wewnętrzny"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1354
#: ../js/ui/components/telepathyClient.js:1356
#, c-format
msgid "Connection to %s failed"
msgstr "Połączenie z kontem %s się nie powiodło"
#: ../js/ui/components/telepathyClient.js:1363
#: ../js/ui/components/telepathyClient.js:1365
msgid "Reconnect"
msgstr "Połącz ponownie"
#: ../js/ui/components/telepathyClient.js:1364
#: ../js/ui/components/telepathyClient.js:1366
msgid "Edit account"
msgstr "Modyfikuj konto"
#: ../js/ui/components/telepathyClient.js:1409
#: ../js/ui/components/telepathyClient.js:1411
msgid "Unknown reason"
msgstr "Nieznana przyczyna"
#: ../js/ui/dash.js:245 ../js/ui/dash.js:273
#: ../js/ui/dash.js:253 ../js/ui/dash.js:292
msgid "Show Applications"
msgstr "Wyświetl programy"
@ -903,14 +915,14 @@ msgstr "Wyświetl programy"
msgid "Date and Time Settings"
msgstr "Ustawienia daty i czasu"
#: ../js/ui/dateMenu.js:109
#: ../js/ui/dateMenu.js:111
msgid "Open Calendar"
msgstr "Otwórz kalendarz"
#. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#.
#: ../js/ui/dateMenu.js:175
#: ../js/ui/dateMenu.js:201
msgid "%A %B %e, %Y"
msgstr "%A, %e %B %Y"
@ -1075,23 +1087,23 @@ msgstr "Wyświetl źródło"
msgid "Web Page"
msgstr "Strona WWW"
#: ../js/ui/messageTray.js:1081
#: ../js/ui/messageTray.js:1084
msgid "Open"
msgstr "Otwórz"
#: ../js/ui/messageTray.js:1088
#: ../js/ui/messageTray.js:1091
msgid "Remove"
msgstr "Usuń"
#: ../js/ui/messageTray.js:2088
#: ../js/ui/messageTray.js:1543
msgid "Message Tray"
msgstr "Obszar powiadamiania"
#: ../js/ui/messageTray.js:2551
#: ../js/ui/messageTray.js:2549
msgid "System Information"
msgstr "Informacje systemowe"
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:373
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374
msgctxt "program"
msgid "Unknown"
msgstr "Nieznany"
@ -1147,7 +1159,7 @@ msgstr "Proszę wprowadzić polecenie:"
#. Translators: This is a time format for a date in
#. long format
#: ../js/ui/screenShield.js:79
#: ../js/ui/screenShield.js:80
msgid "%A, %B %d"
msgstr "%A, %e %B"
@ -1199,7 +1211,7 @@ msgstr "Hasło"
msgid "Remember Password"
msgstr "Zapamiętanie hasła"
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:169
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:170
msgid "Unlock"
msgstr "Odblokuj"
@ -1614,67 +1626,63 @@ msgstr "Głośność"
msgid "Microphone"
msgstr "Mikrofon"
#: ../js/ui/unlockDialog.js:176
#: ../js/ui/unlockDialog.js:177
msgid "Log in as another user"
msgstr "Zaloguj jako inny użytkownik"
#: ../js/ui/userMenu.js:180
#: ../js/ui/userMenu.js:181
msgid "Available"
msgstr "Dostępny"
#: ../js/ui/userMenu.js:183
#: ../js/ui/userMenu.js:184
msgid "Busy"
msgstr "Zajęty"
#: ../js/ui/userMenu.js:186
#: ../js/ui/userMenu.js:187
msgid "Invisible"
msgstr "Niewidoczny"
#: ../js/ui/userMenu.js:189
#: ../js/ui/userMenu.js:190
msgid "Away"
msgstr "Nieobecny"
#: ../js/ui/userMenu.js:192
#: ../js/ui/userMenu.js:193
msgid "Idle"
msgstr "Bezczynny"
#: ../js/ui/userMenu.js:195
#: ../js/ui/userMenu.js:196
msgid "Unavailable"
msgstr "Niedostępny"
#: ../js/ui/userMenu.js:618 ../js/ui/userMenu.js:759
msgid "Switch User"
msgstr "Przełącz użytkownika"
#: ../js/ui/userMenu.js:619
msgid "Switch Session"
msgstr "Przełącz sesję"
#: ../js/ui/userMenu.js:743
#: ../js/ui/userMenu.js:744
msgid "Notifications"
msgstr "Powiadomienia"
#: ../js/ui/userMenu.js:751
#: ../js/ui/userMenu.js:752
msgid "System Settings"
msgstr "Ustawienia systemu"
#: ../js/ui/userMenu.js:764
#: ../js/ui/userMenu.js:760
msgid "Switch User"
msgstr "Przełącz użytkownika"
#: ../js/ui/userMenu.js:765
msgid "Log Out"
msgstr "Wyloguj się"
#: ../js/ui/userMenu.js:769
#: ../js/ui/userMenu.js:770
msgid "Lock"
msgstr "Zablokuj ekran"
#: ../js/ui/userMenu.js:784
#: ../js/ui/userMenu.js:785
msgid "Install Updates & Restart"
msgstr "Zaktualizuj i uruchom ponownie"
#: ../js/ui/userMenu.js:802
#: ../js/ui/userMenu.js:803
msgid "Your chat status will be set to busy"
msgstr "Stan komunikatora zostanie ustawiony na \"zajęty\""
#: ../js/ui/userMenu.js:803
#: ../js/ui/userMenu.js:804
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1696,7 +1704,7 @@ msgstr "Programy"
msgid "Search"
msgstr "Wyszukiwanie"
#: ../js/ui/wanda.js:119
#: ../js/ui/wanda.js:117
#, c-format
msgid ""
"Sorry, no wisdom for you today:\n"
@ -1705,12 +1713,12 @@ msgstr ""
"Nic mądrego na dzisiaj:\n"
"%s"
#: ../js/ui/wanda.js:123
#: ../js/ui/wanda.js:121
#, c-format
msgid "%s the Oracle says"
msgstr "Wyrocznia %s przemawia"
#: ../js/ui/wanda.js:164
#: ../js/ui/wanda.js:162
msgid "Your favorite Easter Egg"
msgstr "Twój ulubiony żart"
@ -1747,23 +1755,23 @@ msgstr[2] "%u wejść"
msgid "System Sounds"
msgstr "Dźwięki systemowe"
#: ../src/main.c:330
#: ../src/main.c:332
msgid "Print version"
msgstr "Wyświetla wersję"
#: ../src/main.c:336
#: ../src/main.c:338
msgid "Mode used by GDM for login screen"
msgstr "Tryb używany przez GDM dla ekranu logowania"
#: ../src/main.c:342
#: ../src/main.c:344
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "Używa podanego trybu, np. \"gdm\" dla ekranu logowania"
#: ../src/main.c:348
#: ../src/main.c:350
msgid "List possible modes"
msgstr "Wyświetla listę możliwych trybów"
#: ../src/shell-app.c:621
#: ../src/shell-app.c:622
#, c-format
msgid "Failed to launch '%s'"
msgstr "Uruchomienie \"%s\" się nie powiodło"

501
po/ru.po

File diff suppressed because it is too large Load Diff

809
po/sk.po

File diff suppressed because it is too large Load Diff

940
po/ta.po

File diff suppressed because it is too large Load Diff

View File

@ -218,12 +218,12 @@ msgstr "يىغقۇچقا قوش"
#: ../js/ui/appFavorites.js:91
#, c-format
msgid "%s has been added to your favorites."
msgstr "%s يىغقۇچىڭىزغا قوشۇلدى."
msgstr "%s يىغقۇچىڭىزغا قوشۇلدى."
#: ../js/ui/appFavorites.js:122
#, c-format
msgid "%s has been removed from your favorites."
msgstr "%s يىغقۇچىڭىزدىن چىقىرىۋېتىلىدۇ."
msgstr "%s يىغقۇچىڭىزدىن چىقىرىۋېتىلىدۇ."
#. Translators: Shown in calendar event list for all day events
#. * Keep it short, best if you can use less then 10 characters
@ -437,7 +437,7 @@ msgstr "يېقىنقى تۈرلەر"
#: ../js/ui/endSessionDialog.js:63
#, c-format
msgid "Log Out %s"
msgstr "%s تىزىمدىن چىقىش"
msgstr "%s تىزىمدىن چىقىش"
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:70
msgid "Log Out"
@ -452,7 +452,7 @@ msgstr ""
#: ../js/ui/endSessionDialog.js:66
#, c-format
msgid "%s will be logged out automatically in %d seconds."
msgstr "%s تىزىمدىن %d سېكۇنتتىن كېيىن ئۆزلۈكىدىن چىقىسىز."
msgstr "%s تىزىمدىن %d سېكۇنتتىن كېيىن ئۆزلۈكىدىن چىقىسىز."
#: ../js/ui/endSessionDialog.js:67
#, c-format
@ -566,7 +566,7 @@ msgstr "سىزىقچە"
#: ../js/ui/panel.js:533
#, c-format
msgid "Quit %s"
msgstr "%s چېكىن"
msgstr "%s چېكىن"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
@ -799,7 +799,7 @@ msgstr "رەت قىل"
#: ../js/ui/status/bluetooth.js:408
#, c-format
msgid "Pairing confirmation for %s"
msgstr "%s نىڭ جەزملىشىنى جۈپلەشتۈرۈۋاتىدۇ"
msgstr "%s نىڭ جەزملىشىنى جۈپلەشتۈرۈۋاتىدۇ"
#: ../js/ui/status/bluetooth.js:414 ../js/ui/status/bluetooth.js:448
#, c-format
@ -823,7 +823,7 @@ msgstr "ماسلاشمىدى"
#: ../js/ui/status/bluetooth.js:441
#, c-format
msgid "Pairing request for %s"
msgstr "%s دىن كەلگەن جۈپلەش ئىلتىماسى"
msgstr "%s دىن كەلگەن جۈپلەش ئىلتىماسى"
#: ../js/ui/status/bluetooth.js:449
msgid "Please enter the PIN mentioned on the device."
@ -1074,22 +1074,22 @@ msgstr "مىكروفون"
#: ../js/ui/telepathyClient.js:335
#, c-format
msgid "%s is online."
msgstr "%s توردا."
msgstr "%s توردا."
#: ../js/ui/telepathyClient.js:340
#, c-format
msgid "%s is offline."
msgstr "%s توردا يوق."
msgstr "%s توردا يوق."
#: ../js/ui/telepathyClient.js:343
#, c-format
msgid "%s is away."
msgstr "%s يوق."
msgstr "%s يوق."
#: ../js/ui/telepathyClient.js:346
#, c-format
msgid "%s is busy."
msgstr "%s ئالدىراش."
msgstr "%s ئالدىراش."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
@ -1114,7 +1114,7 @@ msgstr "ئىزدە"
#: ../js/ui/windowAttentionHandler.js:42
#, c-format
msgid "%s has finished starting"
msgstr "%s باشلاشنى تاماملىدى"
msgstr "%s باشلاشنى تاماملىدى"
#: ../js/ui/windowAttentionHandler.js:44
#, c-format

View File

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

View File

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

View File

@ -8,6 +8,8 @@ noinst_LTLIBRARIES =
noinst_PROGRAMS =
service_in_files =
SUBDIRS = gvc
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --warn-all --warn-error --add-include-path=$(srcdir)
@ -79,7 +81,6 @@ CLEANFILES += gnome-shell $(bin_SCRIPTS)
include Makefile-st.am
include Makefile-tray.am
include Makefile-gvc.am
include Makefile-calendar-server.am
include Makefile-hotplug-sniffer.am
@ -119,7 +120,6 @@ shell_public_headers_h = \
shell-network-agent.h \
shell-perf-log.h \
shell-screenshot.h \
shell-screen-grabber.h \
shell-slicer.h \
shell-stack.h \
shell-tp-client.h \
@ -167,7 +167,6 @@ libgnome_shell_la_SOURCES = \
shell-polkit-authentication-agent.h \
shell-polkit-authentication-agent.c \
shell-screenshot.c \
shell-screen-grabber.c \
shell-secure-text-buffer.c \
shell-secure-text-buffer.h \
shell-slicer.c \
@ -232,8 +231,6 @@ test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
test_recorder_SOURCES = \
$(shell_recorder_sources) $(shell_recorder_private_sources) \
shell-screen-grabber.c \
shell-screen-grabber.h \
test-recorder.c
endif BUILD_RECORDER
@ -288,7 +285,7 @@ libgnome_shell_la_LIBADD = \
$(BLUETOOTH_LIBS) \
libst-1.0.la \
libtray.la \
libgvc.la \
gvc/libgvc.la \
$(NULL)
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)

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