Compare commits

..

221 Commits

Author SHA1 Message Date
35d21c0bca Bump version to 3.37.2
Update NEWS.
2020-06-03 01:29:26 +02:00
b487846c0a notificationDaemon: Try harder to find a matching app
Unlike the desktop-entry hint, the app name is not optional. That
doesn't mean that we'll be able to match it to a .desktop file,
but we can at least try if we fail to match on PID or desktop-entry.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1291
2020-06-02 23:17:24 +00:00
7bbce1d5ad workspace: Position clones using width and height instead of scale
Since we now have a layout manager for the WindowClone that allows
allocating it a size that isn't the absolute size of the window, we can
now give the WindowClone an artificial size and it will get scaled
accordingly.

So make use of that and stop positioning WindowClones using fixed
position and scale and use a fixed position and fixed size instead. This
will make it easier to use a ClutterLayoutManager to allocate the
WindowClones, because layout managers should only set the allocation of
their children, not the scale.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1294
2020-06-02 23:03:06 +00:00
bf40d96a83 workspace: Use boundingBox to get absolute width and height of window
Since we're going to override the fixed width and height of the
ClutterActor the WindowClone is subclassing, remove those confusing
getter methods for width and height and switch to the public boundingBox
for getting that information.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1294
2020-06-02 23:03:06 +00:00
2d650e51a5 workspace: Use boundingBox instead of getOriginalPosition()
The getOriginalPosition() API of WindowClone can easily be replaced by
using the existing boundingBox property, which reflects the windows
bounding box in absolute coordinates. This property is also used
everywhere else in the Workspace object, so we can use it here, too.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1294
2020-06-02 23:03:06 +00:00
85d2837466 workspace: Allow allocating smaller sizes for window clones
Change the preferred size functions of the layout manager of window
clones to allow allocating smaller sizes, too. Also scale down the
allocation sizes of the ClutterClones our allocate implementation so
the ClutterClones will scale their texture accordingly.

This will enable us to position the window clones using their allocation
size instead of their scale, which is necessary when introducing a new
ClutterLayoutManager that positions the window clones.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1294
2020-06-02 23:03:06 +00:00
25985868e8 Revert "workspace: Animate window clones using translation properties"
We're going to add a ClutterLayoutManager responsible for allocating the
WindowClones. Since layout managers should only set the allocation of
actors, not the translation or scale, we need to position the
WindowClones using their x, y, width and height properties.

The first step for this is to revert this commit, which switched from
setting fixed positions on WindowClones to using the translation
properties.

This reverts commit 8929c89d1f.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1294
2020-06-02 23:03:06 +00:00
393c6c6805 lookingGlass: Add actor tree inspector
Being able to visualize the actor tree is a handy feature
to have, specially when debugging the hierarchy.

Add a new "Actors" tab to the Looking Glass with the actor
tree inspector. The tree is cleared on unmap to not get
heavy on the number of actors.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1292
2020-06-02 12:44:21 -03:00
775d6ec431 Updated Slovenian translation 2020-06-01 22:25:53 +02:00
988f996407 workspace: Also hide attached dialogs in WindowClone from picking
As explained in the comment in _init() of WindowClone, we hide the
actual clone from picking so it doesn't interfere with XDND.

This description applies to the clones of the attached dialogs just as
well though, so hide the clones of attached dialogs from picking, too.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1293
2020-06-01 14:01:39 +00:00
315c8820ca padOsd: Apply specific CSS to Button/Leader SVG classes
Applying a fill operation on the Leader line path seems to close
it, resulting in filled polygon. Bug or not this is not the intended
result here, we can do less ambiguously by not specifying the fill
CSS property to the Leader class.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2570

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
8a89de04a2 padOsd: Keep label coordinates in image coordinates
Apply the necessary transforms to map those coordinates to actor
positions in the allocate phase. This all fits since it's the place
where we do know the size the actor will have.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
63abfc163d padOsd: Cache label coordinates/arrangements
This is actually static for a given PadDiagram, as it always represents
a single device.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2570

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
f58cb34065 padOsd: Only allocate child labels within allocate vfunc
Make both start/stop edition and label updates queue a relayout, and
only deal with child allocations in the allocate method.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
ece1329145 padOsd: Drop needless call
If we got this far, we are dealing with an already known label.
There's no need for this check.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
989118981b padOsd: Use map to store misc action label data
We'll be adding more stuff here, so it's a bit inconvenient to keep
it an array.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
c511c469fe padOsd: Move all coord/existence checks to _addLabel()
Drops some repetitive code. Also rely completely on the label/leader
elements being found in order to find buttons/rings/strips.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
dac05c7e53 padOsd: Make label coordinates API "private"
This is only called internally, and only needed there.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
c90e7ce258 padOsd: Move button/ring/strip label creation to PadDiagram
It's the natural container of those. We can create all those labels
internally, and only expose the updateLabels() method to update them
wholesome.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
963f96292d padOsd: Fix double styling
We set the StLabel style property, there's no need to re-apply the
large/bold text style via markup. Makes the StLabel text size consistent
across editable state changes.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
989ee6593b padOsd: Disable ellipsizing in title label
We make the label text large and let it ellipsize. It ends up doing
so instead of allowing the label to expand. This title is important
and we don't want it to be ellipsized, so ensure that won't happen.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2845

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
2a8eea1ff5 padOsd: Fix .allocate() call
This was not updated to the API change in commit 9a8ced9f5b.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1290
2020-05-29 18:06:48 +00:00
55c287280b screenshot: Properly clean up if PickColor() is cancelled
We currently only remove the screenshot operation from the shooter
map if the color pick operation completed successfully, but not if
it was cancelled. As a result, we now reject any further requests
from the same sender because we assume that there is an ongoing
operation.

Fix this by moving the cleanup to a finally clause that runs for
both code paths.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1288
2020-05-29 00:52:33 +02:00
1fdd4ff313 screenshot: Return an error when operation is blocked
Right now _createScreenshot() returns a tuple that indicates failure
when a sender requests a screenshot operation before a previously
started operation finished.

However that doesn't work for the PickColor() method, as it uses a
different return type than the other methods.

Address this by returning an error instead, which works in any case;
arguably trying to start multiple operations in parallel is an error
by the caller more than it is a failed operation anyway.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1288
2020-05-29 00:52:33 +02:00
3522338b3d extensions-tool: Escape '\' and '"' in json string
If user-input string contains '\' and/or '"', extensions-tool
generates invalid json.
This fixes that by escaping '\' and '"'.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1279
2020-05-28 11:23:19 +00:00
61e3349dc7 Update Korean translation
(cherry picked from commit 4099c446da)
2020-05-27 23:50:42 +00:00
dc27db0897 iconGrid: Remove fillParent support
This was only used by the frequent view to display as many children
as fit the available space. Now that the view is gone, there's no
need to keep the support ...

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1286
2020-05-28 00:31:49 +02:00
f09fbb19cf iconGrid: Merge PaginatedIconGrid and IconGrid
Now that the only user of the IconGrid is AppDisplay, and
it only uses the paginated icon grid, there's no point in
having the two classes split anymore.

In addition to that, future commits will introduce a layout
manager that will extend current icon grid features, and
merging PaginatedIconGrid and IconGrid in the same class will
vastly simplify this transition.

Merge PaginatedIconGrid into IconGrid, and adapt AppDisplay
to this change.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1267
2020-05-27 19:23:56 -03:00
846fa77b37 appDisplay: Merge AppDisplay in AllView
Now that AllView is the only actor that AppDisplay creates,
we can actually merge them together.

Merge AllView in AppDisplay, remove what used to be AppDisplay,
and rename AllView to AppDisplay.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/880
2020-05-27 21:06:36 +00:00
b57bcf823f appDisplay: Simplify AppDisplay
Inherit St.Widget and remove the custom layout manager. Instead,
override vfunc_allocate(). Also remove the view stack.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/880
2020-05-27 21:06:36 +00:00
548e19a7cd appDisplay: Remove Frequent view
The Frequent apps grid has a few problems:

 * On a fresh install there would be no history of app usage so the
   applications shown in the grid have no relevance it takes time
   to be useful instead of being useful from the start;

 * The grid has far too many items in it to be relevant; 24 apps is
   well beyond the average use case as most people don't frequently
   use that many, so it gets populated with several apps that are
   single use (hello xterm);

 * The position of items in the grid are always changing based on an
   unknown frequency metric (and not by user-intended input) which
   makes it a poor way to quickly launch apps as one would have to
   constantly learn the positions of the items in the grid;

 * Having two app grids is a bit superfluous and needlessly complicates
   the app launching navigation: you have to spend time checking the
   frequent grid and if it's not there you have to switch over to another
   grid and find the app you need in there it's not straightforward.

Remove the Frequent tab and simplify the related code.

Related: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1425

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/880
2020-05-27 21:06:36 +00:00
4ae04d5aa8 power: Fix icon when discharging at 100%
The special-case for a fill level of 100 introduced in commit 5fd52e99d3
should only apply when charging, for the discharging state there's a
proper battery-level-100-symbolic icon.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2286
2020-05-26 21:27:42 +02:00
5d5ca80d17 st/box-layout: Fix gtk-doc comments
Commit 9dc421875 added a subtle syntax error: # is used to cross
reference symbols, but must not be used in the definition of the
symbols itself.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1281
2020-05-25 18:43:30 +00:00
d81237b9d6 st/texture-cache: Cancel pending requests on icon-theme changes
As outlined in commit 36b8dcbe07, we can end up with wrong icons
if the icon theme changes right after a GTK theme change to/from
HighContrast triggered a theme reload.

That's because when we reload icons for the new icon theme, there
are already pending requests due to the icon-style change; those
requests are simply re-used for the new icons, with the existing
icon infos from the old theme.

The above commit applied a simple work-around by changing the
icon theme before the GTK theme, but that only works for the
HighContrast switch in our own UI.

It turns out that Settings also uses the "wrong" order, so the
issue still reproduces with the Universal Access panel.

So instead of relying on everything changing the settings in the
order we expect, cancel all ongoing requests on icon-theme changes.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1277
2020-05-25 12:55:28 +02:00
71b3b03b2f theme: Make world clock times tabular
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2825
2020-05-24 18:27:12 +00:00
8c909e37e9 panel: fix size of battery percentage label
Adjust the label of the (optional) battery percentage in the top
bar to have the same size as all other text in the top bar.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2652
2020-05-24 16:37:57 +00:00
6508fa4349 Update German translation
(cherry picked from commit bc3c1e5a68)
2020-05-24 16:06:35 +00:00
ce8fb83c36 Update Romanian translation 2020-05-24 10:43:48 +00:00
58ec607818 Update Slovak translation
(cherry picked from commit b148a8bc60)
2020-05-24 07:28:07 +00:00
f06223df48 screenshot: Add preview to color picker
With color picking implemented in the compositor, we
can do better than letting the user pick a pixel with
the crosshair cursor, and present them with a preview
of the color that will be selected.

Do this by replacing the cursor with a custom icon and
apply a recoloring effect, where we replace a given color
with the color of the currently hovered pixel (similar
to a green screen).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/451
2020-05-22 16:10:43 +02:00
9a8ced9f5b search: Remove usage of allocation flags
Allocation flags have been removed from Clutter, and commit
400d045a6a accidentally added their
arguments again which causes a warning, so remove those arguments.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1276
2020-05-22 10:18:24 +00:00
67c45e5648 Update Ukrainian translation 2020-05-22 05:44:50 +00:00
b88ed3f251 Use pid_t for meta_window_get_pid()
The return value of meta_window_get_pid() changed again and it now
returns pid_t, which usually just resolves to int on most platforms. We
should still use pid_t now though, so do that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1188
2020-05-21 23:11:21 +00:00
669b0f193a StClipboard: add st_clipboard_get_mimetypes
Since the `MetaSelection` of the global `StClipboard` is private (and
should be), there is no reasonable way for extensions or external code
to query the supported mime-types.

Add `st_clipboard_get_mimetypes()` so this can be queried without
poking around in private code.

closes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2819
2020-05-21 22:24:59 +00:00
9cad7ae975 extensions-app: Indicate extension errors
Currently there is no indication that an extension had an error except
for the sensitivity of the switch (which may have a different cause).

This is useful information to users, so add a small error indicator
alongside the updates icon and show the actual error in the details.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2337
2020-05-21 21:45:04 +00:00
48e6a58250 extensionSystem: Don't log error name
logExtensionError() currently saves the error message by calling
toString() on the passed error. That's convenient as it allows to
pass a string instead of a "proper" error, but the result isn't
great for the common Error case: Its toString() method prefixes
the message with the error name, which usually is just "Error:".

The plain message is more suitable for displaying it to users,
so use that for Error objects.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2337
2020-05-21 21:45:04 +00:00
d2583aa47b extensions-app: Reset switch handle when it becomes insensitive
Currently the switches handle position reflects the requested
extension state (as in: the user (de)activated the switch),
while the actual extension state is reflected by the underlying
state.

That doesn't work well when the switch is insensitive though (for
example on error), because the desaturation neuters the color
that reflects the state.

Address this by resetting the switch handle to the state when
making it insensitive.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1263
2020-05-21 21:29:31 +00:00
0ab34fe21f st: Remove BoxLayout child meta
They were deprecated last cycle in favor of ClutterActor's own
expand/align properties, time to retire them for good.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1274
2020-05-21 21:17:16 +00:00
0f947d4ff9 st/theme: Remove entry from files_by_stylesheet after emitting signal
Since e06109c23c we keep old theme nodes
valid during the emission of the "custom-stylesheets-changed" signal.

It turns out that we might still look up the file of a stylesheet using
the files_by_stylesheet hashtable during the emission of that signal,
causing a crash because the assertion in _st_theme_resolve_url() fails.

So fix that and remove the stylesheet entry from the files_by_stylesheet
hashtable after emitting the "custom-stylesheets-changed" signal. And to
be consistent, also remove the entry from the stylesheets_by_file
hashtable after emitting the signal.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2757
2020-05-21 20:59:35 +00:00
9dc421875b StBoxLayout: Fix up some documentation
`StBoxLayout` has a couple properties (`vertical` and `pack-start`)
improperly referenced as signals, and is somewhat unclear these
properties are wrappers around the underlying `ClutterBoxLayout`
properties.

Fix these up and add references to the underlying properties, rather
than redescribing them.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2816
2020-05-21 22:37:23 +02:00
9c3c9a155e st: Remove deprecated Bin properties
Those were deprecated last cycle in favor of ClutterActor's own
expand/align properties, and don't have any effect anymore.

Time to remove them for good.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1273
2020-05-21 14:36:59 +02:00
faaed642a7 js: Listen to notify::allocation instead of allocation-changed
ClutterActors "allocation-changed" signal was removed since it's no
longer needed now that there are no ClutterAllocationFlags anymore.

See https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1245
2020-05-20 15:12:36 +02:00
9b99b67fea Remove ClutterAllocationFlags
Those flags were removed from Clutter since they're pretty much unused,
so remove them here, too.

See https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1245
2020-05-20 15:12:03 +02:00
693dd79d28 iconGrid: Remove dead code
Remove unused methods from IconGrid.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1265
2020-05-19 16:40:49 -03:00
400d045a6a search: Replace IconGrid from grid search results
Replace the usage of IconGrid in the grid search results by
a custom layout manager that only allocates as many children
as the actor can fit.

This new layout manager does not implement changing the icon
size depending on the screen size.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1265
2020-05-19 16:40:49 -03:00
e20cf1ac78 environment: Replace monkey-patched method with Symbol.iterator
This allows using the actor itself as iterator:

  for (let child of container)
      doStuff(child);

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1269
2020-05-19 21:33:31 +02:00
8d4e650a95 environment: Monkey-patch iterate_children() generator
This is a small convenience method for using ClutterActor's iterator API
with javascript's built-in iterator protocol, for example as:

  for (let child of container.iterate_children())
      doStuff(child);

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1268
2020-05-19 21:07:20 +02:00
82fd68b985 notificationDaemon: Fix grouping by PID
For fd.o notifications, we are taking the sender's PID into
account when associating notifications with sources (mainly
to deal with notify-send).

This broke when the implementation under the well-known name
was moved into a separate service, as the implementation in
gnome-shell will now always see the public notification-daemon
as sender.

Restore the old behavior by resolving the sender PID in the
separate service, and pass it as hint to the implementation
in gnome-shell.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2592
2020-05-19 08:24:07 +00:00
6ddd43f361 extensionSystem: Prevent broken updates
Spidermonkey caches imports, which means that uninstalling an
old extension version and installing a new one doesn't work as
expected: If the previous version was loaded, then its code will
be imported instead.

For the last couple of releases this has been a reliable source
of extension bug reports after major GNOME updates. Thankfully
chrome-gnome-shell removed its update support in favor of our
built-in support now, but users may still use older versions
or perform those actions manually, so it still makes sense to
catch this case and set an appropriate error.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1248
2020-05-18 20:41:06 +00:00
4e2ae30a47 dateMenu: Remove unused property
This is a left-over from an earlier iteration where the session's
presence status was used rather than the GSetting.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2796
2020-05-18 17:02:57 +00:00
32bc064d10 calendar: Fix initial do-not-disturb state
The do-not-disturb button and the contained switch are
tied together via a bidirectional property binding.

However it still matters which objects are used as source
and target, as that will determine the initial state: Right
now the (unchecked) button is used as source, which means
that do-not-disturb is turned off on startup.

We want the state to be preserved, so swap source and target
to let the switch (that is bound to the underlying GSetting)
control the initial state.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2804
2020-05-18 18:55:19 +02:00
87606c6a6b status: Pass scroll events to volume and brightness sliders
Sliders can be operated by mouse scroll, but the mouse has to be over
the slider control.  Make the brightness and volume system menu entries
forward scroll events to the sliders they contain so that scrolling
anywhere on the menu item operates the slider.

Closes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2795
2020-05-18 11:30:28 +00:00
955afb8711 Update Serbian translation
(cherry picked from commit db2917479a)
2020-05-17 19:22:51 +00:00
3309031fd1 extensionSystem: Update canChange on error
Whether or not an extension has errors influences the 'canChange'
property, but so far we only update it for errors that occur when
initializing the extension, not when an extension is enabled later.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1249
2020-05-16 16:33:22 +00:00
a2235c269a Update Finnish translation
(cherry picked from commit 5815f9ac0e)
2020-05-16 11:03:11 +00:00
1cf2c9edd0 Update Turkish translation 2020-05-16 09:12:43 +00:00
64a3ecf9b1 dateMenu: Update timezone offsets when timezone changes
Adds a signal handler to update the timezone offsets whenever the
user changes the system timezone.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2209
2020-05-15 20:46:00 +00:00
f144ed6e87 Update Catalan translation 2020-05-15 20:43:22 +02:00
a47e0f9845 extensionDownloader: Replace deprecated Soup.SessionAsync
Soup.SessionAsync by default sets timeout and idle_timeout to 0. This
causes connections to hang around in state CLOSE_WAIT forever after the
remote host has closed the connection.

To fix this, we could set timeout and idle_timeout manually. However,
Soup.SessionAsync is marked as deprecated anyway and should be replaced
by Soup.Session. Doing so also sets a default timeout of 60 seconds.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2774
2020-05-14 19:43:56 +00:00
0737c8f416 dash: Allow adding favorites out of favorites zone
Previously, you could not add favorites outside of the favorites zone.
This change inserts a placeholder at the end of the favorites zone if
you are outside of it.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2777
2020-05-14 18:32:57 +00:00
fba350eaad Update Indonesian translation
(cherry picked from commit bc6a3329b4)
2020-05-14 09:43:30 +00:00
6d5e93b00b extensionSystem: Disable extension before unloading stylesheet
Removing a stylesheet from the theme will trigger a style update. There's
little point in updating the extension actors that are about to be destroyed
(hopefully), so call the extension's disable() function first.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2757
2020-05-13 20:10:56 +02:00
f526e592fe mpris: Prevent DBus race when creating media players
Sometimes an MPRIS media player will create and then destroy an object
before the signals that handle the object's destruction can be created.
This verifies that the object still exists after the necessary signals
have been created.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2776
2020-05-13 19:46:24 +02:00
751a94ab5d Update Japanese translation 2020-05-13 15:16:58 +00:00
e0e128e207 Update Japanese translation 2020-05-13 15:08:22 +00:00
137e6c8493 windowManager: Allow xwayland startup to complete without systemd
Since commit 0ecddafc20 gsd-xsettings startup has been made conditional
on the systemd user instance being available at runtime. While that is
correct, it means that completing xwayland startup is also conditional
now.

We always want xwayland startup to go ahead, so wait for the XSettings
plugin to appear on the bus when gsd-xsettings is launched by gnome-session
and complete the task immediately if startup fails.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1252
2020-05-12 18:05:38 +02:00
72751c2d92 Update Persian translation 2020-05-12 14:24:58 +00:00
b84fa852f6 Update French translation
(cherry picked from commit e8e79173d9)
2020-05-12 14:15:08 +00:00
d20961f323 Update Swedish translation
(cherry picked from commit 884a2623a0)
2020-05-11 22:36:14 +00:00
5a01395a2b Update Italian translation
(cherry picked from commit fbdb56eb6d)
2020-05-11 15:53:05 +00:00
e59ca7053b workspacesView: Lower scroll timeout
Looks like 250ms is too high, lower it to 150ms.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2602
2020-05-09 19:27:36 +05:00
6895592a7b appDisplay: Lower scroll timeout
Looks like 250ms is too high, lower it to 150ms.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2602
2020-05-09 19:27:33 +05:00
eed27a2a4c shell: Fix return value if the systemd unit is actually successfully run
This got broken by last minute changes in commit 2d56395921. There's no change
too simple.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1242
2020-05-08 19:21:32 +02:00
43c6afa80f Update Romanian translation 2020-05-08 16:32:22 +00:00
7d60f418e7 systemActions: Use 'system-log-out-symbolic' for logout
Changing the icon to 'system-log-out-symbolic' has no visual
change in a default GNOME setup since both 'system-log-out-symbolic'
and 'application-exit-symbolic' are the same in adwaita-icon-theme
(at the time of writing), however, other icon themes differentiate
between the two icons so pointing to the appropriate icon name
is the right thing to do.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2751
2020-05-07 19:19:32 +00:00
94dca1606f extensions-app: Add permission to talk to gnome-session
This is required for offering a "Logout" option when handling extension
updates.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2735
2020-05-07 15:58:06 +00:00
27774582b6 extensions-app: Fix Logout call
Commit 764527c8c9 adjusted the "call" call to promisification that
never happened (in this bit of code).

We can either add back a callback or properly promisify the call;
this opts for the latter.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2735
2020-05-07 15:58:06 +00:00
7dc08b06b1 Updated Spanish translation 2020-05-07 16:48:35 +02:00
a9d73b1017 panel: Center app icon
Giving the icon extra space may distort it, so center it vertically.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2578
2020-05-07 14:57:12 +02:00
25e4d0ba8b Update British English translation
(cherry picked from commit 6a9ce0f18c)
2020-05-07 10:48:37 +00:00
2d56395921 shell: Check we are in a systemd environment before starting systemd units
Avoid starting/stopping the gsd-xsettings systemd unit if the shell itself
was not started via systemd. In the lack of a user session manager, we
have no means to neatly start/stop services, so should rely on the good
ol' gnome-session to do this for us.

This changes the return value meaning slightly, TRUE means "service did
start", FALSE otherwise. The error is only raised if we ought to start,
but it produced an error somehow.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1238
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2755
2020-05-07 12:16:11 +02:00
0ecddafc20 windowManager: Handle return value/errors from systemd unit calls
These may produce errors, and return a value indicating we should
proceed further. Check for those when starting/stopping gsd-xsettings.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1238
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2755
2020-05-07 12:16:03 +02:00
af34c8d2f4 Update Dutch translation
(cherry picked from commit 473a666cc0)
2020-05-06 11:13:47 +00:00
5223599145 Update Ukrainian translation 2020-05-04 17:21:20 +00:00
c96af776d6 Updated Spanish translation 2020-05-04 16:41:18 +02:00
34da48453e shell-app: Add PrefersNonDefaultGPU support to shell_app_launch()
Read the "PrefersNonDefaultGPU" key in desktop files to figure out
whether the application prefers running on the discrete GPU, or the
default GPU, and apply that.

Update the "Launch..." contextual menu to allow launching on
the default GPU if the application "prefers [the] non default GPU".

See:
https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#recognized-keys

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1804
2020-05-04 16:22:03 +02:00
13dcd78be1 shell-app: Downgrade not finding a discrete GPU to debug
As we'll want to call this unconditionally soon.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1226
2020-05-04 16:22:03 +02:00
3bfa9916da appDisplay: Use global switcheroo-control D-Bus proxy
Rather than creating our own.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1226
2020-05-04 16:22:03 +02:00
b17017679b shell/global: Notify when switcheroo-control prop changes
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1226
2020-05-04 16:22:03 +02:00
9d7832ea44 shell/global: Make switcheroo-control available from JS
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1226
2020-05-04 16:22:03 +02:00
49605c7b00 shell/global: Watch for switcheroo-control appearing
Rather than staticly expecting switcheroo-control to already be running
on the system, wait for it appearing and disappearing.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1226
2020-05-04 16:22:03 +02:00
bf8b9cecf5 Updated Spanish translation 2020-05-04 09:57:45 +02:00
c291291304 Add Ossetian translation 2020-05-03 16:06:23 +00:00
e08a4acd06 ibusManager: Fix the panel after porting to Promises
Commit 764527c8c9 not only ports this file
to Promises but also changes the behavior of _initPanelService method.
Instead of always calling _updateReadiness when _panelService is ready,
it only calls it when get_global_engine_async succeeds.

The only callers of _updateReadiness are _initEngines and
_initPanelService. Assume that _initEngines completes first. Its
_updateReadiness call keeps _ready as false and it is expected for
_initPanelService to change it to true. However, since
get_global_engine_async fails because there is no active engine,
_initPanelService never calls _updateReadiness. Therefore, all setEngine
calls do nothing because _ready is false, and the input method panel
never shows. Users are unable to use any input method even if they can
see that ibus-daemon is already running.

Fix the issue by changing it back to the old behavior.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1235
2020-05-03 23:26:39 +08:00
0397a104ba Update Polish translation
Fixes https://gitlab.gnome.org/Teams/Translation/pl/-/issues/6
2020-05-02 21:45:45 +02:00
a41c1d4fda Update Slovak translation
(cherry picked from commit e4199c71cc)
2020-05-02 14:07:51 +00:00
8ae3ed907a Update Chinese (Taiwan) translation 2020-05-02 08:07:05 +00:00
31cd8f738c appFavorites: Add eog to rename list
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1233
2020-05-02 00:16:28 +02:00
a4cd9e0038 Update Ukrainian translation 2020-05-01 15:57:22 +00:00
e06109c23c st/theme: Unref CRStylesheet after removing old theme nodes
Since we now remove all theme nodes on a stylesheet change (ie.
StTheme's "custom-stylesheets-changed" signal) instead of only
invalidating them, those nodes may not be accessed anymore as soon as
"custom-stylesheets-changed" is emitted.

It turned out though that when comparing them to the newly generated
nodes in `st_widget_recompute_style()` using the
`st_theme_node_paint/geometry_equal()` functions, the properties of the
old nodes will still be accessed, causing a crash since the
CRDeclarations are already freed.

To fix that, keep the reference to the CRStylesheet, which owns the
CRDeclarations used by the theme nodes, around a bit longer, so it's
still possible to access the CRDeclarations inside the
"custom-stylesheets-changed" signal handler. This allows us to compare
the old theme nodes to the new ones since the CSS properties of both are
still valid.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2709
2020-05-01 14:24:16 +00:00
05485fe04c extensions-app: Fix translatable string
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1231
2020-05-01 14:14:35 +02:00
13062af7ef Update Chinese (Taiwan) translation
(cherry picked from commit dff855942e)
2020-04-30 17:32:19 +00:00
5e254666b0 messageTray: Add missing property getter
gjs has gotten less forgiving about missing getters/setters, and
commit 6aa1b817 missed the missing getter in the base policy class.

Most notifications use a policy subclass that already provides a
getter, but at least Main.notify() and friends don't; unbreak them
by fixing the base class.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1229
2020-04-30 07:41:38 +00:00
d29eb8646a Update Friulian translation 2020-04-29 22:34:43 +00:00
f1af37f220 Bump version to 3.37.1
Update NEWS.
2020-04-29 21:40:33 +02:00
d3880c0bff main: Unset the right prevFocus actor after the focus stack got shifted
When a modal that's not on top of the modalActorFocusStack gets popped,
we shift the focus stack as described in popModal() to ensure the chain
remains correct. That however destroys the association of a modal actor
and its prevFocus actor on the focus stack, because the prevFocus actors
are now moved to different entries of the stack.

Now when a prevFocus actor gets destroyed, we don't handle that case
correctly and search for the modal actor that was associated with the
prevFocus actor before the stack was shifted, which means we end up
unsetting the wrong prevFocus actor.

So fix that and search the stack for the prevFocus actor which is being
destroyed instead to unset the correct entry.

Thanks to Florian Müllner for figuring out the actual issue and
proposing this fix.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2446
2020-04-29 12:40:13 +02:00
4dfa39457e st/theme-context: Also remove theme nodes on stylesheet changes
StThemeNodes are built around the assumption that they're "immutable",
that means they are created once with certain parameters (that resolve
to certain css properties) and then replaced with new ones in case those
parameters changed.

Changes to the internal information stored by theme nodes (i.e. the css
properties, font names or the cached scale-factor) are not all handled
the same though: For changes to the font or the scale-factor we remove
all theme nodes from the cache and let the widgets which are on stage
generate new theme nodes. For changes to the css properties/the
stylesheet, we invalidate the properties of all theme nodes but keep
them in the cache using `_st_theme_node_reset_for_stylesheet_change()`.

So be a bit more consistent and handle changes to the css-properties/the
stylesheet stored by StThemeNodes the same way as changes to the font or
scale-factor.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1218
2020-04-28 19:53:58 +00:00
325ff73c5b st: Ensure to reset all widget theme nodes
Theme node invalidation stops at unmapped widgets, and widgets
that forget to chain up to the default ::style-changed implementation.
This may leave stale nodes that were invalidated on
StThemeContext::changed, but are still set on widgets, and maybe
used for CSS property lookups.

Make sure that theme node invalidation happens always by moving
propagation outside the vfunc, and ensure the theme nodes are reset
across the full actor tree. Emission of ::style-changed, and obtaining
a new theme node may be delayed till when the actor is mapped.

The theme node is also cleared after unparenting an actor to avoid
stale references.

This ensures that all widgets get their theme node cleared after
stylesheet changes, instead of maybe being left with a theme node
that's been cleared of all its properties.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2541

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1223
2020-04-28 18:46:13 +00:00
1fa4e3b1b2 Update Turkish translation 2020-04-28 13:19:54 +00:00
f89091d0f0 ci: Rebase extension-ci image to F32
... and base our 'js' test on the js engine we are actually using.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1177
2020-04-28 09:04:49 +00:00
859927df39 ci: Document how to build the image
Updating the CI image is rare enough to not know the involved
commands by heart, so adding a comment like mutter did a while
ago makes perfect sense.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1177
2020-04-28 09:04:49 +00:00
e7512fcd79 ci: Rename Dockerfile
Our primary image now comes from mutter, so the default Dockerfile
name is free for our JS image.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1177
2020-04-28 09:04:49 +00:00
2b70151794 keyboard: Minor cleanup
Use the more concise operator shorthand.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1177
2020-04-28 09:04:49 +00:00
153b7d525d cleanup: Don't linebreak before closing parentheses
Otherwise recent versions of eslint want "dangling" commas,
which is at least ugly considering that most functions don't
allow adding arguments at leasure.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1177
2020-04-28 09:04:49 +00:00
2e80995f19 overviewControls: Remove transitions before updating adjustment value
The workspace switcher blocks state updates while the indicator is
animating. Since commit 9c1940ef9d the indicator is considered to
be animating when the workspace adjustment's value doesn't equal the
active workspace.

There is one case though where this breaks badly: When a workspace
is inserted before the active one, the adjustment's upper and value
properties are changed without transitions. But if that change happens
while there's an ongoing transition to the previously active workspace,
the value gets out of sync with the active workspace and we end up
blocking state updates indefinitely.

Fix this by removing any transitions before setting the adjustment
value.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2625
2020-04-28 01:28:50 +02:00
9232cbf8a7 ci: Cache eslint results
While this isn't useful during CI, it can provide a massive speed-up
when used locally.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1094
2020-04-27 22:15:25 +00:00
55f74bb863 Add small gnome-shell-extension-prefs script
Commit d76162c1c0 removed the ability to pass an extension UUID to
the Extensions app, when we moved the dialog to a portal and made
gnome-shell use it instead of spawning the extensions app.

However that missed that many extensions called out to the app to
open their own prefs.

While extensions are encouraged to switch to the new openPrefs()
convenience method added in commit 8030d9ad32, restore the old
behavior with a small script under the old gnome-shell-extension-prefs
name that either calls out to the portal or launches the app.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1220
2020-04-28 00:06:19 +02:00
b02e3719b3 extensions-app: Rename executable
We kept the old binary name when overhauling the tool for the Extensions
app to avoid unnecessary churn for packagers/distributors.

However we now have a reason to "free" the old name, so rename the binary
to match the (sub)project name.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1220
2020-04-28 00:06:19 +02:00
3ba4304da9 keyboard: Add missing setter
We override the :visible property for the keyboard actor, but don't
provide a corresponding setter. The property is therefore read-only
on the javascript level, and any attempt to set it will fail.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2691
2020-04-27 23:48:54 +02:00
49d6db34b7 altTab: Set allocation before allocating children
Just as with the last commit, we should not break the assumption made by
Clutter that parents have their allocation set before their children get
allocated, so fix that here, too.

In this case we have to fix it by chaining up to the parent vfunc
override and updating the allocation once more before allocating the
`this._label` child.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1615
2020-04-27 19:53:27 +02:00
63a0e521fd boxpointer: Call set_allocation before allocating child
It's important to update the allocation of the parent before allocating
its children, it's an assumption we make in a lot of places.

This broke resource scale calculation for boxpointers and their
children when multiple monitors with different scales are used and the
primary monitor is not positioned at x=0, y=0.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1615
2020-04-27 19:53:20 +02:00
c00d79bae2 calendar-server: Improve performance by properly using ECalClientView
The previous code always restarted whole ECalClientView when it received
any changes in it, which could sometimes lead to constant repeated restarts
of the view.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1875
2020-04-27 16:14:57 +00:00
30d902f898 calendar-server: Drop separate private struct
CalendarSources is a final type, so the regular instance struct is
already non-public. No need for a separate private struct and priv
pointer ...

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1875
2020-04-27 16:14:57 +00:00
8f9da6f801 calendar-server: Add missing spaces
... according to coding style.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1875
2020-04-27 16:14:57 +00:00
20648e9207 calendar-server: Replace tabs with spaces
... according to the coding style.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1875
2020-04-27 16:14:57 +00:00
614fe202e0 Updated Spanish translation 2020-04-27 18:14:01 +02:00
c3646a7642 js/main: Inhibit remote access when depending on session mode
The session mode determines whether the screen casting should work or
not, but until now only dealt with the built in screen cast, not the
ones using PipeWire. Add the newly added API for inhibiting remote
access when the session mode says screencasts are not allowed.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1210
2020-04-27 15:18:18 +00:00
772df91762 shell/global: Add 'backend' property
Replace all Meta.get_backend() with global.backend. Maybe sooner or
later we can further decrease the amount of singletons handled by
libmutter.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1210
2020-04-27 15:18:18 +00:00
c90910731f croco: Remove duplicated conditions
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1219
2020-04-27 16:23:46 +02:00
ba69cd99d1 ci: Simplify flatpak job
The template has been updated to rewrite the manifest to use the
checked out tree, so it's no longer necessary to pass additional
build arguments (which are now ignored) or generate translations
before the build (it's already in the manifest).

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1217
2020-04-27 13:16:55 +00:00
fb6e341efd Revert "ci: Revert to a previous version of the flatpak template"
This reverts commit 1ff638a51f.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1217
2020-04-27 13:16:55 +00:00
3dc4f01113 JS: migrate from the global window to globalThis
As of mozjs68 (gjs-1.64) `globalThis` is recommended over `window` and
it makes more sense in this context anyways. Migrate the few instances
of `window` we use and adjust the eslint configuration.

`window` will continue to resolve to `globalThis`, so this won't affect
extensions or other downstream users.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2322

closes #2322
2020-04-26 19:07:02 -07:00
d94d0f60c8 calendar: Do less work in hasEvents()
getEvents() filters all events for the given range and sorts the result.

That's more than we need when checking whether there are any events,
where we only care that there's at least one event in the range.

Address this by splitting out the event filtering into a generator
function, so hasEvents() can return after at most one iteration.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1192
2020-04-26 16:20:49 +00:00
8d79f6f4c8 calendar: Update events on changes
We track messages so that we can account for just added and removed
events instead of having to rebuild the entire list, however it's
also possible that the time or summary of an existing event changed.

Account for that by updating existing messages in-place.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1192
2020-04-26 16:20:49 +00:00
c5e5bb0be1 Update Basque translation 2020-04-25 17:21:35 +00:00
8d139bbd95 authPrompt: Grab key focus when making entry sensitive
We currently let the entry of the autoPrompt grab the key focus inside
setQuestion(), which is called from _onAskQuestion(), which is the
callback of the "ask-question" signal.

It seems that the "ask-question" signal isn't emitted again right after
the password-check failed, but a few seconds after that. Since we get
the "verification-failed" signal earlier than "ask-question" (right
after we know the check failed) and we also get a hint whether the entry
should be usable again with the canRetry argument, we can also grab key
focus to in the same step.

So do that by grabbing key focus when making the entry sensitive.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2655
2020-04-25 14:54:07 +00:00
fb1bb291eb unlockDialog: Call AuthPrompt.addCharacter() directly
The additional function UnlockDialog.addCharacter() is only used at one
place, so we can simply remove it and call AuthPrompt.addCharacter()
directly. The AuthPrompt is shown right before that anyway.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1209
2020-04-25 14:54:07 +00:00
3199620a83 systemActions: include ASCII alternatives in search index
With this change, "eteindre" matches "éteindre" (the French translation
for "power off"), consistent with search for applications where "e"
matches "é".

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2688
2020-04-25 13:55:20 +01:00
c88bb66369 Update Ukrainian translation 2020-04-25 08:08:40 +00:00
a60d57ea1f screenShield: Don't inhibit suspend during initial setup
Normally, we inhibit suspend while locking the screen. But in the
session mode used for gnome-initial-setup locking is not supported, so
in that case this inhibit call is pointless and should be avoided.
Without this patch you get the following error when you suspend and
resume during initial setup:

JS ERROR: Error getting systemd inhibitor: Gio.IOErrorEnum:
GDBus.Error:org.freedesktop.login1.OperationInProgress: The operation
inhibition has been requested for is already running
_promisify/proto[asyncFunc]/</<@resource:///org/gnome/gjs/modules/core/overrides/Gio.js:435:45

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1213
2020-04-24 23:47:31 +00:00
527ce66cd4 screenShield: Fix use of null this._dialog
On Fedora 32 if you close the laptop lid during gnome-initial-setup,
gnome-shell hits this error:

JS ERROR: Exception in callback for signal: prepare-for-sleep: TypeError: this._dialog is undefined
_resetLockScreen@resource:///org/gnome/shell/ui/screenShield.js:434:9
activate@resource:///org/gnome/shell/ui/screenShield.js:571:14
lock@resource:///org/gnome/shell/ui/screenShield.js:617:14
_prepareForSleep@resource:///org/gnome/shell/ui/screenShield.js:219:22
_emit@resource:///org/gnome/gjs/modules/core/_signals.js:133:47
_prepareForSleep@resource:///org/gnome/shell/misc/loginManager.js:198:14
_emit@resource:///org/gnome/gjs/modules/core/_signals.js:133:47
_convertToNativeSignal@resource:///org/gnome/gjs/modules/core/overrides/Gio.js:169:19

This is because _ensureUnlockDialog() hit its first early return. So
return early from activate() in that case, so this._dialog doesn't get
used while it's null.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1213
2020-04-24 23:47:31 +00:00
40415a6849 Update Persian translation 2020-04-24 20:06:24 +00:00
1ff638a51f ci: Revert to a previous version of the flatpak template
A new version seems to be causing some issues, so
use the previous revision until it's resolved

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1214
2020-04-24 20:34:32 +02:00
2a9ccf2e2c appDisplay: Return the parent class' result in overrides
StButton returns CLUTTER_EVENT_STOP in various circumstances, but
AppIcon throws that away and returns CLUTTER_EVENT_PROPAGATE even
when it should stop.

Return the parent class' result instead of CLUTTER_EVENT_PROPAGATE.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1211
2020-04-23 19:14:43 -03:00
2909d91c13 appDisplay: Use const instead of let in vfunc_leave_event
The return value of the chain up is not changed, let's use the
proper descriptor.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1211
2020-04-23 19:14:40 -03:00
0dba12193d st: Update to new API for creating paint context
It now takes a redraw clip and flags.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1207
2020-04-23 14:46:03 +00:00
02f40b3b63 Update Czech translation 2020-04-22 13:01:15 +00:00
1fd51efc7f Update Brazilian Portuguese translation
(cherry picked from commit 60ee6ab4b7)
2020-04-22 12:33:18 +00:00
6f881f232e test-theme: Check return value of chdir()
I noticed the following warning while building the .deb package for
gnome-shell on Endless OS:

      ../src/st/test-theme.c: In function ‘main’:
      ../src/st/test-theme.c:549:3: warning: ignoring return value of ‘chdir’, declared with attribute warn_unused_result [-Wunused-result]
         chdir (cwd);
         ^~~~~~~~~~~

(Of course this is very unlikely to fail in practice.)

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1208
2020-04-21 15:00:23 +02:00
be12c71534 loginDialog: Get resource scale by get_resource_scale
To shut up 'Getting invalid resource scale property' warnings in the log.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1206
2020-04-21 13:48:56 +02:00
6aa1b817c9 messageTray: Make NotificationPolicy properties read-only
These properties are never written; in the base class they are always
their default values, and in the subclasses the getters are overridden.

This will be necessary because GJS is adding checks to make sure that
readable properties always have a getter, writable properties always
have a setter, and that the variations of camelCase/snake_case are
handled correctly. It's supposedly backwards compatible, but that
assumes that code is not doing things like forgetting a setter on a
writable property. (If the missing setter had ever been called, it might
have led to a crash, which is why we've made this change.)

This is the minimally invasive patch which should work with both older
and newer versions of GJS. If you decide to require GJS 1.65.2, then
you'll also be able to remove the getters from NotificationPolicy as
well.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1205
2020-04-20 17:27:48 -07:00
300961e19e Update zh_CN translations 2020-04-18 09:10:21 +00:00
b191e9ef91 authPrompt: Fix spinner alignment
We want the spinner to be centered with regard to the entry, but
constraining the height breaks that:

 1. clutter_actor_allocate() is called with the available size
 2. clutter_actor_update_constraints() then adjusts that according
    to the constraints
 3. clutter_actor_adjust_allocation() applies the margin/expand/align
    properties.

The issue there is that 2. reduces the allocation to the desired size,
so there is no more extra space to distribute in 3.

We can fix this by either constraining everything (and rely on the
cancel button's alignment) or limit the constraint to the width. The
latter seems more appropriate, given that the constraint is only used
to center the entry horizontally.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2628
2020-04-17 22:35:31 +00:00
5ec5978d4a windowManager: Fix ngettext() call
We don't pass the number that allows gettext to decide on the
correct string, whoops.

Spotted by Alexandre Franke.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2649
2020-04-17 22:25:09 +00:00
f4d90bc127 polkitAgent: Reset the session request timeout when removing it
When handing the resetDialog request we're leaving a source ID alive,
leading this error:

(gnome-shell:22464): GLib-CRITICAL **: 17:46:11.065: Source ID 12934 was not
found when attempting to remove it:

== Stack trace for context 0x55c9246916c0 ==
#0 55c9249151b8 i   js/ui/components/polkitAgent.js:391 (11f71fd544c0 @ 100)
#1 7ffc55140aa0 b   self-hosted:1009 (3062ba49af88 @ 423)
#2 55c924915120 i   js/ui/modalDialog.js:167 (1c9e50ae9880 @ 62)
#3 55c924915098 i   js/ui/modalDialog.js:186 (1c9e50ae9970 @ 12)
#4 55c924915008 i   js/ui/environment.js:75 (1c9e50a8d5b0 @ 98)
#5 55c924914f78 i   js/ui/environment.js:149 (1c9e50a8d9e8 @ 14)

So, reset the source handle to avoid trying to remove it.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1203
2020-04-17 16:17:51 +00:00
bfa34914db polkitAgent: Return GLib.SOURCE_REMOVE on timeout callback
resetDialog is used (also) as GLib timeout function, so while just returning
an undefined value will stop the timeout anyways, it's just cleaner to
use the GSource expected return values

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1203
2020-04-17 16:17:51 +00:00
8d1e4659d1 js/ui: Always use namespace for animation modes
Clutter.Animation doesn't contain any animation modes, they live in
Clutter.AnimationMode. The places we did `Clutter.Animation.WHATEVER`
just evaluated to `undefined`. Thus, use the correct namespace for the
animation mode enums.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1199
2020-04-15 13:59:38 +00:00
b3b91f1699 js: Drop tweener.js
We're using clutter's animation framework now, so lets drop the old
tweener support layer.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1200
2020-04-15 13:25:14 +00:00
ff4c5270d3 build: Obtain systemduserunitdir from pkg-config
Previously, this prevented local installation because systemd did not
make the variable's prefix overridable

https://github.com/systemd/systemd/issues/9595

but since it has been fixed in systemd 242, we can finally use that.

---

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1194
2020-04-13 15:27:09 +00:00
e240f7ea59 build: Install keybindings relative to our datadír
It is a good practice to install files relative to our own variables

https://www.bassi.io/articles/2018/03/15/pkg-config-and-paths/

and it is required on systems like NixOS.

---

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1194
2020-04-13 15:27:09 +00:00
9f1ad5d86d extension-tool/build: Install completions relative to our datadír
It is a good practice to install files relative to our own variables

https://www.bassi.io/articles/2018/03/15/pkg-config-and-paths/

and it is required on systems like NixOS.

Thanks to Iñigo, bash-completion support that since 2.10:

https://github.com/scop/bash-completion/pull/344

---

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1194
2020-04-13 15:27:09 +00:00
a1ab32af0f Update Finnish translation
(cherry picked from commit cc0fac895c)
2020-04-13 15:03:35 +00:00
3fac0632a8 appDisplay: Look up directory- instead of category translations
Translations are provided by .directory files, so trying to look
up a category name without the suffix will always fail.

Commit 343b3351f1 tried to fix this previously by changing the
saved keys, but that broke existing translatable folders.

Appending the .directory suffix for the lookup instead fixes the
issue without regressing non-custom folders.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2623
2020-04-13 14:56:34 +00:00
c2b518929d Revert "app-cache: Fix cache for folder translations"
Existing folders as created by gnome-software (including the
default ones) all have the .directory suffix, so dropping
the suffix from the keys broke those folders.

This reverts commit 343b3351f1.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2623
2020-04-13 14:56:34 +00:00
c422d82752 Update Esperanto translation 2020-04-11 18:21:21 +00:00
da0c7fc2b6 dateMenu: Update empty weather label
Remove subtitle for the empty weather state
to match world clocks button.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2179
2020-04-09 10:52:44 -03:00
167bc080d9 appDisplay: Reorganize AppDisplay actor hierarchy
Right now, the actor hierarchy is such that the scroll view
does not contain the actual grid. It looks as follows:

              StScrollView
                    ↓
               StBoxLayout
                    ↓
                ShellStack
                ↓        ↓
   PaginatedIconGrid     StWidget

This hierarchy can be slightly reorganized by changing it to be as
follows:

            ShellStack
             ↓     ↓
   StScrollView   StWidget
        ↓
   StBoxLayout
        ↓
 PaginatedIconGrid

This will simplify future work where the PaginatedIconGrid will be
an implementation of StScrollable, in which case we'll be able to
simply remove the StBoxLayout from there.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1191
2020-04-08 21:12:06 -03:00
7d7a15f978 st/entry: Allow hint actor to shrink
We currently always ignore the minimum width of the hint actor and
request/allocate the preferred width. This can be problematic with
labels with long text, where we should rather ellipsize the text
than allow the entry to grow indefinively.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2607
2020-04-08 22:41:19 +00:00
1b5cf0b8a8 build: Bump version requirement
We are currently optionally using a 0.53 feature, bump the requirement
to make it non-optional.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1186
2020-04-07 23:13:27 +02:00
306b005943 extensions-tool: Add small indicator template
Adding an additional icon to the top bar is one of the more common
patterns used by extensions. Make this easier by providing a template
for it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
d229abf07d extensions-tool: Prompt for template when appropriate
When creating an extension interactively, we currently always use
the default template unless the --template option is used.

Instead, display the list of available templates to the user and
prompt them to pick one if it wasn't specified.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
6f6251c0bc extensions-tool: Add --template create option
We now have everything in place to allow users to pick a template
other than the default one (although at the moment it's the only
one we have), so add a corresponding option.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
fd034e3551 extensions-tool: Add hidden --list-templates option
This isn't a very useful option on its own, but will be used to
provide completions for a user-visible --template option.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
f9bee05d49 extensions-tool: Add template metadata
When we allow users to choose between different templates, we should
provide some context for each template to facilitate that choice.

Add that metadata in the form of a .desktop file, which allows us to
specify name and description, and is well supported by our translation
infrastructure.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
37c6fbc6b2 extensions-tool: Prepare for alternative templates
The template used when creating a new extension is intentionally
minimal, as the sample code in the old extensions-tool proved to
be annoying more often than not.

However as we support per-command options, we don't have to limit
ourselves to a single template, and can offer alternatives for
common use cases.

To prepare for that, namespace the existing template by moving it
into a subfolder.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
9719604b79 extensions-tool: Separate create metadata when prompting
When using the create command's --interactive option, we prompt for
any metadata that wasn't passed on the command line. As every prompt
is preceded by a short multi-line description, it is hard to follow
when everything is lumped together.

Improve legibility by separating all prompts by newlines.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
b6262f0666 extensions-tool: Handle NULL input when prompting for metadata
g_data_input_stream_read_line_utf8() may return NULL, for example
when interrupting the prompt with ^D. Handle that case and keep
prompting until we got a line.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
6c0bd207e9 ci: Handle POTFILES.skip in potfiles check
Allow marking files as ignored when searching for translatable
strings, similar to "good" ol' intltool.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/812
2020-04-07 20:27:00 +00:00
91b13effc8 appFavorites: Hide favourites which are blacklisted by parental controls
If a favourite is set for an app which is blocked by parental controls,
that favourite should be hidden.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/465
2020-04-07 17:47:33 +02:00
143ab6ac7f search: Hide search providers which are blacklisted by parental controls
If a search provider is installed by an app which is blacklisted for the
current user by their parental controls, don’t show it or results for
it.

Currently, this only filters ‘remote’ (not built-in to the shell) search
providers. This seems fine for now; in future it could be expanded to
also filter built-in search providers, if any of them end up needing to
be filtered.

No corresponding changes need to be made `remoteSearch.js`, because the
results of `loadRemoteSearchProviders()` are filtered in `search.js`.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/465
2020-04-07 17:47:33 +02:00
3e5b90dbba js: Add support for parental controls filtering to the desktop
Filter the apps shown on the desktop and in search results according to
whether they are blacklisted by the user’s parental controls.

This supports dynamically updating the filter during the user’s session.

This adds an optional dependency on libmalcontent. If that’s unavailable, no
parental controls filtering will occur.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/465
2020-04-07 17:47:29 +02:00
b82039e324 util: Add a wrapper around getuid()
So we can use it from JS in an upcoming commit.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/465
2020-04-07 17:46:39 +02:00
83862d04a0 build: Bump gjs requirement
We require gjs!410 for commit 764527. There has been a gjs release
with that change now, so bump the requirement accordingly.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2559
2020-04-07 14:06:45 +00:00
52d07f6d9b ci: Update to F32-based image
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2559
2020-04-07 14:06:45 +00:00
21de88c3ba bluetooth: Do not update hadSetupDevices on adapter changes
While we now deal more gracefully with adapter removals, we can
still mess up the hadSetupDevices tracking:

As adapters become available before any devices, we'll always
reset the setting to false when Bluetooth is turned on. And if
no set up device happens to be in range, it will still be false
when Bluetooth is turned off again.

To address that, only update the setting if we have an adapter
(like we do now) and we had one before (so it wasn't the adapter
itself that changed).

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1174
2020-04-07 15:44:50 +02:00
456ca3d3e0 bluetooth: Do not sync() immediately on model changes
Our intended behavior when bluetooth is turned off is to keep
the menu visible if devices had been set up previously.

However since gnome-bluetooth@c437c729, devices are removed
first before removing the default adapter, so we now end up
always setting the property to false before checking for it.

Fix this by deferring all model changes to an idle, so that
we can process them as a unit. Do the same for proxy property
changes, as those may trigger a row-removal.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1174
2020-04-07 15:44:50 +02:00
f4ba3e4ab8 bluetooth: Fix showing menu when devices were set up
Since commit 26c2cb9f65, nDevices is always the actual number of
paired/trusted devices. So when bluetooth is turned off, it is
now 0 rather than forced to 1 if devices were set up previously.

Fix this by checking the property that tracks set up devices instead.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1174
2020-04-07 15:44:50 +02:00
d4db5a59c1 shell-app: Ignore invalid window PIDs
When building the list of window PIDs, it's possible Mutter doesn't know
about the PID the client has and meta_window_get_pid() will return 0. We
should handle this case by not adding the PID to the list of PIDs
instead of adding an invalid one to it.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1184
2020-04-06 21:53:37 +00:00
4aee87a31b shell-window-tracker: Detect invalid PID values of 0
MetaWindows get_pid() API changed to use the client PID, which also
works for Wayland clients instead of only X11 clients now. This API
returns 0 instead of -1 for invalid PIDs, so update our check according
to that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1184
2020-04-06 21:53:37 +00:00
e8f5a842b1 theme: tone down weekend with events
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2588
2020-04-06 20:54:37 +00:00
5c681a76b6 Update Ukrainian translation 2020-04-06 16:19:08 +00:00
53a24e6ddd animation: Set size through CSS
Pretty much the same case of the previous commit: we want this size
to be scale-dependant, and using the width and height properties of
ClutterActor doesn't automatically update.

Use CSS to set the width and height.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 11:24:30 -03:00
b27c89f836 appDisplay: Set the folder icon geometry through CSS
The CSS engine is scale-aware, whereas simply setting the
width and height properties directly isn't.

Use CSS to set the folder icon.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 11:24:30 -03:00
9f870aa1c7 st/theme-node: Use the node's scale factor
Each node stores the scale factor in place when it was created.
Creating nodes with the same style, but with different scale
factors, yields different nodes.

Use the node's scale factor instead of retrieving the context's
one.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 11:24:30 -03:00
c9cfeb8318 st/theme-node: Consider scale factor when comparing
The CSS engine of St is scale-aware, which means every length
and size it produces is multiplied by the current scale factor.

However, the individual nodes aren't aware of the scale factor
when they compare to each other.

Store and compare the scale factors in the nodes themselves.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1635

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 11:24:30 -03:00
497e66ce6a st/theme-context: Add a getter for the scale-factor property
Will be used by the next commit to avoid going through the GObject
machinery when retrieving the scale factor.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 11:24:30 -03:00
bc973b80d7 st/theme-context: Also invalidate root node on stylesheet changes
Since commit 6a42d77261 we invalidate the
cached properties for each theme node on stylesheet changes by iterating
over the hashtable of the theme context instead of listening to the
signal in each individual theme node.

That commit forgot one particular node though that's not stored in the
hashtable, but using the `priv->root_node` property instead: The theme
node that belongs to the stage.

So make sure we also invalidate the cached properties of the stage theme
node on stylesheet changes. This fixes various crashes that happened
with extensions providing custom stylesheets (emitting the
"custom-stylesheets-changed" signal on every extension enable/disable),
trying to access an already freed CSS property of the stage.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2584
2020-04-06 10:45:55 +00:00
85846d88f0 shell-app: Use container widget for fallback X11 app icons
Just like StIcon does, we should use a container widget for the fallback
app icon that we get using the cairo surface property. It's needed
because the widget returned by shell_app_create_icon_texture() can be
resized freely, while we want the aspect ratio of the actual texture to
remain the same.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2578
2020-04-06 08:28:26 +00:00
6b7c85b079 data: Add extension-portal desktop file
Now that the extension preference dialog is opened by a separate
D-Bus service rather than the Extensions app, it can be opened
without a parent window that provides name and icon.

Fix this by adding back a hidden .desktop file.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2562
2020-04-05 13:36:35 +00:00
d80ef67d1d extension-tool: Use enable/disable D-Bus API if possible
Commit 4589da957 added D-Bus API for enabling/disabling extensions,
use that if possible to provide better feedback and not clutter the
settings with non-existent UUIDs.

The old code path is preserved as fallback to keep the commands
working from outside a running shell session.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2391
2020-04-05 13:42:50 +02:00
62f3457a95 extensions-tool/uninstall: Error out for system extensions
UninstallExtensions() only returns whether the operation was successful,
not why it failed. However we know that only user extensions can be
uninstalled, so check that first to provide a more meaningful error.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2391
2020-04-05 13:42:50 +02:00
636ab4b0e9 extensions-tool: Split out get_extension_property() helper
For the prefs command, we first fetch the extension info to check
whether the extension exists and actually has preferences. This
pattern can be useful for other commands and properties, so split
out a generic helper function.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2391
2020-04-05 13:42:50 +02:00
23e382dd33 extensions-tool: Log existing errors
In many cases we currently only indicate failure in the return value,
which is easily missed. Print some meaningful errors instead.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2391
2020-04-05 13:42:50 +02:00
f5a170ce46 extensions-tool: Add common option to silence errors
Error reporting is useful when used interactively, but often undesirable
when used in scripts. Account for that with a common --quiet option,
which is more convenient than redirection stderr to /dev/null.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2391
2020-04-05 13:42:50 +02:00
fbd6beea2c extensions-app: Validate .desktop file during meson test
... if desktop-file-validate is available.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1160
2020-04-05 11:02:00 +00:00
360f5b1642 extensions-app: Add category in .desktop file
Predefined categories aren't a great way for organizing installed
applications, but they have their use in "stores" like Software
or flathub.

Not listing any category means we fall through the cracks, so
pick the (hopefully) least inappropriate one ...

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1160
2020-04-05 11:02:00 +00:00
f0a785df9d extensions-app: Add developer name in metainfo
Unlike Software, flathub doesn't fall back to the "project group"
when no developer is specified, so add one.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1160
2020-04-05 11:02:00 +00:00
e2c1bfbedd extensions-app: Add flathub badge to README
The app is now on flathub, so brag about that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1160
2020-04-05 11:02:00 +00:00
7e5a1cfd90 Update Latvian translation
(cherry picked from commit 6d38a4a7b3)
2020-04-04 16:14:55 +00:00
07deda593a st/icon: Always show empty texture if both gicons are NULL
Commit 7ff7fb5d3b forgot to clear the
`priv->icon_texture` actor when returning from st_icon_update(), which
means we don't always switch to an empty icon if both gicon properties
are set to NULL.

Fix this and destroy the actor before returning early from
st_icon_update().

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1178
2020-04-04 16:20:35 +02:00
1ca39e8586 st/icon: Use a static GIcon for the missing-image icon
Don't create a new GIcon for the "missing-image" texture but simply
create it once statically instead and always use that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1179
2020-04-04 13:21:54 +02:00
196 changed files with 19221 additions and 13667 deletions

1
.gitignore vendored
View File

@ -60,7 +60,6 @@ src/calendar-server/evolution-calendar.desktop
src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell
src/gnome-shell-calendar-server
src/gnome-shell-extension-prefs
src/gnome-shell-extension-tool
src/gnome-shell-hotplug-sniffer
src/gnome-shell-perf-helper

View File

@ -18,7 +18,7 @@ variables:
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
stage: review
variables:
GIT_DEPTH: "100"
@ -28,10 +28,10 @@ check_commit_log:
- merge_requests
js_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
stage: review
script:
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- find js -name '*.js' -exec js68 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG)
<<: *only_default
artifacts:
@ -40,7 +40,7 @@ js_check:
when: on_failure
eslint:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
stage: review
script:
- ./.gitlab-ci/run-eslint.sh
@ -51,21 +51,21 @@ eslint:
when: always
potfile_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
stage: review
script:
- ./.gitlab-ci/check-potfiles.sh
<<: *only_default
no_template_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
stage: review
script:
- ./.gitlab-ci/check-template-strings.sh
<<: *only_default
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
stage: build
before_script:
- .gitlab-ci/checkout-mutter.sh
@ -83,7 +83,7 @@ build:
- build
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
stage: test
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
@ -100,7 +100,7 @@ test:
when: on_failure
test-pot:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
stage: test
before_script:
- ninja -C mutter/build install
@ -124,11 +124,7 @@ flatpak:
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
FLATPAK_MODULE: "gnome-extensions-app"
APP_ID: "org.gnome.Extensions"
MESON_ARGS: "$SUBPROJECT"
extends: .flatpak
before_script:
- flatpak run --command=$SUBPROJECT/generate-translations.sh
--filesystem=host org.gnome.Sdk//master
<<: *only_default
nightly:

24
.gitlab-ci/Dockerfile Normal file
View File

@ -0,0 +1,24 @@
# Rebuild and push with
#
# cd .gitlab-ci/
# podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2 .
# podman push registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
#
FROM registry.fedoraproject.org/fedora:32
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' git && \
# For syntax checks with `find . -name '*.js' -exec js68 -c -s '{}' ';'`
dnf install -y findutils mozjs68-devel && \
# For static analysis with eslint
dnf install -y nodejs && \
npm install -g eslint && \
# Shameless plug for my own tooling; useful for generating zip
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf install -y gnome-extensions-tool meson && \
dnf clean all

View File

@ -1,18 +0,0 @@
FROM registry.fedoraproject.org/fedora:latest
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' git && \
# For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'`
dnf install -y findutils mozjs60-devel && \
# For static analysis with eslint
dnf install -y nodejs && \
npm install -g eslint && \
# Shameless plug for my own tooling; useful for generating zip
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf install -y gnome-extensions-tool meson && \
dnf clean all && \
rm -rf /var/cache/dnf

View File

@ -6,6 +6,11 @@ globs=('*.js' '*.c')
# find source files that contain gettext keywords
files=$(grep -lR ${globs[@]/#/--include=} '\(gettext\|[^I_)]_\)(' $srcdirs)
# filter out excluded files
if [ -f po/POTFILES.skip ]; then
files=$(for f in $files; do ! grep -q ^$f po/POTFILES.skip && echo $f; done)
fi
# find those that aren't listed in POTFILES.in
missing=$(for f in $files; do ! grep -q ^$f po/POTFILES.in && echo $f; done)

View File

@ -18,12 +18,14 @@ run_eslint() {
local extra_args=ARGS_$1
local output_var=OUTPUT_$1
local output=${!output_var}
local cache=.eslintcache-${1,,}
# ensure output exists even if eslint doesn't report any errors
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js subprojects/extensions-app/js
eslint -f unix --cache --cache-location $cache ${!extra_args} -o $output \
js subprojects/extensions-app/js
}
list_commit_range_additions() {

85
NEWS
View File

@ -1,3 +1,88 @@
3.37.2
======
* Add support for "PrefersNonDefaultGPU" desktop key [Bastien; !1226]
* Only start systemd units when running under systemd
[Carlos, Florian; #2755, !1242, !1252]
* Fix "ghost" media controls [Bryan; #2776]
* Fix zombie sockets from extensions downloader [Michael; #2774]
* Update world clocks offsets when timezone changes [Bryan; #2209]
* Support scrolling anywhere in slider menu items [Peter; #2795]
* Fix "Do Not Disturb" setting getting reset on startup [Florian; #2804]
* Only allow updates for extensions that aren't cached [Florian; !1248]
* Fix matching notifications by PID [Florian; #2592]
* Indicate extension errors in Extensions app [Florian; #2337]
* Add clipboard API for querying supported mimetypes [Andy; #2819]
* Add preview to color picker [Florian; #451]
* Improve world clocks styling [PrOF-kk; #2825]
* Remove Frequent view from app picker [Georges; !880]
* Fix pad OSD glitches [Carlos; !1290]
* Expose actor tree in looking glass [Georges; !1292]
* Fixed crashes [Jonas D., Florian; #2709, #2757]
* Misc. bug fixes and cleanups [Florian, AsciiWolf, Michael, Piotr, Ting-Wei,
Amr, Alexander, Bryan, Georges, Jonas D., Andy, Björn, Koki, Carlos; !1229,
!1231, !1233, !1235, #2578, #2735, #2751, #2602, #2777, !1249, #2796, !1268,
!1269, !1265, !1245, !1273, #2816, !1274, !1263, !1188, !1276, #2652, !1277,
!1281, #2286, !1267, !1286, !1279, !1288, !1293, !1294, !1291]
Contributors:
AsciiWolf, Michael Catanzaro, Björn Daase, Jonas Dreßler, Bryan Dunsmore,
Koki Fukuda, Carlos Garnacho, Andy Holmes, Amr Ibrahim, Soslan Khubulov,
Ting-Wei Lan, Michael Lass, Alexander Mikhaylenko, Florian Müllner,
Georges Basile Stavracas Neto, Bastien Nocera, PrOF-kk, Peter Simonyi
Translators:
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Yuri Chornoivan [uk],
Dušan Kazik [sk], Piotr Drąg [pl], Soslan Khubulov [os],
Daniel Mustieles [es], Nathan Follens [nl], Bruce Cowan [en_GB],
Florentina Mușat [ro], Milo Casagrande [it], Anders Jonsson [sv],
Charles Monzat [fr], Danial Behzadi [fa], sicklylife [ja], Kukuh Syafaat [id],
Jordi Mas [ca], Emin Tufan Çetin [tr], Jiri Grönroos [fi], Марко Костић [sr],
Christian Kirbach [de], Changwoo Ryu [ko], Matej Urbančič [sl]
3.37.1
======
* Improve bluetooth submenu title [Mariana; #2340]
* Add openPrefs() convenience method for extensions [Florian; !1163]
* Bring back support for empty StIcons [Andre, Jonas D.; !1173, !1178]
* Wake up screen when unlocking programmatically [Florian; !1158]
* Improve extensions tool error reporting [Florian; #2391]
* Improve handling of scale-factor changes [Georges; !1176]
* Tone down weekend days with events in calendar [Jakub; #2588]
* Fix showing bluetooth submenu when devices were set up [Florian; !1174]
* Add support for parental controls filtering [Philip W.; !465]
* Provide alternative extension templates [Florian; !812]
* Improve weather section's empty state [Mariana; #2179]
* Fix translations of folder names [Florian; #2623]
* Drop Tweener [Jonas Å.; !1200]
* Match ASCII alternatives of system actions [Will; #2688]
* Fix delay on lock screen after entering wrong password [Jonas D.; #2655]
* Use globalThis instead of window [Andy; #2322]
* Inhibit remote access when disabled by session mode [Jonas Å.; !1210]
* Improve calendar-server performance [Milan; #1875]
* Add gnome-shell-extension-prefs wrapper for compatibility [Florian; !1220]
* Fix stuck lock screen after unlock [Jonas D., Florian; #2446]
* Fixed crashes [Jonas D., Florian, Carlos; #2584, #2625, !1223, !1218]
* Misc. bug fixes and cleanups [Florian, Jonas Å., Marco, Andre, Georges,
Jonas D., Jan, Philip Ch.,, Xiaoguang, Will, Jordan, Matthew, qarmin;
!1126, !1155, !1156, !1165, !1168, !1169, #2551, #2563, !1172, !1175, !1179,
!1160, #2562, #2578, !1184, #2559, !1186, #2607, !1191, !1194, !1199, !1203,
#2649, #2628, !1205, !1206, !1208, !1207, !1211, !1214, !1213, !1192, !1217,
!1219, #1615, #2691, !1094, !1177]
Contributors:
Marco Trevisan (Treviño), Philip Chimento, Milan Crha, Jonas Dreßler,
Carlos Garnacho, Andy Holmes, Matthew Leeds, Andre Moreira Magalhaes,
Florian Müllner, Georges Basile Stavracas Neto, Jordan Petridis,
Mariana Picolo, Jakub Steiner, Will Thompson, Jan Tojnar, Xiaoguang Wang,
Philip Withnall, qarmin, Jonas Ådahl
Translators:
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Danial Behzadi [fa],
Jiri Grönroos [fi], Ibai Oihanguren Sala [eu], Марко Костић [sr],
Rūdolfs Mazurs [lv], Yuri Chornoivan [uk], Carmen Bianca BAKKER [eo],
Dingzhong Chen [zh_CN], Rafael Fontenelle [pt_BR], Petr Kovář [cs],
Asier Sarasua Garmendia [eu], Daniel Mustieles [es], Emin Tufan Çetin [tr]
3.36.0
======
* Fix off-by-1900 error in date conversions [Florian; !1061]

View File

@ -1,12 +1,19 @@
<node>
<interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
<method name="SetTimeRange">
<arg type="x" name="since" direction="in"/>
<arg type="x" name="until" direction="in"/>
<arg type="b" name="force_reload" direction="in"/>
</method>
<signal name="EventsAddedOrUpdated">
<arg type="a(ssbxxa{sv})" name="events" direction="out"/>
</signal>
<signal name="EventsRemoved">
<arg type="as" name="ids" direction="out"/>
</signal>
<signal name="ClientDisappeared">
<arg type="s" name="source_uid" direction="out"/>
</signal>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>

View File

@ -2,7 +2,6 @@
<gresources>
<gresource prefix="/org/gnome/shell/dbus-interfaces">
<file preprocess="xml-stripblanks">net.hadess.SensorProxy.xml</file>
<file preprocess="xml-stripblanks">net.hadess.SwitcherooControl.xml</file>
<file preprocess="xml-stripblanks">org.freedesktop.Application.xml</file>
<file preprocess="xml-stripblanks">org.freedesktop.bolt1.Device.xml</file>
<file preprocess="xml-stripblanks">org.freedesktop.bolt1.Manager.xml</file>

View File

@ -6,6 +6,7 @@
<file>checkbox-off-focused.svg</file>
<file>checkbox-off.svg</file>
<file>checkbox.svg</file>
<file alias="icons/color-pick.svg">color-pick.svg</file>
<file>dash-placeholder.svg</file>
<file>gnome-shell.css</file>
<file>gnome-shell-high-contrast.css</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M6.5 1.031c-.371 0-.742-.035-1.11.016-.367.05-.73.203-.972.476-.125.141-.215.309-.266.485-.047.18-.054.367-.02.55.032.184.102.356.192.516.09.164.203.309.317.457L5 4H2a1.8 1.8 0 00-.41.035.791.791 0 00-.36.195.791.791 0 00-.195.36C1 4.723 1 4.863 1 5v2.75l.77-.344c.265-.117.542-.23.832-.242.289-.016.586.074.812.254.227.18.383.441.465.723.082.277.101.57.121.859.02.316.04.637-.016.95-.058.312-.199.616-.43.831a1.264 1.264 0 01-.874.32c-.317-.007-.618-.128-.91-.257L1 10.5V14c0 .137.004.277.035.41a.791.791 0 00.195.36c.098.097.227.16.36.195.133.035.273.035.41.035h3l-.328-.68c-.14-.293-.274-.597-.29-.922-.015-.32.095-.652.31-.894.214-.242.523-.39.84-.453.316-.067.644-.059.968-.059.324 0 .652-.008.969.059.316.062.625.21.84.453.214.242.324.574.308.894-.015.325-.148.63-.289.922L8 15h3a1.8 1.8 0 00.41-.035.791.791 0 00.36-.195.791.791 0 00.195-.36C12 14.277 12 14.137 12 14v-3.563l.703.297c.29.125.59.239.902.246.313.004.63-.101.864-.308.238-.203.386-.496.46-.8C15 9.565 15 9.25 15 8.937c0-.313 0-.63-.07-.934-.075-.305-.223-.598-.461-.8a1.288 1.288 0 00-.864-.31c-.312.008-.613.122-.902.247L12 7.437V5a1.8 1.8 0 00-.035-.41.791.791 0 00-.195-.36.791.791 0 00-.36-.195C11.277 4 11.137 4 11 4H8l.36-.469c.113-.148.226-.293.316-.457.09-.16.16-.332.191-.515a1.248 1.248 0 00-.02-.551 1.256 1.256 0 00-.265-.485c-.242-.273-.605-.425-.973-.476-.367-.05-.738-.016-1.109-.016zm0 0" fill="#474747"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

1
data/icons/meson.build Normal file
View File

@ -0,0 +1 @@
install_subdir('hicolor', install_dir: icondir)

View File

@ -1,5 +1,6 @@
desktop_files = [
'org.gnome.Shell.desktop',
'org.gnome.Shell.Extensions.desktop',
]
service_files = []
@ -42,6 +43,7 @@ endforeach
subdir('dbus-interfaces')
subdir('icons')
subdir('theme')
data_resources = [

View File

@ -0,0 +1,10 @@
[Desktop Entry]
Type=Application
# Keep in sync with subprojects/extensions-app
Name=Extensions
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gnome.Shell.Extensions
# Never launch this, just provide name+icon to portal dialog
Exec=false
OnlyShowIn=GNOME;
NoDisplay=true

94
data/theme/color-pick.svg Normal file
View File

@ -0,0 +1,94 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5.4116011mm"
height="5.1374583mm"
viewBox="0 0 5.4116011 5.1374583"
version="1.1"
id="svg5595"
inkscape:version="0.92.4 (unknown)"
sodipodi:docname="color-pick.svg">
<defs
id="defs5589">
<filter
inkscape:collect="always"
x="-0.10291173"
width="1.2058235"
y="-0.065432459"
height="1.1308649"
id="filter5601"
style="color-interpolation-filters:sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.610872"
id="feGaussianBlur5603" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="39.387731"
inkscape:cy="12.554326"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5592">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-103.12753,-146.26461)">
<circle
r="8.4810486"
cy="9.82623"
cx="10.226647"
id="circle7584"
style="color:#000000;display:inline;overflow:visible;opacity:0.6;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;filter:url(#filter5601)"
transform="matrix(0.26458333,0,0,0.26458333,103.12753,146.26461)" />
<path
style="color:#000000;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.26399338;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
d="m 108.07728,148.64122 c 0,1.2393 -1.00465,2.24394 -2.24395,2.24394 -1.23929,0 -2.24716,-1.00465 -2.25221,-2.24394 l -0.009,-2.24458 2.26136,6.4e-4 c 1.2393,3.4e-4 2.24395,1.00464 2.24395,2.24394 z"
id="path7523-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssscss" />
<circle
style="color:#000000;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#50dbb5;fill-opacity:1;stroke:none;stroke-width:0.36885914;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
id="path7482-1"
cx="105.83707"
cy="148.64352"
r="1.844296" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -14,8 +14,6 @@ $app_icon_padding: 24px;
}
}
//.app-display { spacing: 20px; }
/* App Icons */
$app_grid_fg_color: #fff;
@ -123,15 +121,11 @@ $app_grid_fg_color: #fff;
}
// Some hacks I don't even know
.all-apps,
.frequent-apps > StBoxLayout {
.all-apps {
// horizontal padding to make sure scrollbars or dash don't overlap content
padding: 0px 88px 10px 88px;
}
// Label when no frequent apps
.no-frequent-applications-label { @extend %status_text; }
// shutdown and other actions in the grid
.system-action-icon {
background-color: rgba(0,0,0,0.8);
@ -139,44 +133,3 @@ $app_grid_fg_color: #fff;
border-radius: 99px;
icon-size: $app_icon_size * 0.5;
}
/* Frequent | All toggle */
// container
.app-view-controls {
padding-bottom: 32px;
}
// buttons
.app-view-control {
padding: 4px 32px;
margin: 0 4px;
&, &:hover, &:checked {
@include button(undecorated);
color: darken($osd_fg_color, 25%);
}
&:hover {
color: $osd_fg_color;
box-shadow: inset 0 -2px darken($osd_fg_color, 25%);
}
&:active {
box-shadow: inset 0 -2px $osd_fg_color;
}
&:checked {
color: $osd_fg_color;
box-shadow: inset 0 -2px $selected_bg_color;
}
&:first-child {
border-right-width: 0;
border-radius: 0;
}
&:last-child {
border-radius: 0;
}
}

View File

@ -153,9 +153,11 @@
}
.calendar-day-with-events {
color: lighten($fg_color,10%);
font-weight: bold;
background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg");
&.calendar-work-day {
color: lighten($fg_color,10%);
font-weight: bold;
}
}
.calendar-other-month-day {
@ -202,7 +204,7 @@
.world-clocks-time {
font-weight: bold;
color: $fg_color;
font-feature-settings: "lnum";
font-feature-settings: "tnum";
@include fontsize($base_font_size);
text-align: right;
}

View File

@ -1,5 +1,7 @@
/* Looking Glass */
$text_fg_color: #ccc;
// Dialog
#LookingGlassDialog {
background-color: $osd_bg_color;
@ -52,6 +54,11 @@
&:hover { color: lighten($link_color, 10%); }
&:active { color: darken($link_color, 10%); }
}
.actor-link {
color: $text_fg_color;
&:hover { color: lighten($text_fg_color, 20%); }
&:active { color: darken($text_fg_color, 20%); }
}
}
.lg-completions-text {

View File

@ -54,6 +54,10 @@
@extend %status_text;
}
.grid-search-results {
spacing: $base_spacing * 6;
}
// Search results with icons
.grid-search-result {
@extend %app-well-app;

View File

@ -9,6 +9,8 @@ const { ServiceImplementation } = imports.dbusService;
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
var NotificationDaemon = class extends ServiceImplementation {
constructor() {
super(NotificationsIface, '/org/freedesktop/Notifications');
@ -42,7 +44,15 @@ var NotificationDaemon = class extends ServiceImplementation {
null, null);
}
NotifyAsync(params, invocation) {
async NotifyAsync(params, invocation) {
const pid = await this._getSenderPid(invocation.get_sender());
const hints = params[6];
params[6] = {
...hints,
'sender-pid': new GLib.Variant('u', pid),
};
this._proxy.NotifyRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
@ -77,4 +87,19 @@ var NotificationDaemon = class extends ServiceImplementation {
invocation.return_value(new GLib.Variant('(ssss)', res));
});
}
async _getSenderPid(sender) {
const res = await Gio.DBus.session.call(
'org.freedesktop.DBus',
'/',
'org.freedesktop.DBus',
'GetConnectionUnixProcessID',
new GLib.Variant('(s)', [sender]),
new GLib.VariantType('(u)'),
Gio.DBusCallFlags.NONE,
-1,
null);
const [pid] = res.deepUnpack();
return pid;
}
};

View File

@ -184,7 +184,7 @@ var AuthPrompt = GObject.registerClass({
});
this._defaultButtonWell.add_constraint(new Clutter.BindConstraint({
source: this.cancelButton,
coordinate: Clutter.BindCoordinate.SIZE,
coordinate: Clutter.BindCoordinate.WIDTH,
}));
this._mainBox.add_child(this._defaultButtonWell);
@ -424,7 +424,13 @@ var AuthPrompt = GObject.registerClass({
}
updateSensitivity(sensitive) {
if (this._entry.reactive === sensitive)
return;
this._entry.reactive = sensitive;
if (sensitive)
this._entry.grab_key_focus();
}
vfunc_hide() {

View File

@ -589,8 +589,8 @@ var LoginDialog = GObject.registerClass({
return actorBox;
}
vfunc_allocate(dialogBox, flags) {
this.set_allocation(dialogBox, flags);
vfunc_allocate(dialogBox) {
this.set_allocation(dialogBox);
let themeNode = this.get_theme_node();
dialogBox = themeNode.get_content_box(dialogBox);
@ -719,19 +719,19 @@ var LoginDialog = GObject.registerClass({
// Finally hand out the allocations
if (bannerAllocation)
this._bannerView.allocate(bannerAllocation, flags);
this._bannerView.allocate(bannerAllocation);
if (authPromptAllocation)
this._authPrompt.allocate(authPromptAllocation, flags);
this._authPrompt.allocate(authPromptAllocation);
if (userSelectionAllocation)
this._userSelectionBox.allocate(userSelectionAllocation, flags);
this._userSelectionBox.allocate(userSelectionAllocation);
if (logoAllocation)
this._logoBin.allocate(logoAllocation, flags);
this._logoBin.allocate(logoAllocation);
if (sessionMenuButtonAllocation)
this._sessionMenuButton.allocate(sessionMenuButtonAllocation, flags);
this._sessionMenuButton.allocate(sessionMenuButtonAllocation);
}
_ensureUserListLoaded() {
@ -810,12 +810,13 @@ var LoginDialog = GObject.registerClass({
return;
this._logoBin.destroy_all_children();
if (this._logoFile && this._logoBin.resource_scale > 0) {
const [valid, resourceScale] = this._logoBin.get_resource_scale();
if (this._logoFile && valid) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, -1,
scaleFactor,
this._logoBin.resource_scale));
resourceScale));
}
}

View File

@ -23,6 +23,7 @@
<file>misc/modemManager.js</file>
<file>misc/objectManager.js</file>
<file>misc/params.js</file>
<file>misc/parentalControlsManager.js</file>
<file>misc/permissionStore.js</file>
<file>misc/smartcardManager.js</file>
<file>misc/systemActions.js</file>
@ -101,7 +102,6 @@
<file>ui/swipeTracker.js</file>
<file>ui/switcherPopup.js</file>
<file>ui/switchMonitor.js</file>
<file>ui/tweener.js</file>
<file>ui/unlockDialog.js</file>
<file>ui/userWidget.js</file>
<file>ui/viewSelector.js</file>

View File

@ -171,13 +171,13 @@ var IBusManager = class {
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
this._updateReadiness();
try {
// If an engine is already active we need to get its properties
const engine =
await this._ibus.get_global_engine_async(-1, this._cancellable);
this._engineChanged(this._ibus, engine.get_name());
this._updateReadiness();
} catch (e) {
}
}

View File

@ -24,8 +24,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
[expr_, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter(
attr => attr.slice(0, attrHead.length) == attrHead
);
attr => attr.slice(0, attrHead.length) === attrHead);
}
// Look for the empty expression or partially entered words
@ -34,8 +33,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
if (text == '' || matches) {
[expr_, attrHead] = matches;
methods = globalCompletionList.filter(
attr => attr.slice(0, attrHead.length) == attrHead
);
attr => attr.slice(0, attrHead.length) === attrHead);
}
}

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
const { GLib, GnomeDesktop, Meta } = imports.gi;
const { GLib, GnomeDesktop } = imports.gi;
const Main = imports.ui.main;
@ -62,11 +62,11 @@ var KeyboardManager = class {
return;
this._currentKeymap = { layouts, variants, options };
Meta.get_backend().set_keymap(layouts, variants, options);
global.backend.set_keymap(layouts, variants, options);
}
_applyLayoutGroupIndex(idx) {
Meta.get_backend().lock_layout_group(idx);
global.backend.lock_layout_group(idx);
}
apply(id) {

View File

@ -0,0 +1,146 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// Copyright (C) 2018, 2019, 2020 Endless Mobile, Inc.
//
// This is a GNOME Shell component to wrap the interactions over
// D-Bus with the malcontent library.
//
// Licensed under the GNU General Public License Version 2
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/* exported getDefault */
const { Gio, GObject, Shell } = imports.gi;
// We require libmalcontent ≥ 0.6.0
const HAVE_MALCONTENT = imports.package.checkSymbol(
'Malcontent', '0', 'ManagerGetValueFlags');
var Malcontent = null;
if (HAVE_MALCONTENT) {
Malcontent = imports.gi.Malcontent;
Gio._promisify(Malcontent.Manager.prototype, 'get_app_filter_async', 'get_app_filter_finish');
}
let _singleton = null;
function getDefault() {
if (_singleton === null)
_singleton = new ParentalControlsManager();
return _singleton;
}
// A manager class which provides cached access to the constructing users
// parental controls settings. Its possible for the users parental controls
// to change at runtime if the Parental Controls application is used by an
// administrator from within the users session.
var ParentalControlsManager = GObject.registerClass({
Signals: {
'app-filter-changed': {},
},
}, class ParentalControlsManager extends GObject.Object {
_init() {
super._init();
this._initialized = false;
this._disabled = false;
this._appFilter = null;
this._initializeManager();
}
async _initializeManager() {
if (!HAVE_MALCONTENT) {
log('Skipping parental controls support as its disabled');
this._initialized = true;
this.emit('app-filter-changed');
return;
}
log(`Getting parental controls for user ${Shell.util_get_uid()}`);
try {
const connection = await Gio.DBus.get(Gio.BusType.SYSTEM, null);
this._manager = new Malcontent.Manager({ connection });
this._appFilter = await this._manager.get_app_filter_async(
Shell.util_get_uid(),
Malcontent.ManagerGetValueFlags.NONE,
null);
} catch (e) {
if (e.matches(Malcontent.ManagerError, Malcontent.ManagerError.DISABLED)) {
log('Parental controls globally disabled');
this._disabled = true;
} else {
logError(e, 'Failed to get parental controls settings');
return;
}
}
this._manager.connect('app-filter-changed', this._onAppFilterChanged.bind(this));
// Signal initialisation is complete.
this._initialized = true;
this.emit('app-filter-changed');
}
async _onAppFilterChanged(manager, uid) {
// Emit 'changed' signal only if app-filter is changed for currently logged-in user.
let currentUid = Shell.util_get_uid();
if (currentUid !== uid)
return;
try {
this._appFilter = await this._manager.get_app_filter_async(
currentUid,
Malcontent.ManagerGetValueFlags.NONE,
null);
this.emit('app-filter-changed');
} catch (e) {
// Log an error and keep the old app filter.
logError(e, `Failed to get new MctAppFilter for uid ${Shell.util_get_uid()} on app-filter-changed`);
}
}
get initialized() {
return this._initialized;
}
// Calculate whether the given app (a Gio.DesktopAppInfo) should be shown
// on the desktop, in search results, etc. The app should be shown if:
// - The .desktop file doesnt say it should be hidden.
// - The executable from the .desktop files Exec line isnt blacklisted in
// the users parental controls.
// - None of the flatpak app IDs from the X-Flatpak and the
// X-Flatpak-RenamedFrom lines are blacklisted in the users parental
// controls.
shouldShowApp(appInfo) {
// Quick decision?
if (!appInfo.should_show())
return false;
// Are parental controls enabled (at configure time or runtime)?
if (!HAVE_MALCONTENT || this._disabled)
return true;
// Have we finished initialising yet?
if (!this.initialized) {
log(`Warning: Hiding app because parental controls not yet initialised: ${appInfo.get_id()}`);
return false;
}
return this._appFilter.is_appinfo_allowed(appInfo);
}
});

View File

@ -83,13 +83,17 @@ const SystemActions = GObject.registerClass({
this._canHavePowerOff = true;
this._canHaveSuspend = true;
function tokenizeKeywords(keywords) {
return keywords.split(';').map(keyword => GLib.str_tokenize_and_fold(keyword, null)).flat(2);
}
this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID, {
// Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _('power off;shutdown;reboot;restart;halt;stop').split(/[; ]/),
keywords: tokenizeKeywords(_('power off;shutdown;reboot;restart;halt;stop')),
available: false,
});
this._actions.set(LOCK_SCREEN_ACTION_ID, {
@ -97,15 +101,15 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(/[; ]/),
keywords: tokenizeKeywords(_('lock screen')),
available: false,
});
this._actions.set(LOGOUT_ACTION_ID, {
// Translators: The name of the logout action in search
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
iconName: 'system-log-out-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;log out;sign off").split(/[; ]/),
keywords: tokenizeKeywords(_('logout;log out;sign off')),
available: false,
});
this._actions.set(SUSPEND_ACTION_ID, {
@ -113,7 +117,7 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/),
keywords: tokenizeKeywords(_('suspend;sleep')),
available: false,
});
this._actions.set(SWITCH_USER_ACTION_ID, {
@ -121,14 +125,14 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(/[; ]/),
keywords: tokenizeKeywords(_('switch user')),
available: false,
});
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
name: '',
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;unlock orientation;screen;rotation").split(/[; ]/),
keywords: tokenizeKeywords(_('lock orientation;unlock orientation;screen;rotation')),
available: false,
});
@ -277,7 +281,7 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map(term => term.toLowerCase());
terms = terms.map(term => GLib.str_tokenize_and_fold(term, null)[0]);
let results = [];

View File

@ -68,8 +68,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._items = this._switcherList.icons;
}
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
vfunc_allocate(box) {
super.vfunc_allocate(box);
// Allocate the thumbnails
// We try to avoid overflowing the screen so we base the resulting size on
@ -102,7 +102,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags);
this._thumbnails.allocate(childBox);
}
}
@ -681,8 +681,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// Cache the window list now; we don't handle dynamic changes here,
// and we don't want to be continually retrieving it
appIcon.cachedWindows = allWindows.filter(
w => windowTracker.get_window_app(w) == appIcon.app
);
w => windowTracker.get_window_app(w) === appIcon.app);
if (appIcon.cachedWindows.length > 0)
this._addIcon(appIcon);
}
@ -750,9 +749,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
return super.vfunc_get_preferred_height(forWidth);
}
vfunc_allocate(box, flags) {
vfunc_allocate(box) {
// Allocate the main list items
super.vfunc_allocate(box, flags);
super.vfunc_allocate(box);
let contentBox = this.get_theme_node().get_content_box(box);
@ -767,7 +766,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y1 = contentBox.y1 + itemBox.y2 + arrowHeight;
childBox.y2 = childBox.y1 + arrowHeight;
this._arrows[i].allocate(childBox, flags);
this._arrows[i].allocate(childBox);
}
}
@ -1057,28 +1056,28 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
return [minHeight, natHeight];
}
vfunc_allocate(box, flags) {
vfunc_allocate(box) {
let themeNode = this.get_theme_node();
let contentBox = themeNode.get_content_box(box);
const labelHeight = this._label.height;
const totalLabelHeight =
labelHeight + themeNode.get_padding(St.Side.BOTTOM);
let childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM);
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y1 = box.y1;
childBox.y2 = box.y2 - totalLabelHeight;
super.vfunc_allocate(childBox, flags);
box.y2 -= totalLabelHeight;
super.vfunc_allocate(box);
// Hooking up the parent vfunc will call this.set_allocation() with
// the height without the label height, so call it again with the
// correct size here.
this.set_allocation(box, flags);
box.y2 += totalLabelHeight;
this.set_allocation(box);
const childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - labelHeight;
this._label.allocate(childBox);
}
highlight(index, justOutline) {

View File

@ -15,8 +15,7 @@ class Animation extends St.Bin {
const themeContext = St.ThemeContext.get_for_stage(global.stage);
super._init({
width: width * themeContext.scale_factor,
height: height * themeContext.scale_factor,
style: `width: ${width}px; height: ${height}px;`,
});
this.connect('destroy', this._onDestroy.bind(this));

View File

@ -10,6 +10,7 @@ const GrabHelper = imports.ui.grabHelper;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const PageIndicators = imports.ui.pageIndicators;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const PopupMenu = imports.ui.popupMenu;
const Search = imports.ui.search;
const SwipeTracker = imports.ui.swipeTracker;
@ -17,8 +18,6 @@ const Params = imports.misc.params;
const Util = imports.misc.util;
const SystemActions = imports.misc.systemActions;
const { loadInterfaceXML } = imports.misc.fileUtils;
var MENU_POPUP_TIMEOUT = 600;
var MAX_COLUMNS = 6;
var MIN_COLUMNS = 4;
@ -30,12 +29,11 @@ var INACTIVE_GRID_OPACITY = 77;
var INACTIVE_GRID_OPACITY_ANIMATION_TIME = 240;
var FOLDER_SUBICON_FRACTION = .4;
var MIN_FREQUENT_APPS_COUNT = 3;
var VIEWS_SWITCH_TIME = 400;
var VIEWS_SWITCH_ANIMATION_DELAY = 100;
var PAGE_SWITCH_TIME = 250;
var SCROLL_TIMEOUT_TIME = 150;
var APP_ICON_SCALE_IN_TIME = 500;
var APP_ICON_SCALE_IN_DELAY = 700;
@ -45,11 +43,6 @@ const FOLDER_DIALOG_ANIMATION_TIME = 200;
const OVERSHOOT_THRESHOLD = 20;
const OVERSHOOT_TIMEOUT = 1000;
const SWITCHEROO_BUS_NAME = 'net.hadess.SwitcherooControl';
const SWITCHEROO_OBJECT_PATH = '/net/hadess/SwitcherooControl';
const SwitcherooProxyInterface = loadInterfaceXML('net.hadess.SwitcherooControl');
const SwitcherooProxy = Gio.DBusProxy.makeProxyWrapper(SwitcherooProxyInterface);
let discreteGpuAvailable = false;
function _getCategories(info) {
@ -114,7 +107,8 @@ function _findBestFolderName(apps) {
}, commonCategories);
for (let category of commonCategories) {
let translated = Shell.util_get_translated_folder_name(category);
const directory = '%s.directory'.format(category);
const translated = Shell.util_get_translated_folder_name(directory);
if (translated !== null)
return translated;
}
@ -144,11 +138,7 @@ var BaseAppView = GObject.registerClass({
padWithSpacing: true,
}, true);
if (this.use_pagination)
this._grid = new IconGrid.PaginatedIconGrid(gridParams);
else
this._grid = new IconGrid.IconGrid(gridParams);
this._grid = new IconGrid.IconGrid(gridParams);
this._grid.connect('child-focused', (grid, actor) => {
this._childFocused(actor);
});
@ -161,6 +151,12 @@ var BaseAppView = GObject.registerClass({
this._animateLaterId = 0;
this._viewLoadedHandlerId = 0;
this._viewIsReady = false;
// Filter the apps through the users parental controls.
this._parentalControlsManager = ParentalControlsManager.getDefault();
this._parentalControlsManager.connect('app-filter-changed', () => {
this._redisplay();
});
}
_childFocused(_actor) {
@ -324,24 +320,46 @@ var BaseAppView = GObject.registerClass({
}
});
var AllView = GObject.registerClass({
}, class AllView extends BaseAppView {
var AppDisplay = GObject.registerClass(
class AppDisplay extends BaseAppView {
_init() {
super._init({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
use_pagination: true,
});
this._grid._delegate = this;
this._stack = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_actor(this._stack);
let box = new St.BoxLayout({
vertical: true,
y_align: Clutter.ActorAlign.START,
});
box.add_child(this._grid);
this._scrollView = new St.ScrollView({
style_class: 'all-apps',
x_expand: true,
y_expand: true,
reactive: true,
});
this.add_actor(this._scrollView);
this._grid._delegate = this;
this._scrollView.add_actor(box);
this._stack.add_actor(this._scrollView);
this._eventBlocker = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
visible: false,
});
this._stack.add_actor(this._eventBlocker);
this._scrollView.set_policy(St.PolicyType.NEVER,
St.PolicyType.EXTERNAL);
@ -362,24 +380,7 @@ var AllView = GObject.registerClass({
this._folderIcons = [];
this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
let box = new St.BoxLayout({
vertical: true,
y_align: Clutter.ActorAlign.START,
});
this._grid.currentPage = 0;
this._stack.add_actor(this._grid);
this._eventBlocker = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
visible: false,
});
this._stack.add_actor(this._eventBlocker);
box.add_actor(this._stack);
this._scrollView.add_actor(box);
this._scrollView.connect('scroll-event', this._onScroll.bind(this));
@ -432,6 +433,29 @@ var AllView = GObject.registerClass({
Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this._switcherooNotifyId = global.connect('notify::switcheroo-control',
() => this._updateDiscreteGpuAvailable());
this._updateDiscreteGpuAvailable();
}
_updateDiscreteGpuAvailable() {
this._switcherooProxy = global.get_switcheroo_control();
if (this._switcherooProxy) {
let prop = this._switcherooProxy.get_cached_property('HasDualGpu');
discreteGpuAvailable = prop ? prop.unpack() : false;
} else {
discreteGpuAvailable = false;
}
}
vfunc_allocate(box) {
box = this.get_theme_node().get_content_box(box);
let availWidth = box.get_width();
let availHeight = box.get_height();
this.adaptToSize(availWidth, availHeight);
super.vfunc_allocate(box);
}
_onDestroy() {
@ -514,7 +538,7 @@ var AllView = GObject.registerClass({
} catch (e) {
return false;
}
return appInfo.should_show();
return this._parentalControlsManager.shouldShowApp(appInfo);
});
let apps = this._appInfoList.map(app => app.get_id());
@ -624,7 +648,7 @@ var AllView = GObject.registerClass({
this._grid.currentPage = pageNumber;
// Tween the change between pages.
// Animate the change between pages.
this._adjustment.ease(this._grid.getPageY(this._grid.currentPage), {
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
duration: animate ? PAGE_SWITCH_TIME : 0,
@ -651,12 +675,11 @@ var AllView = GObject.registerClass({
this._canScroll = false;
this._scrollTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
PAGE_SWITCH_TIME, () => {
SCROLL_TIMEOUT_TIME, () => {
this._canScroll = true;
this._scrollTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
);
});
return Clutter.EVENT_STOP;
}
@ -947,301 +970,6 @@ var AllView = GObject.registerClass({
}
});
var FrequentView = GObject.registerClass(
class FrequentView extends BaseAppView {
_init() {
super._init({
style_class: 'frequent-apps',
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
}, { fillParent: true });
this._noFrequentAppsLabel = new St.Label({ text: _("Frequently used applications will appear here"),
style_class: 'no-frequent-applications-label',
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this._grid.y_expand = true;
this.add_actor(this._grid);
this.add_actor(this._noFrequentAppsLabel);
this._noFrequentAppsLabel.hide();
this._usage = Shell.AppUsage.get_default();
}
vfunc_map() {
this._redisplay();
super.vfunc_map();
}
hasUsefulData() {
return this._usage.get_most_used().length >= MIN_FREQUENT_APPS_COUNT;
}
_compareItems() {
// The FrequentView does not need to be sorted alphabetically
return 0;
}
_loadApps() {
let apps = [];
let mostUsed = this._usage.get_most_used();
let hasUsefulData = this.hasUsefulData();
this._noFrequentAppsLabel.visible = !hasUsefulData;
if (!hasUsefulData)
return [];
// Allow dragging of the icon only if the Dash would accept a drop to
// change favorite-apps. There are no other possible drop targets from
// the app picker, so there's no other need for a drag to start,
// at least on single-monitor setups.
// This also disables drag-to-launch on multi-monitor setups,
// but we hope that is not used much.
let favoritesWritable = global.settings.is_writable('favorite-apps');
for (let i = 0; i < mostUsed.length; i++) {
if (!mostUsed[i].get_app_info().should_show())
continue;
let appIcon = this._items.get(mostUsed[i].get_id());
if (!appIcon) {
appIcon = new AppIcon(mostUsed[i], {
isDraggable: favoritesWritable,
});
}
apps.push(appIcon);
}
return apps;
}
// Called before allocation to calculate dynamic spacing
adaptToSize(width, height) {
let box = new Clutter.ActorBox();
box.x1 = box.y1 = 0;
box.x2 = width;
box.y2 = height;
box = this.get_theme_node().get_content_box(box);
box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this._grid.adaptToSize(availWidth, availHeight);
}
});
var Views = {
FREQUENT: 0,
ALL: 1,
};
var ControlsBoxLayout = GObject.registerClass(
class ControlsBoxLayout extends Clutter.BoxLayout {
/*
* Override the BoxLayout behavior to use the maximum preferred width of all
* buttons for each child
*/
vfunc_get_preferred_width(container, forHeight) {
let maxMinWidth = 0;
let maxNaturalWidth = 0;
for (let child = container.get_first_child();
child;
child = child.get_next_sibling()) {
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
maxMinWidth = Math.max(maxMinWidth, minWidth);
maxNaturalWidth = Math.max(maxNaturalWidth, natWidth);
}
let childrenCount = container.get_n_children();
let totalSpacing = this.spacing * (childrenCount - 1);
return [maxMinWidth * childrenCount + totalSpacing,
maxNaturalWidth * childrenCount + totalSpacing];
}
});
var ViewStackLayout = GObject.registerClass({
Signals: { 'allocated-size-changed': { param_types: [GObject.TYPE_INT,
GObject.TYPE_INT] } },
}, class ViewStackLayout extends Clutter.BinLayout {
vfunc_allocate(actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
// Prepare children of all views for the upcoming allocation, calculate all
// the needed values to adapt available size
this.emit('allocated-size-changed', availWidth, availHeight);
super.vfunc_allocate(actor, box, flags);
}
});
var AppDisplay = GObject.registerClass(
class AppDisplay extends St.BoxLayout {
_init() {
super._init({
style_class: 'app-display',
vertical: true,
x_expand: true,
y_expand: true,
});
this._privacySettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.privacy' });
this._privacySettings.connect('changed::remember-app-usage',
this._updateFrequentVisibility.bind(this));
this._views = [];
let view, button;
view = new FrequentView();
button = new St.Button({ label: _("Frequent"),
style_class: 'app-view-control button',
can_focus: true,
x_expand: true });
this._views[Views.FREQUENT] = { view, 'control': button };
view = new AllView();
button = new St.Button({ label: _("All"),
style_class: 'app-view-control button',
can_focus: true,
x_expand: true });
this._views[Views.ALL] = { view, 'control': button };
this._viewStackLayout = new ViewStackLayout();
this._viewStack = new St.Widget({ x_expand: true, y_expand: true,
layout_manager: this._viewStackLayout });
this._viewStackLayout.connect('allocated-size-changed', this._onAllocatedSizeChanged.bind(this));
this.add_actor(this._viewStack);
let layout = new ControlsBoxLayout({ homogeneous: true });
this._controls = new St.Widget({
style_class: 'app-view-controls',
layout_manager: layout,
x_align: Clutter.ActorAlign.CENTER,
});
this._controls.connect('notify::mapped', () => {
// controls are faded either with their parent or
// explicitly in animate(); we can't know how they'll be
// shown next, so make sure to restore their opacity
// when they are hidden
if (this._controls.mapped)
return;
this._controls.remove_all_transitions();
this._controls.opacity = 255;
});
layout.hookup_style(this._controls);
this.add_actor(new St.Bin({ child: this._controls }));
for (let i = 0; i < this._views.length; i++) {
this._viewStack.add_actor(this._views[i].view);
this._controls.add_actor(this._views[i].control);
let viewIndex = i;
this._views[i].control.connect('clicked', () => {
this._showView(viewIndex);
global.settings.set_uint('app-picker-view', viewIndex);
});
}
let initialView = Math.min(global.settings.get_uint('app-picker-view'),
this._views.length - 1);
let frequentUseful = this._views[Views.FREQUENT].view.hasUsefulData();
if (initialView == Views.FREQUENT && !frequentUseful)
initialView = Views.ALL;
this._showView(initialView);
this._updateFrequentVisibility();
Gio.DBus.system.watch_name(SWITCHEROO_BUS_NAME,
Gio.BusNameWatcherFlags.NONE,
this._switcherooProxyAppeared.bind(this),
() => {
this._switcherooProxy = null;
this._updateDiscreteGpuAvailable();
});
}
_updateDiscreteGpuAvailable() {
if (!this._switcherooProxy)
discreteGpuAvailable = false;
else
discreteGpuAvailable = this._switcherooProxy.HasDualGpu;
}
_switcherooProxyAppeared() {
this._switcherooProxy = new SwitcherooProxy(Gio.DBus.system, SWITCHEROO_BUS_NAME, SWITCHEROO_OBJECT_PATH,
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._updateDiscreteGpuAvailable();
});
}
animate(animationDirection, onComplete) {
let currentView = this._views.filter(v => v.control.has_style_pseudo_class('checked')).pop().view;
// Animate controls opacity using iconGrid animation time, since
// it will be the time the AllView or FrequentView takes to show
// it entirely.
let finalOpacity;
if (animationDirection == IconGrid.AnimationDirection.IN) {
this._controls.opacity = 0;
finalOpacity = 255;
} else {
finalOpacity = 0;
}
this._controls.ease({
opacity: finalOpacity,
duration: IconGrid.ANIMATION_TIME_IN,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
});
currentView.animate(animationDirection, onComplete);
}
_showView(activeIndex) {
for (let i = 0; i < this._views.length; i++) {
if (i == activeIndex)
this._views[i].control.add_style_pseudo_class('checked');
else
this._views[i].control.remove_style_pseudo_class('checked');
let animationDirection = i == activeIndex
? IconGrid.AnimationDirection.IN
: IconGrid.AnimationDirection.OUT;
this._views[i].view.animateSwitch(animationDirection);
}
}
_updateFrequentVisibility() {
let enabled = this._privacySettings.get_boolean('remember-app-usage');
this._views[Views.FREQUENT].control.visible = enabled;
let visibleViews = this._views.filter(v => v.control.visible);
this._controls.visible = visibleViews.length > 1;
if (!enabled && this._views[Views.FREQUENT].view.visible)
this._showView(Views.ALL);
}
selectApp(id) {
this._showView(Views.ALL);
this._views[Views.ALL].view.selectApp(id);
}
_onAllocatedSizeChanged(actor, width, height) {
let box = new Clutter.ActorBox();
box.x1 = box.y1 = 0;
box.x2 = width;
box.y2 = height;
box = this._viewStack.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
for (let i = 0; i < this._views.length; i++)
this._views[i].view.adaptToSize(availWidth, availHeight);
}
});
var AppSearchProvider = class AppSearchProvider {
constructor() {
this._appSys = Shell.AppSystem.get_default();
@ -1250,6 +978,8 @@ var AppSearchProvider = class AppSearchProvider {
this.canLaunchSearch = false;
this._systemActions = new SystemActions.getDefault();
this._parentalControlsManager = ParentalControlsManager.getDefault();
}
getResultMetas(apps, callback) {
@ -1284,18 +1014,30 @@ var AppSearchProvider = class AppSearchProvider {
}
getInitialResultSet(terms, callback, _cancellable) {
// Defer until the parental controls manager is initialised, so the
// results can be filtered correctly.
if (!this._parentalControlsManager.initialized) {
let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
if (this._parentalControlsManager.initialized) {
this._parentalControlsManager.disconnect(initializedId);
this.getInitialResultSet(terms, callback, _cancellable);
}
});
return;
}
let query = terms.join(' ');
let groups = Shell.AppSystem.search(query);
let usage = Shell.AppUsage.get_default();
let results = [];
groups.forEach(group => {
group = group.filter(appID => {
const app = this._appSys.lookup_app(appID);
return app && app.app_info.should_show();
return app && this._parentalControlsManager.shouldShowApp(app.app_info);
});
results = results.concat(group.sort(
(a, b) => usage.compare(a, b)
));
(a, b) => usage.compare(a, b)));
});
results = results.concat(this._systemActions.getMatchingActions(terms));
@ -1430,7 +1172,7 @@ class FolderView extends BaseAppView {
if (!app)
return;
if (!app.get_app_info().should_show())
if (!this._parentalControlsManager.shouldShowApp(app.get_app_info()))
return;
if (apps.some(appIcon => appIcon.id == appId))
@ -1616,7 +1358,7 @@ var FolderIcon = GObject.registerClass({
return false;
let view = _getViewFromIcon(source);
if (!view || !(view instanceof AllView))
if (!view || !(view instanceof AppDisplay))
return false;
if (this._folder.get_strv('apps').includes(source.id))
@ -1938,7 +1680,7 @@ var AppFolderDialog = GObject.registerClass({
}
}
vfunc_allocate(box, flags) {
vfunc_allocate(box) {
let contentBox = this.get_theme_node().get_content_box(box);
contentBox = this._viewBox.get_theme_node().get_content_box(contentBox);
@ -1951,7 +1693,7 @@ var AppFolderDialog = GObject.registerClass({
this._view._grid.topPadding = 0;
super.vfunc_allocate(box, flags);
super.vfunc_allocate(box);
// We can only start zooming after receiving an allocation
if (this._needsZoomAndFade)
@ -2176,7 +1918,7 @@ var AppIcon = GObject.registerClass({
}
vfunc_leave_event(crossingEvent) {
let ret = super.vfunc_leave_event(crossingEvent);
const ret = super.vfunc_leave_event(crossingEvent);
this.fake_release();
this._removeMenuTimeout();
@ -2184,22 +1926,22 @@ var AppIcon = GObject.registerClass({
}
vfunc_button_press_event(buttonEvent) {
super.vfunc_button_press_event(buttonEvent);
const ret = super.vfunc_button_press_event(buttonEvent);
if (buttonEvent.button == 1) {
this._setPopupTimeout();
} else if (buttonEvent.button == 3) {
this.popupMenu();
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
return ret;
}
vfunc_touch_event(touchEvent) {
super.vfunc_touch_event(touchEvent);
const ret = super.vfunc_touch_event(touchEvent);
if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN)
this._setPopupTimeout();
return Clutter.EVENT_PROPAGATE;
return ret;
}
vfunc_clicked(button) {
@ -2368,7 +2110,7 @@ var AppIcon = GObject.registerClass({
return source != this &&
(source instanceof this.constructor) &&
(view instanceof AllView);
(view instanceof AppDisplay);
}
_setHoveringByDnd(hovering) {
@ -2469,14 +2211,12 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
this.removeAll();
let windows = this._source.app.get_windows().filter(
w => !w.skip_taskbar
);
w => !w.skip_taskbar);
if (windows.length > 0) {
this.addMenuItem(
/* Translators: This is the heading of a list of open windows */
new PopupMenu.PopupSeparatorMenuItem(_("Open Windows"))
);
new PopupMenu.PopupSeparatorMenuItem(_('Open Windows')));
}
windows.forEach(window => {
@ -2506,10 +2246,16 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
if (discreteGpuAvailable &&
this._source.app.state == Shell.AppState.STOPPED) {
this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card"));
this._onDiscreteGpuMenuItem.connect('activate', () => {
const appPrefersNonDefaultGPU = appInfo.get_boolean('PrefersNonDefaultGPU');
const gpuPref = appPrefersNonDefaultGPU
? Shell.AppLaunchGpu.DEFAULT
: Shell.AppLaunchGpu.DISCRETE;
this._onGpuMenuItem = this._appendMenuItem(appPrefersNonDefaultGPU
? _('Launch using Integrated Graphics Card')
: _('Launch using Discrete Graphics Card'));
this._onGpuMenuItem.connect('activate', () => {
this._source.animateLaunch();
this._source.app.launch(0, -1, true);
this._source.app.launch(0, -1, gpuPref);
this.emit('activate-window', null);
});
}

View File

@ -2,6 +2,7 @@
/* exported getAppFavorites */
const Shell = imports.gi.Shell;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const Signals = imports.signals;
const Main = imports.ui.main;
@ -12,6 +13,7 @@ const RENAMED_DESKTOP_IDS = {
'cheese.desktop': 'org.gnome.Cheese.desktop',
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
'empathy.desktop': 'org.gnome.Empathy.desktop',
'eog.desktop': 'org.gnome.eog.desktop',
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
'evolution.desktop': 'org.gnome.Evolution.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
@ -64,6 +66,13 @@ const RENAMED_DESKTOP_IDS = {
class AppFavorites {
constructor() {
// Filter the apps through the users parental controls.
this._parentalControlsManager = ParentalControlsManager.getDefault();
this._parentalControlsManager.connect('app-filter-changed', () => {
this.reload();
this.emit('changed');
});
this.FAVORITE_APPS_KEY = 'favorite-apps';
this._favorites = {};
global.settings.connect('changed::%s'.format(this.FAVORITE_APPS_KEY), this._onFavsChanged.bind(this));
@ -95,7 +104,7 @@ class AppFavorites {
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
let apps = ids.map(id => appSys.lookup_app(id))
.filter(app => app != null);
.filter(app => app !== null && this._parentalControlsManager.shouldShowApp(app.app_info));
this._favorites = {};
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
@ -134,6 +143,9 @@ class AppFavorites {
if (!app)
return false;
if (!this._parentalControlsManager.shouldShowApp(app.app_info))
return false;
let ids = this._getIds();
if (pos == -1)
ids.push(appId);

View File

@ -147,9 +147,8 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
_onDeviceSelected(dialog, device) {
let connection = this._dbusImpl.get_connection();
let info = this._dbusImpl.get_info();
let deviceName = Object.keys(AudioDevice).filter(
dev => AudioDevice[dev] == device
)[0].toLowerCase();
const deviceName = Object.keys(AudioDevice)
.filter(dev => AudioDevice[dev] === device)[0].toLowerCase();
connection.emit_signal(this._audioSelectionDialog._sender,
this._dbusImpl.get_object_path(),
info ? info.name : null,

View File

@ -30,8 +30,8 @@ var BarLevel = GObject.registerClass({
accessible_role: Atk.Role.LEVEL_BAR,
};
super._init(Object.assign(defaultParams, params));
this.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width();
this.connect('notify::allocation', () => {
this._barLevelWidth = this.allocation.get_width();
});
this._customAccessible = St.GenericAccessible.new_for_actor(this);

View File

@ -196,8 +196,13 @@ var BoxPointer = GObject.registerClass({
return themeNode.adjust_preferred_height(...height);
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box);
this._updateFlip(box);
}
this.set_allocation(box);
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
@ -209,7 +214,7 @@ var BoxPointer = GObject.registerClass({
childBox.y1 = 0;
childBox.x2 = availWidth;
childBox.y2 = availHeight;
this._border.allocate(childBox, flags);
this._border.allocate(childBox);
childBox.x1 = borderWidth;
childBox.y1 = borderWidth;
@ -229,13 +234,7 @@ var BoxPointer = GObject.registerClass({
childBox.x2 -= rise;
break;
}
this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box);
this._updateFlip(box);
this.set_allocation(box, flags);
}
this.bin.allocate(childBox);
}
_drawBorder(area) {

View File

@ -222,7 +222,12 @@ class DBusEventSource extends EventSourceBase {
}
}
this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
this._dbusProxy.connectSignal('EventsAddedOrUpdated',
this._onEventsAddedOrUpdated.bind(this));
this._dbusProxy.connectSignal('EventsRemoved',
this._onEventsRemoved.bind(this));
this._dbusProxy.connectSignal('ClientDisappeared',
this._onClientDisappeared.bind(this));
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
@ -258,7 +263,7 @@ class DBusEventSource extends EventSourceBase {
}
_resetCache() {
this._events = [];
this._events = new Map();
this._lastRequestBegin = null;
this._lastRequestEnd = null;
}
@ -274,28 +279,47 @@ class DBusEventSource extends EventSourceBase {
this.emit('changed');
}
_onChanged() {
this._loadEvents(false);
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
const [appointments = []] = argArray;
let changed = false;
for (let n = 0; n < appointments.length; n++) {
const [id, summary, allDay, startTime, endTime] = appointments[n];
const date = new Date(startTime * 1000);
const end = new Date(endTime * 1000);
let event = new CalendarEvent(id, date, end, summary, allDay);
this._events.set(event.id, event);
changed = true;
}
if (changed)
this.emit('changed');
}
_onEventsReceived(results, _error) {
let newEvents = [];
let appointments = results[0] || [];
for (let n = 0; n < appointments.length; n++) {
let a = appointments[n];
let date = new Date(a[4] * 1000);
let end = new Date(a[5] * 1000);
let id = a[0];
let summary = a[1];
let allDay = a[3];
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
_onEventsRemoved(dbusProxy, nameOwner, argArray) {
const [ids = []] = argArray;
this._events = newEvents;
this._isLoading = false;
this.emit('changed');
let changed = false;
for (const id of ids)
changed |= this._events.delete(id);
if (changed)
this.emit('changed');
}
_onClientDisappeared(dbusProxy, nameOwner, argArray) {
let [sourceUid = ''] = argArray;
sourceUid += '\n';
let changed = false;
for (const id of this._events.keys()) {
if (id.startsWith(sourceUid))
changed |= this._events.delete(id);
}
if (changed)
this.emit('changed');
}
_loadEvents(forceReload) {
@ -304,33 +328,38 @@ class DBusEventSource extends EventSourceBase {
return;
if (this._curRequestBegin && this._curRequestEnd) {
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
this._onEventsReceived.bind(this),
Gio.DBusCallFlags.NONE);
if (forceReload) {
this._events.clear();
this.emit('changed');
}
this._dbusProxy.SetTimeRangeRemote(
this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
Gio.DBusCallFlags.NONE);
}
}
requestRange(begin, end) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
this._isLoading = true;
this._lastRequestBegin = begin;
this._lastRequestEnd = end;
this._curRequestBegin = begin;
this._curRequestEnd = end;
this._loadEvents(false);
this._loadEvents(true);
}
}
*_getFilteredEvents(begin, end) {
for (const event of this._events.values()) {
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
yield event;
}
}
getEvents(begin, end) {
let result = [];
for (let n = 0; n < this._events.length; n++) {
let event = this._events[n];
let result = [...this._getFilteredEvents(begin, end)];
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
result.push(event);
}
result.sort((event1, event2) => {
// sort events by end time on ending day
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
@ -344,12 +373,8 @@ class DBusEventSource extends EventSourceBase {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
let events = this.getEvents(dayBegin, dayEnd);
if (events.length == 0)
return false;
return true;
const { done } = this._getFilteredEvents(dayBegin, dayEnd).next();
return !done;
}
});
@ -701,12 +726,11 @@ var Calendar = GObject.registerClass({
var EventMessage = GObject.registerClass(
class EventMessage extends MessageList.Message {
_init(event, date) {
super._init('', event.summary);
super._init('', '');
this._event = event;
this._date = date;
this.setTitle(this._formatEventTime());
this.update(event);
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
@ -718,6 +742,13 @@ class EventMessage extends MessageList.Message {
super.vfunc_style_changed();
}
update(event) {
this._event = event;
this.setTitle(this._formatEventTime());
this.setBody(event.summary);
}
_formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
@ -875,7 +906,7 @@ class EventsSection extends MessageList.MessageListSection {
}
_reloadEvents() {
if (this._eventSource.isLoading)
if (this._eventSource.isLoading || this._reloading)
return;
this._reloading = true;
@ -901,6 +932,7 @@ class EventsSection extends MessageList.MessageListSection {
this._messageById.set(event.id, message);
this.addMessage(message, false);
} else {
message.update(event);
this.moveMessage(message, i, false);
}
}
@ -1167,8 +1199,8 @@ class CalendarMessageList extends St.Widget {
child: this._dndSwitch,
label_actor: dndLabel,
});
this._dndButton.bind_property('checked',
this._dndSwitch, 'state',
this._dndSwitch.bind_property('state',
this._dndButton, 'checked',
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
hbox.add_child(this._dndButton);

View File

@ -13,17 +13,13 @@ var ComponentManager = class {
_sessionUpdated() {
let newEnabledComponents = Main.sessionMode.components;
newEnabledComponents.filter(
name => !this._enabledComponents.includes(name)
).forEach(name => {
this._enableComponent(name);
});
newEnabledComponents
.filter(name => !this._enabledComponents.includes(name))
.forEach(name => this._enableComponent(name));
this._enabledComponents.filter(
name => !newEnabledComponents.includes(name)
).forEach(name => {
this._disableComponent(name);
});
this._enabledComponents
.filter(name => !newEnabledComponents.includes(name))
.forEach(name => this._disableComponent(name));
this._enabledComponents = newEnabledComponents;
}

View File

@ -125,8 +125,7 @@ var ContentTypeDiscoverer = class {
_emitCallback(mount, contentTypes = []) {
// we're not interested in win32 software content types here
contentTypes = contentTypes.filter(
type => type != 'x-content/win32-software'
);
type => type !== 'x-content/win32-software');
let apps = [];
contentTypes.forEach(type => {

View File

@ -327,12 +327,16 @@ var AuthenticationDialog = GObject.registerClass({
}
let resetDialog = () => {
this._sessionRequestTimeoutId = 0;
if (this.state != ModalDialog.State.OPENED)
return;
return GLib.SOURCE_REMOVE;
this._passwordEntry.hide();
this._cancelButton.grab_key_focus();
this._okButton.reactive = false;
return GLib.SOURCE_REMOVE;
};
if (delay) {

View File

@ -292,11 +292,11 @@ class DashActor extends St.Widget {
});
}
vfunc_allocate(box, flags) {
vfunc_allocate(box) {
let contentBox = this.get_theme_node().get_content_box(box);
let availWidth = contentBox.x2 - contentBox.x1;
this.set_allocation(box, flags);
this.set_allocation(box);
let [appIcons, showAppsButton] = this.get_children();
let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
@ -306,11 +306,11 @@ class DashActor extends St.Widget {
childBox.y1 = contentBox.y1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2 - showAppsNatHeight;
appIcons.allocate(childBox, flags);
appIcons.allocate(childBox);
childBox.y1 = contentBox.y2 - showAppsNatHeight;
childBox.y2 = contentBox.y2;
showAppsButton.allocate(childBox, flags);
showAppsButton.allocate(childBox);
}
vfunc_get_preferred_height(forWidth) {
@ -815,7 +815,12 @@ var Dash = GObject.registerClass({
else
pos = 0; // always insert at the top when dash is empty
if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
// Put the placeholder after the last favorite if we are not
// in the favorites zone
if (pos > numFavorites)
pos = numFavorites;
if (pos !== this._dragPlaceholderPos && this._animatingPlaceholdersCount === 0) {
this._dragPlaceholderPos = pos;
// Don't allow positioning before or after self
@ -843,11 +848,6 @@ var Dash = GObject.registerClass({
this._dragPlaceholder.show(fadeIn);
}
// Remove the drag placeholder if we are not in the
// "favorites zone"
if (pos > numFavorites)
this._clearDragPlaceholder();
if (!this._dragPlaceholder)
return DND.DragMotionResult.NO_DROP;

View File

@ -94,6 +94,7 @@ class WorldClocksSection extends St.Button {
});
this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0;
this._tzNotifyId = 0;
this._locations = [];
@ -166,8 +167,6 @@ class WorldClocksSection extends St.Button {
layout.attach(header, 0, 0, 2, 1);
this.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location;
@ -180,21 +179,8 @@ class WorldClocksSection extends St.Button {
let time = new St.Label({ style_class: 'world-clocks-time' });
const utcOffset = this._getTimeAtLocation(l).get_utc_offset();
const offsetCurrentTz = utcOffset - localOffset;
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR;
const offsetMinutes =
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) /
GLib.TIME_SPAN_MINUTE;
const prefix = offsetCurrentTz >= 0 ? '+' : '-';
const text = offsetMinutes === 0
? '%s%d'.format(prefix, offsetHours)
: '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
const tz = new St.Label({
style_class: 'world-clocks-timezone',
text,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
@ -212,32 +198,65 @@ class WorldClocksSection extends St.Button {
layout.attach(tz, 2, i + 1, 1, 1);
}
this._locations[i].actor = time;
this._locations[i].timeLabel = time;
this._locations[i].tzLabel = tz;
}
if (this._grid.get_n_children() > 1) {
if (!this._clockNotifyId) {
this._clockNotifyId =
this._clock.connect('notify::clock', this._updateLabels.bind(this));
this._clock.connect('notify::clock', this._updateTimeLabels.bind(this));
}
this._updateLabels();
if (!this._tzNotifyId) {
this._tzNotifyId =
this._clock.connect('notify::timezone', this._updateTimezoneLabels.bind(this));
}
this._updateTimeLabels();
this._updateTimezoneLabels();
} else {
if (this._clockNotifyId)
this._clock.disconnect(this._clockNotifyId);
this._clockNotifyId = 0;
if (this._tzNotifyId)
this._clock.disconnect(this._tzNotifyId);
this._tzNotifyId = 0;
}
}
_getTimezoneOffsetAtLocation(location) {
const localOffset = GLib.DateTime.new_now_local().get_utc_offset();
const utcOffset = this._getTimeAtLocation(location).get_utc_offset();
const offsetCurrentTz = utcOffset - localOffset;
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR;
const offsetMinutes =
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) /
GLib.TIME_SPAN_MINUTE;
const prefix = offsetCurrentTz >= 0 ? '+' : '-';
const text = offsetMinutes === 0
? '%s%d'.format(prefix, offsetHours)
: '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
return text;
}
_getTimeAtLocation(location) {
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
return GLib.DateTime.new_now(tz);
}
_updateLabels() {
_updateTimeLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
let now = this._getTimeAtLocation(l.location);
l.actor.text = Util.formatTime(now, { timeOnly: true });
l.timeLabel.text = Util.formatTime(now, { timeOnly: true });
}
}
_updateTimezoneLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
l.tzLabel.text = this._getTimezoneOffsetAtLocation(l.location);
}
}
@ -281,13 +300,13 @@ class WeatherSection extends St.Button {
this.child = box;
let titleBox = new St.BoxLayout({ style_class: 'weather-header-box' });
titleBox.add_child(new St.Label({
this._titleLabel = new St.Label({
style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_align: Clutter.ActorAlign.END,
text: _('Weather'),
}));
});
titleBox.add_child(this._titleLabel);
box.add_child(titleBox);
this._titleLocation = new St.Label({
@ -414,10 +433,8 @@ class WeatherSection extends St.Button {
_updateForecasts() {
this._forecastGrid.destroy_all_children();
if (!this._weatherClient.hasLocation) {
this._setStatusLabel(_("Select a location…"));
if (!this._weatherClient.hasLocation)
return;
}
const { info } = this._weatherClient;
this._titleLocation.text = this._findBestLocationName(info.location);
@ -444,6 +461,12 @@ class WeatherSection extends St.Button {
if (!this.visible)
return;
if (this._weatherClient.hasLocation)
this._titleLabel.text = _('Weather');
else
this._titleLabel.text = _('Select weather location…');
this._forecastGrid.visible = this._weatherClient.hasLocation;
this._titleLocation.visible = this._weatherClient.hasLocation;
this._updateForecasts();
@ -462,7 +485,6 @@ class MessagesIndicator extends St.Icon {
this._sources = [];
this._count = 0;
this._doNotDisturb = false;
this._settings = new Gio.Settings({
schema_id: 'org.gnome.desktop.notifications',
@ -543,8 +565,8 @@ class FreezableBinLayout extends Clutter.BinLayout {
return this._savedHeight;
}
vfunc_allocate(container, allocation, flags) {
super.vfunc_allocate(container, allocation, flags);
vfunc_allocate(container, allocation) {
super.vfunc_allocate(container, allocation);
let [width, height] = allocation.get_size();
this._savedWidth = [width, width];

View File

@ -245,16 +245,15 @@ function _loggingFunc(...args) {
}
function init() {
// Add some bindings to the global JS namespace; (gjs keeps the web
// browser convention of having that namespace be called 'window'.)
window.global = Shell.Global.get();
// Add some bindings to the global JS namespace
globalThis.global = Shell.Global.get();
window.log = _loggingFunc;
globalThis.log = _loggingFunc;
window._ = Gettext.gettext;
window.C_ = Gettext.pgettext;
window.ngettext = Gettext.ngettext;
window.N_ = s => s;
globalThis._ = Gettext.gettext;
globalThis.C_ = Gettext.pgettext;
globalThis.ngettext = Gettext.ngettext;
globalThis.N_ = s => s;
GObject.gtypeNameBasedOnJSPath = true;
@ -286,6 +285,11 @@ function init() {
_easeActorProperty(this, 'value', target, params);
};
Clutter.Actor.prototype[Symbol.iterator] = function* () {
for (let c = this.get_first_child(); c; c = c.get_next_sibling())
yield c;
};
Clutter.Actor.prototype.toString = function () {
return St.describe_actor(this);
};
@ -356,9 +360,7 @@ function init() {
// OK, now things are initialized enough that we can import shell JS
const Format = imports.format;
const Tweener = imports.ui.tweener;
Tweener.init();
String.prototype.format = Format.format;
}

View File

@ -238,7 +238,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
});
function init() {
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
_httpSession = new Soup.Session({ ssl_use_system_ca_file: true });
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
// _httpSession.add_feature(new Soup.ProxyResolverDefault());

View File

@ -26,6 +26,7 @@ var ExtensionManager = class {
this._updateNotified = false;
this._extensions = new Map();
this._unloadedExtensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
@ -102,18 +103,18 @@ var ExtensionManager = class {
}
}
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
try {
extension.stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
for (let i = 0; i < order.length; i++) {
let otherUuid = order[i];
try {
@ -259,7 +260,8 @@ var ExtensionManager = class {
if (!extension)
return;
let message = error.toString();
const message = error instanceof Error
? error.message : error.toString();
extension.error = message;
extension.state = ExtensionState.ERROR;
@ -268,6 +270,7 @@ var ExtensionManager = class {
extension.errors.push(message);
logError(error, 'Extension %s'.format(uuid));
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
@ -317,6 +320,14 @@ var ExtensionManager = class {
return extension;
}
_canLoad(extension) {
if (!this._unloadedExtensions.has(extension.uuid))
return true;
const version = this._unloadedExtensions.get(extension.uuid);
return extension.metadata.version === version;
}
loadExtension(extension) {
// Default to error, we set success as the last step
extension.state = ExtensionState.ERROR;
@ -325,6 +336,9 @@ var ExtensionManager = class {
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
extension.state = ExtensionState.OUT_OF_DATE;
} else if (!this._canLoad(extension)) {
this.logExtensionError(extension.uuid, new Error(
'A different version was loaded previously. You need to log out for changes to take effect.'));
} else {
let enabled = this._enabledExtensions.includes(extension.uuid);
if (enabled) {
@ -335,6 +349,8 @@ var ExtensionManager = class {
} else {
extension.state = ExtensionState.INITIALIZED;
}
this._unloadedExtensions.delete(extension.uuid);
}
this._updateCanChange(extension);
@ -342,15 +358,22 @@ var ExtensionManager = class {
}
unloadExtension(extension) {
const { uuid, type } = extension;
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
this._callExtensionDisable(extension.uuid);
this._callExtensionDisable(uuid);
extension.state = ExtensionState.UNINSTALLED;
this.emit('extension-state-changed', extension);
this._extensions.delete(extension.uuid);
// If we did install an importer, it is now cached and it's
// impossible to load a different version
if (type === ExtensionType.PER_USER && extension.imports)
this._unloadedExtensions.set(uuid, extension.metadata.version);
this._extensions.delete(uuid);
return true;
}
@ -463,19 +486,15 @@ var ExtensionManager = class {
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
uuid => !this._enabledExtensions.includes(uuid)
).forEach(uuid => {
this._callExtensionEnable(uuid);
});
newEnabledExtensions
.filter(uuid => !this._enabledExtensions.includes(uuid))
.forEach(uuid => this._callExtensionEnable(uuid));
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
this._extensionOrder.filter(
uuid => !newEnabledExtensions.includes(uuid)
).reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
this._extensionOrder
.filter(uuid => !newEnabledExtensions.includes(uuid))
.reverse().forEach(uuid => this._callExtensionDisable(uuid));
this._enabledExtensions = newEnabledExtensions;
}

View File

@ -197,9 +197,9 @@ function zoomOutActorAtPos(actor, x, y) {
});
}
function animateIconPosition(icon, box, flags, nChangedIcons) {
function animateIconPosition(icon, box, nChangedIcons) {
if (!icon.has_allocation() || icon.allocation.equal(box) || icon.opacity === 0) {
icon.allocate(box, flags);
icon.allocate(box);
return false;
}
@ -207,7 +207,7 @@ function animateIconPosition(icon, box, flags, nChangedIcons) {
icon.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
icon.set_easing_delay(nChangedIcons * ICON_POSITION_DELAY);
icon.allocate(box, flags);
icon.allocate(box);
icon.restore_easing_state();
@ -226,7 +226,6 @@ var IconGrid = GObject.registerClass({
columnLimit: null,
minRows: 1,
minColumns: 1,
fillParent: false,
xAlign: St.Align.MIDDLE,
padWithSpacing: false });
this._rowLimit = params.rowLimit;
@ -234,7 +233,6 @@ var IconGrid = GObject.registerClass({
this._minRows = params.minRows;
this._minColumns = params.minColumns;
this._xAlign = params.xAlign;
this._fillParent = params.fillParent;
this._padWithSpacing = params.padWithSpacing;
this.topPadding = 0;
@ -242,6 +240,12 @@ var IconGrid = GObject.registerClass({
this.rightPadding = 0;
this.leftPadding = 0;
this._nPages = 0;
this.currentPage = 0;
this._rowsPerPage = 0;
this._spaceBetweenPages = 0;
this._childrenPerPage = 0;
this._updateIconSizesLaterId = 0;
this._items = [];
@ -297,11 +301,6 @@ var IconGrid = GObject.registerClass({
}
vfunc_get_preferred_width(_forHeight) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
return [0, 0];
let nChildren = this.get_n_children();
let nColumns = this._colLimit
? Math.min(this._colLimit, nChildren)
@ -320,52 +319,23 @@ var IconGrid = GObject.registerClass({
return this.get_children().filter(actor => actor.visible);
}
vfunc_get_preferred_height(forWidth) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
return [0, 0];
let themeNode = this.get_theme_node();
let children = this._getVisibleChildren();
let nColumns;
forWidth = themeNode.adjust_for_width(forWidth);
if (forWidth < 0)
nColumns = children.length;
else
[nColumns] = this._computeLayout(forWidth);
let nRows;
if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns);
else
nRows = 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
return themeNode.adjust_preferred_height(height, height);
_availableHeightPerPageForItems() {
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_get_preferred_height() {
const height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
}
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
vfunc_allocate(box) {
if (this._childrenPerPage === 0)
log('computePages() must be called before allocate(); pagination will not work.');
if (this._fillParent) {
// Reset the passed in box to fill the parent
let parentBox = this.get_parent().allocation;
let gridBox = themeNode.get_content_box(parentBox);
box = themeNode.get_content_box(gridBox);
}
this.set_allocation(box);
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let spacing = this._getSpacing();
let [nColumns, usedWidth] = this._computeLayout(availWidth);
@ -381,34 +351,27 @@ var IconGrid = GObject.registerClass({
leftEmptySpace = availWidth - usedWidth;
}
let animating = this._clonesAnimating.length > 0;
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
let nChangedIcons = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
children[i].opacity = 0;
} else {
if (!animating)
children[i].opacity = 255;
if (animateIconPosition(children[i], childBox, nChangedIcons))
nChangedIcons++;
if (animateIconPosition(children[i], childBox, flags, nChangedIcons))
nChangedIcons++;
}
children[i].show();
columnIndex++;
if (columnIndex == nColumns) {
if (columnIndex === nColumns)
columnIndex = 0;
rowIndex++;
}
if (columnIndex == 0) {
y += this._getVItemSize() + spacing;
if ((i + 1) % this._childrenPerPage === 0)
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
x = box.x1 + leftEmptySpace + this.leftPadding;
} else {
x += this._getHItemSize() + spacing;
@ -460,7 +423,11 @@ var IconGrid = GObject.registerClass({
* set of items to be animated.
*/
_getChildrenToAnimate() {
return this._getVisibleChildren().filter(child => child.opacity > 0);
const children = this._getVisibleChildren().filter(child => child.opacity > 0);
const firstIndex = this._childrenPerPage * this.currentPage;
const lastIndex = firstIndex + this._childrenPerPage;
return children.slice(firstIndex, lastIndex);
}
_resetAnimationActors() {
@ -736,16 +703,6 @@ var IconGrid = GObject.registerClass({
return usedWidth + this.leftPadding + this.rightPadding;
}
removeAll() {
this._items = [];
this.remove_all_children();
}
destroyAll() {
this._items = [];
this.destroy_all_children();
}
addItem(item, index) {
if (!(item.icon instanceof BaseIcon))
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
@ -761,14 +718,6 @@ var IconGrid = GObject.registerClass({
this.remove_child(item);
}
getItemAtIndex(index) {
return this.get_child_at_index(index);
}
visibleItemsCount() {
return this.get_children().filter(c => c.is_visible()).length;
}
setSpacing(spacing) {
this._fixedSpacing = spacing;
}
@ -818,6 +767,24 @@ var IconGrid = GObject.registerClass({
this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
}
_computePages(availWidthPerPage, availHeightPerPage) {
const [nColumns] = this._computeLayout(availWidthPerPage);
const children = this._getVisibleChildren();
let nRows;
if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns);
else
nRows = 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
// We want to contain the grid inside the parent box with padding
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
this._nPages = Math.ceil(nRows / this._rowsPerPage);
this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - this._availableHeightPerPageForItems();
this._childrenPerPage = nColumns * this._rowsPerPage;
}
/*
* This function must to be called before iconGrid allocation,
* to know how much spacing can the grid has
@ -843,6 +810,7 @@ var IconGrid = GObject.registerClass({
this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
}
this._computePages(availWidth, availHeight);
}
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
@ -855,116 +823,6 @@ var IconGrid = GObject.registerClass({
return GLib.SOURCE_REMOVE;
}
});
var PaginatedIconGrid = GObject.registerClass(
class PaginatedIconGrid extends IconGrid {
_init(params) {
super._init(params);
this._nPages = 0;
this.currentPage = 0;
this._rowsPerPage = 0;
this._spaceBetweenPages = 0;
this._childrenPerPage = 0;
}
vfunc_get_preferred_height(_forWidth) {
let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
}
vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
this.set_allocation(box, flags);
if (this._fillParent) {
// Reset the passed in box to fill the parent
let parentBox = this.get_parent().allocation;
let gridBox = this.get_theme_node().get_content_box(parentBox);
box = this.get_theme_node().get_content_box(gridBox);
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let spacing = this._getSpacing();
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let leftEmptySpace;
switch (this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let nChangedIcons = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
if (animateIconPosition(children[i], childBox, flags, nChangedIcons))
nChangedIcons++;
children[i].show();
columnIndex++;
if (columnIndex == nColumns)
columnIndex = 0;
if (columnIndex == 0) {
y += this._getVItemSize() + spacing;
if ((i + 1) % this._childrenPerPage == 0)
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
x = box.x1 + leftEmptySpace + this.leftPadding;
} else {
x += this._getHItemSize() + spacing;
}
}
}
// Overridden from IconGrid
_getChildrenToAnimate() {
let children = super._getChildrenToAnimate();
let firstIndex = this._childrenPerPage * this.currentPage;
let lastIndex = firstIndex + this._childrenPerPage;
return children.slice(firstIndex, lastIndex);
}
_computePages(availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth_] = this._computeLayout(availWidthPerPage);
let nRows;
let children = this._getVisibleChildren();
if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns);
else
nRows = 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
// We want to contain the grid inside the parent box with padding
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
this._nPages = Math.ceil(nRows / this._rowsPerPage);
this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - this._availableHeightPerPageForItems();
this._childrenPerPage = nColumns * this._rowsPerPage;
}
adaptToSize(availWidth, availHeight) {
super.adaptToSize(availWidth, availHeight);
this._computePages(availWidth, availHeight);
}
_availableHeightPerPageForItems() {
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
}
nPages() {
return this._nPages;

View File

@ -61,7 +61,7 @@ class AspectContainer extends St.Widget {
this.queue_relayout();
}
vfunc_allocate(box, flags) {
vfunc_allocate(box) {
if (box.get_width() > 0 && box.get_height() > 0) {
let sizeRatio = box.get_width() / box.get_height();
@ -79,7 +79,7 @@ class AspectContainer extends St.Widget {
}
}
super.vfunc_allocate(box, flags);
super.vfunc_allocate(box);
}
});
@ -722,7 +722,7 @@ var EmojiPager = GObject.registerClass({
_onPan(action) {
let [dist_, dx, dy_] = action.get_motion_delta(0);
this.delta = this.delta + dx;
this.delta += dx;
if (this._currentKey != null) {
this._currentKey.cancel();
@ -935,8 +935,7 @@ var EmojiSelection = GObject.registerClass({
this.add_child(this._emojiPager);
this._pageIndicator = new PageIndicators.PageIndicators(
Clutter.Orientation.HORIZONTAL
);
Clutter.Orientation.HORIZONTAL);
this.add_child(this._pageIndicator);
this._pageIndicator.setReactive(false);
@ -1119,7 +1118,7 @@ var KeyboardManager = class KeyBoardManager {
this._seat.connect('notify::touch-mode', this._syncEnabled.bind(this));
this._lastDevice = null;
Meta.get_backend().connect('last-device-changed', (backend, device) => {
global.backend.connect('last-device-changed', (backend, device) => {
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE)
return;
@ -1257,6 +1256,10 @@ class Keyboard extends St.BoxLayout {
return this._keyboardVisible && super.visible;
}
set visible(visible) {
super.visible = visible;
}
_onFocusPositionChanged(focusTracker) {
let rect = focusTracker.getCurrentRect();
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);

View File

@ -246,7 +246,7 @@ var LayoutManager = GObject.registerClass({
vertical: true });
this.addChrome(this.panelBox, { affectsStruts: true,
trackFullscreen: true });
this.panelBox.connect('allocation-changed',
this.panelBox.connect('notify::allocation',
this._panelBoxChanged.bind(this));
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',

View File

@ -27,13 +27,11 @@ var RadialShaderEffect = GObject.registerClass({
'brightness': GObject.ParamSpec.float(
'brightness', 'brightness', 'brightness',
GObject.ParamFlags.READWRITE,
0, 1, 1
),
0, 1, 1),
'sharpness': GObject.ParamSpec.float(
'sharpness', 'sharpness', 'sharpness',
GObject.ParamFlags.READWRITE,
0, 1, 0
),
0, 1, 0),
},
}, class RadialShaderEffect extends Shell.GLSLEffect {
_init(params) {

View File

@ -37,10 +37,9 @@ const LG_ANIMATION_TIME = 500;
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of window (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(window).filter(
a => a.charAt(0) != '_'
);
// Don't add the private properties of globalThis (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(globalThis).filter(
a => a.charAt(0) !== '_');
const headerProperties = JsParse.getDeclaredConstants(commandHeader);
return keywords.concat(windowProperties).concat(headerProperties);
@ -555,8 +554,8 @@ var Inspector = GObject.registerClass({
this._lookingGlass = lookingGlass;
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
if (!this._eventHandler)
return;
@ -571,7 +570,7 @@ var Inspector = GObject.registerClass({
childBox.x2 = childBox.x1 + natWidth;
childBox.y1 = primary.y + Math.floor((primary.height - natHeight) / 2);
childBox.y2 = childBox.y1 + natHeight;
this._eventHandler.allocate(childBox, flags);
this._eventHandler.allocate(childBox);
}
_close() {
@ -803,6 +802,191 @@ var Extensions = GObject.registerClass({
}
});
var ActorLink = GObject.registerClass({
Signals: {
'inspect-actor': {},
},
}, class ActorLink extends St.Button {
_init(actor) {
this._arrow = new St.Icon({
icon_name: 'pan-end-symbolic',
icon_size: 8,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
});
const label = new St.Label({
text: actor.toString(),
x_align: Clutter.ActorAlign.START,
});
const inspectButton = new St.Button({
child: new St.Icon({
icon_name: 'insert-object-symbolic',
icon_size: 12,
y_align: Clutter.ActorAlign.CENTER,
}),
reactive: true,
x_expand: true,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER,
});
inspectButton.connect('clicked', () => this.emit('inspect-actor'));
const box = new St.BoxLayout();
box.add_child(this._arrow);
box.add_child(label);
box.add_child(inspectButton);
super._init({
reactive: true,
track_hover: true,
toggle_mode: true,
style_class: 'actor-link',
child: box,
x_align: Clutter.ActorAlign.START,
});
this._actor = actor;
}
vfunc_clicked() {
this._arrow.ease({
rotation_angle_z: this.checked ? 90 : 0,
duration: 250,
});
}
});
var ActorTreeViewer = GObject.registerClass(
class ActorTreeViewer extends St.BoxLayout {
_init(lookingGlass) {
super._init();
this._lookingGlass = lookingGlass;
this._actorData = new Map();
}
_showActorChildren(actor) {
const data = this._actorData.get(actor);
if (!data || data.visible)
return;
data.visible = true;
data.actorAddedId = actor.connect('actor-added', (container, child) => {
this._addActor(data.children, child);
});
data.actorRemovedId = actor.connect('actor-removed', (container, child) => {
this._removeActor(child);
});
for (let child of actor)
this._addActor(data.children, child);
}
_hideActorChildren(actor) {
const data = this._actorData.get(actor);
if (!data || !data.visible)
return;
for (let child of actor)
this._removeActor(child);
data.visible = false;
if (data.actorAddedId > 0) {
actor.disconnect(data.actorAddedId);
data.actorAddedId = 0;
}
if (data.actorRemovedId > 0) {
actor.disconnect(data.actorRemovedId);
data.actorRemovedId = 0;
}
data.children.remove_all_children();
}
_addActor(container, actor) {
if (this._actorData.has(actor))
return;
if (actor === this._lookingGlass)
return;
const button = new ActorLink(actor);
button.connect('notify::checked', () => {
this._lookingGlass.setBorderPaintTarget(actor);
if (button.checked)
this._showActorChildren(actor);
else
this._hideActorChildren(actor);
});
button.connect('inspect-actor', () => {
this._lookingGlass.inspectObject(actor, button);
});
const mainContainer = new St.BoxLayout({ vertical: true });
const childrenContainer = new St.BoxLayout({
vertical: true,
style: 'padding: 0 0 0 18px',
});
mainContainer.add_child(button);
mainContainer.add_child(childrenContainer);
this._actorData.set(actor, {
button,
container: mainContainer,
children: childrenContainer,
visible: false,
actorAddedId: 0,
actorRemovedId: 0,
actorDestroyedId: actor.connect('destroy', () => this._removeActor(actor)),
});
let belowChild = null;
const nextSibling = actor.get_next_sibling();
if (nextSibling && this._actorData.has(nextSibling))
belowChild = this._actorData.get(nextSibling).container;
container.insert_child_above(mainContainer, belowChild);
}
_removeActor(actor) {
const data = this._actorData.get(actor);
if (!data)
return;
for (let child of actor)
this._removeActor(child);
if (data.actorAddedId > 0) {
actor.disconnect(data.actorAddedId);
data.actorAddedId = 0;
}
if (data.actorRemovedId > 0) {
actor.disconnect(data.actorRemovedId);
data.actorRemovedId = 0;
}
if (data.actorDestroyedId > 0) {
actor.disconnect(data.actorDestroyedId);
data.actorDestroyedId = 0;
}
data.container.destroy();
this._actorData.delete(actor);
}
vfunc_map() {
super.vfunc_map();
this._addActor(this, global.stage);
}
vfunc_unmap() {
super.vfunc_unmap();
this._removeActor(global.stage);
}
});
var LookingGlass = GObject.registerClass(
class LookingGlass extends St.BoxLayout {
_init() {
@ -834,9 +1018,9 @@ class LookingGlass extends St.BoxLayout {
Main.uiGroup.add_actor(this);
Main.uiGroup.set_child_below_sibling(this,
Main.layoutManager.panelBox);
Main.layoutManager.panelBox.connect('allocation-changed',
Main.layoutManager.panelBox.connect('notify::allocation',
this._queueResize.bind(this));
Main.layoutManager.keyboardBox.connect('allocation-changed',
Main.layoutManager.keyboardBox.connect('notify::allocation',
this._queueResize.bind(this));
this._objInspector = new ObjInspector(this);
@ -918,6 +1102,9 @@ class LookingGlass extends St.BoxLayout {
this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions);
this._actorTreeViewer = new ActorTreeViewer(this);
notebook.appendPage('Actors', this._actorTreeViewer);
this._entry.clutter_text.connect('activate', (o, _e) => {
// Hide any completions we are currently showing
this._hideCompletions();

View File

@ -643,8 +643,7 @@ var Magnifier = class Magnifier {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setClampScrollingAtEdges(
!this._settings.get_boolean(CLAMP_MODE_KEY)
);
!this._settings.get_boolean(CLAMP_MODE_KEY));
}
}
@ -652,8 +651,7 @@ var Magnifier = class Magnifier {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setMouseTrackingMode(
this._settings.get_enum(MOUSE_TRACKING_KEY)
);
this._settings.get_enum(MOUSE_TRACKING_KEY));
}
}
@ -661,8 +659,7 @@ var Magnifier = class Magnifier {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setFocusTrackingMode(
this._settings.get_enum(FOCUS_TRACKING_KEY)
);
this._settings.get_enum(FOCUS_TRACKING_KEY));
}
}
@ -670,8 +667,7 @@ var Magnifier = class Magnifier {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setCaretTrackingMode(
this._settings.get_enum(CARET_TRACKING_KEY)
);
this._settings.get_enum(CARET_TRACKING_KEY));
}
}
@ -679,8 +675,7 @@ var Magnifier = class Magnifier {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setInvertLightness(
this._settings.get_boolean(INVERT_LIGHTNESS_KEY)
);
this._settings.get_boolean(INVERT_LIGHTNESS_KEY));
}
}
@ -688,8 +683,7 @@ var Magnifier = class Magnifier {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setColorSaturation(
this._settings.get_double(COLOR_SATURATION_KEY)
);
this._settings.get_double(COLOR_SATURATION_KEY));
}
}
@ -1941,9 +1935,8 @@ var MagShaderEffects = class MagShaderEffects {
// it modifies the brightness and/or contrast.
let [cRed, cGreen, cBlue] = this._brightnessContrast.get_contrast();
this._brightnessContrast.set_enabled(
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE ||
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE
);
bRed !== NO_CHANGE || bGreen !== NO_CHANGE || bBlue !== NO_CHANGE ||
cRed !== NO_CHANGE || cGreen !== NO_CHANGE || cBlue !== NO_CHANGE);
}
/**
@ -1970,8 +1963,7 @@ var MagShaderEffects = class MagShaderEffects {
// a null first argument.
let [bRed, bGreen, bBlue] = this._brightnessContrast.get_brightness();
this._brightnessContrast.set_enabled(
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE ||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
);
cRed !== NO_CHANGE || cGreen !== NO_CHANGE || cBlue !== NO_CHANGE ||
bRed !== NO_CHANGE || bGreen !== NO_CHANGE || bBlue !== NO_CHANGE);
}
};

View File

@ -46,6 +46,7 @@ const XdndHandler = imports.ui.xdndHandler;
const KbdA11yDialog = imports.ui.kbdA11yDialog;
const LocatePointer = imports.ui.locatePointer;
const PointerA11yTimeout = imports.ui.pointerA11yTimeout;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const STICKY_KEYS_ENABLE = 'stickykeys-enable';
@ -96,6 +97,8 @@ let _oskResource = null;
Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
let _remoteAccessInhibited = false;
function _sessionUpdated() {
if (sessionMode.isPrimary)
_loadDefaultStylesheet();
@ -120,12 +123,23 @@ function _sessionUpdated() {
if (lookingGlass)
lookingGlass.close();
}
let remoteAccessController = global.backend.get_remote_access_controller();
if (remoteAccessController) {
if (sessionMode.allowScreencast && _remoteAccessInhibited) {
remoteAccessController.uninhibit_remote_access();
_remoteAccessInhibited = false;
} else if (!sessionMode.allowScreencast && !_remoteAccessInhibited) {
remoteAccessController.inhibit_remote_access();
_remoteAccessInhibited = true;
}
}
}
function start() {
// These are here so we don't break compatibility.
global.logError = window.log;
global.log = window.log;
global.logError = globalThis.log;
global.log = globalThis.log;
// Chain up async errors reported from C
global.connect('notify-error', (global, msg, detail) => {
@ -140,6 +154,10 @@ function start() {
sessionMode.connect('updated', _sessionUpdated);
St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
// Initialize ParentalControlsManager before the UI
ParentalControlsManager.getDefault();
_initializeUI();
shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
@ -521,7 +539,9 @@ function pushModal(actor, params) {
let prevFocusDestroyId;
if (prevFocus != null) {
prevFocusDestroyId = prevFocus.connect('destroy', () => {
let index = _findModal(actor);
const index = modalActorFocusStack.findIndex(
record => record.prevFocus === prevFocus);
if (index >= 0)
modalActorFocusStack[index].prevFocus = null;
});
@ -797,7 +817,7 @@ function showRestartMessage(message) {
var AnimationsSettings = class {
constructor() {
let backend = Meta.get_backend();
let backend = global.backend;
if (!backend.is_rendering_hardware_accelerated()) {
St.Settings.get().inhibit_animations();
return;

View File

@ -285,12 +285,12 @@ var LabelExpanderLayout = GObject.registerClass({
return [min, nat];
}
vfunc_allocate(container, box, flags) {
vfunc_allocate(container, box) {
for (let i = 0; i < container.get_n_children(); i++) {
let child = container.get_child_at_index(i);
if (child.visible)
child.allocate(box, flags);
child.allocate(box);
}
}

View File

@ -136,29 +136,22 @@ var FocusGrabber = class FocusGrabber {
var NotificationPolicy = GObject.registerClass({
Properties: {
'enable': GObject.ParamSpec.boolean(
'enable', 'enable', 'enable',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'enable', 'enable', 'enable', GObject.ParamFlags.READABLE, true),
'enable-sound': GObject.ParamSpec.boolean(
'enable-sound', 'enable-sound', 'enable-sound',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
GObject.ParamFlags.READABLE, true),
'show-banners': GObject.ParamSpec.boolean(
'show-banners', 'show-banners', 'show-banners',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
GObject.ParamFlags.READABLE, true),
'force-expanded': GObject.ParamSpec.boolean(
'force-expanded', 'force-expanded', 'force-expanded',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
GObject.ParamFlags.READABLE, false),
'show-in-lock-screen': GObject.ParamSpec.boolean(
'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
GObject.ParamFlags.READABLE, false),
'details-in-lock-screen': GObject.ParamSpec.boolean(
'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
GObject.ParamFlags.READABLE, false),
},
}, class NotificationPolicy extends GObject.Object {
// Do nothing for the default policy. These methods are only useful for the
@ -169,24 +162,28 @@ var NotificationPolicy = GObject.registerClass({
this.run_dispose();
}
get enable() {
return true;
}
get enableSound() {
return this.enable_sound;
return true;
}
get showBanners() {
return this.show_banners;
return true;
}
get forceExpanded() {
return this.force_expanded;
return false;
}
get showInLockScreen() {
return this.show_in_lock_screen;
return false;
}
get detailsInLockScreen() {
return this.details_in_lock_screen;
return false;
}
});
@ -689,8 +686,8 @@ class SourceActorWithLabel extends SourceActor {
});
}
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
vfunc_allocate(box) {
super.vfunc_allocate(box);
let childBox = new Clutter.ActorBox();
@ -710,7 +707,7 @@ class SourceActorWithLabel extends SourceActor {
childBox.y1 = box.y2 - naturalHeight;
childBox.y2 = box.y2;
this._counterBin.allocate(childBox, flags);
this._counterBin.allocate(childBox);
}
_updateCount() {
@ -1167,8 +1164,7 @@ var MessageTray = GObject.registerClass({
this._onNotificationDestroy.bind(this));
this._notificationQueue.push(notification);
this._notificationQueue.sort(
(n1, n2) => n2.urgency - n1.urgency
);
(n1, n2) => n2.urgency - n1.urgency);
this.emit('queue-changed');
}
}

View File

@ -173,6 +173,11 @@ var MprisPlayer = class MprisPlayer {
if (!this._mprisProxy.g_name_owner)
this._close();
});
// It is possible for the bus to disappear before the previous signal
// is connected, so we must ensure that the bus still exists at this
// point.
if (!this._mprisProxy.g_name_owner)
this._close();
}
_onPlayerProxyReady() {

View File

@ -10,13 +10,6 @@ const Params = imports.misc.params;
const { loadInterfaceXML } = imports.misc.fileUtils;
// Should really be defined in Gio.js
const BusIface = loadInterfaceXML('org.freedesktop.DBus');
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
function Bus() {
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
const FdoNotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
var NotificationClosedReason = {
@ -49,9 +42,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
this._sources = [];
this._senderToPid = {};
this._notifications = {};
this._busProxy = new Bus();
this._nextNotificationId = 1;
@ -116,12 +107,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
//
// If no existing source is found, a new source is created as long as
// pid is provided.
//
// Either a pid or ndata.notification is needed to retrieve or
// create a source.
_getSource(title, pid, ndata, sender) {
if (!pid && !(ndata && ndata.notification))
return null;
throw new Error('Either a pid or ndata.notification is needed');
// We use notification's source for the notifications we still have
// around that are getting replaced because we don't keep sources
@ -218,42 +206,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
this._notifications[id] = ndata;
let sender = invocation.get_sender();
let pid = this._senderToPid[sender];
let pid = hints['sender-pid'];
let source = this._getSource(appName, pid, ndata, sender, null);
if (source) {
this._notifyForSource(source, ndata);
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
if (replacesId) {
// There's already a pending call to GetConnectionUnixProcessID,
// which will see the new notification data when it finishes,
// so we don't have to do anything.
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
this._busProxy.GetConnectionUnixProcessIDRemote(sender, (result, excp) => {
// The app may have updated or removed the notification
ndata = this._notifications[id];
if (!ndata)
return;
if (excp) {
logError(excp, 'Call to GetConnectionUnixProcessID failed');
return;
}
[pid] = result;
source = this._getSource(appName, pid, ndata, sender, null);
this._senderToPid[sender] = pid;
source.connect('destroy', () => {
delete this._senderToPid[sender];
});
this._notifyForSource(source, ndata);
});
this._notifyForSource(source, ndata);
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
@ -417,12 +373,11 @@ var FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source {
_init(title, pid, sender, appId) {
this.pid = pid;
this.initialTitle = title;
this.app = this._getApp(appId);
super._init(title);
this.initialTitle = title;
if (this.app)
this.title = this.app.get_name();
else
@ -470,19 +425,20 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
}
_getApp(appId) {
const appSys = Shell.AppSystem.get_default();
let app;
app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
if (app != null)
return app;
if (appId) {
app = Shell.AppSystem.get_default().lookup_app('%s.desktop'.format(appId));
if (app != null)
return app;
}
if (appId)
app = appSys.lookup_app('%s.desktop'.format(appId));
return null;
if (!app)
app = appSys.lookup_app('%s.desktop'.format(this.initialTitle));
return app;
}
setTitle(title) {

View File

@ -400,8 +400,7 @@ var Overview = class {
_getDesktopClone() {
let windows = global.get_window_actors().filter(
w => w.meta_window.get_window_type() == Meta.WindowType.DESKTOP
);
w => w.meta_window.get_window_type() === Meta.WindowType.DESKTOP);
if (windows.length == 0)
return null;

View File

@ -51,7 +51,7 @@ var SlideLayout = GObject.registerClass({
return [minWidth, natWidth];
}
vfunc_allocate(container, box, flags) {
vfunc_allocate(container, box) {
let child = container.get_first_child();
let availWidth = Math.round(box.x2 - box.x1);
@ -72,7 +72,7 @@ var SlideLayout = GObject.registerClass({
actorBox.y1 = box.y1;
actorBox.y2 = actorBox.y1 + availHeight;
child.allocate(actorBox, flags);
child.allocate(actorBox);
}
// eslint-disable-next-line camelcase
@ -394,10 +394,10 @@ class DashSpacer extends St.Widget {
});
var ControlsLayout = GObject.registerClass({
Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
Signals: { 'allocation-changed': {} },
}, class ControlsLayout extends Clutter.BinLayout {
vfunc_allocate(container, box, flags) {
super.vfunc_allocate(container, box, flags);
vfunc_allocate(container, box) {
super.vfunc_allocate(container, box);
this.emit('allocation-changed');
}
});
@ -473,6 +473,7 @@ class ControlsManager extends St.Widget {
// A workspace might have been inserted or removed before the active
// one, causing the adjustment to go out of sync, so update the value
this._workspaceAdjustment.remove_transition('value');
this._workspaceAdjustment.value = activeIndex;
}

View File

@ -2,7 +2,7 @@
/* exported PadOsd, PadOsdService */
const { Atk, Clutter, GDesktopEnums, Gio,
GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
GLib, GObject, Gtk, Meta, Pango, Rsvg, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
@ -329,6 +329,7 @@ var PadDiagram = GObject.registerClass({
this._imagePath = imagePath;
this._handle = this._composeStyledDiagram();
this._initLabels();
}
// eslint-disable-next-line camelcase
@ -343,6 +344,26 @@ var PadDiagram = GObject.registerClass({
this.add_actor(actor);
}
_initLabels() {
let i = 0;
for (i = 0; ; i++) {
if (!this._addLabel(Meta.PadActionType.BUTTON, i))
break;
}
for (i = 0; ; i++) {
if (!this._addLabel(Meta.PadActionType.RING, i, CW) ||
!this._addLabel(Meta.PadActionType.RING, i, CCW))
break;
}
for (i = 0; ; i++) {
if (!this._addLabel(Meta.PadActionType.STRIP, i, UP) ||
!this._addLabel(Meta.PadActionType.STRIP, i, DOWN))
break;
}
}
_wrappingSvgHeader() {
return '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ' +
@ -362,10 +383,8 @@ var PadDiagram = GObject.registerClass({
for (let i = 0; i < this._activeButtons.length; i++) {
let ch = String.fromCharCode('A'.charCodeAt() + this._activeButtons[i]);
css += '.%s {'.format(ch);
css += ' stroke: %s !important;'.format(ACTIVE_COLOR);
css += ' fill: %s !important;'.format(ACTIVE_COLOR);
css += '}';
css += '.%s.Leader { stroke: %s !important; }'.format(ch, ACTIVE_COLOR);
css += '.%s.Button { stroke: %s !important; fill: %s !important; }'.format(ch, ACTIVE_COLOR, ACTIVE_COLOR);
}
return css;
@ -390,9 +409,6 @@ var PadDiagram = GObject.registerClass({
}
_updateDiagramScale() {
if (this._handle == null)
return;
[this._actorWidth, this._actorHeight] = this.get_size();
let dimensions = this._handle.get_dimensions();
let scaleX = this._actorWidth / dimensions.width;
@ -405,6 +421,11 @@ var PadDiagram = GObject.registerClass({
let [, natWidth] = child.get_preferred_width(natHeight);
let childBox = new Clutter.ActorBox();
// I miss Cairo.Matrix
let dimensions = this._handle.get_dimensions();
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
if (direction == LTR) {
childBox.x1 = x;
childBox.x2 = x + natWidth;
@ -415,22 +436,23 @@ var PadDiagram = GObject.registerClass({
childBox.y1 = y - natHeight / 2;
childBox.y2 = y + natHeight / 2;
child.allocate(childBox, 0);
child.allocate(childBox);
}
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
vfunc_allocate(box) {
super.vfunc_allocate(box);
if (this._handle === null)
return;
this._updateDiagramScale();
for (let i = 0; i < this._labels.length; i++) {
let [label, action, idx, dir] = this._labels[i];
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
const { label, x, y, arrangement } = this._labels[i];
this._allocateChild(label, x, y, arrangement);
}
if (this._editorActor && this._curEdited) {
let [label_, action, idx, dir] = this._curEdited;
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
const { x, y, arrangement } = this._curEdited;
this._allocateChild(this._editorActor, x, y, arrangement);
}
}
@ -457,17 +479,6 @@ var PadDiagram = GObject.registerClass({
cr.$dispose();
}
_transformPoint(x, y) {
if (this._handle == null || this._scale == null)
return [x, y];
// I miss Cairo.Matrix
let dimensions = this._handle.get_dimensions();
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
return [Math.round(x), Math.round(y)];
}
_getItemLabelCoords(labelName, leaderName) {
if (this._handle == null)
return [false];
@ -495,44 +506,39 @@ var PadDiagram = GObject.registerClass({
pos.y = this._imageHeight - pos.y;
}
let [x, y] = this._transformPoint(pos.x, pos.y);
return [true, x, y, direction];
return [true, pos.x, pos.y, direction];
}
getButtonLabelCoords(button) {
_getButtonLabels(button) {
let ch = String.fromCharCode('A'.charCodeAt() + button);
let labelName = 'Label%s'.format(ch);
let leaderName = 'Leader%s'.format(ch);
return this._getItemLabelCoords(labelName, leaderName);
return [labelName, leaderName];
}
getRingLabelCoords(number, dir) {
_getRingLabels(number, dir) {
let numStr = number > 0 ? (number + 1).toString() : '';
let dirStr = dir == CW ? 'CW' : 'CCW';
let labelName = 'LabelRing%s%s'.format(numStr, dirStr);
let leaderName = 'LeaderRing%s%s'.format(numStr, dirStr);
return this._getItemLabelCoords(labelName, leaderName);
return [labelName, leaderName];
}
getStripLabelCoords(number, dir) {
_getStripLabels(number, dir) {
let numStr = number > 0 ? (number + 1).toString() : '';
let dirStr = dir == UP ? 'Up' : 'Down';
let labelName = 'LabelStrip%s%s'.format(numStr, dirStr);
let leaderName = 'LeaderStrip%s%s'.format(numStr, dirStr);
return this._getItemLabelCoords(labelName, leaderName);
return [labelName, leaderName];
}
getLabelCoords(action, idx, dir) {
_getLabelCoords(action, idx, dir) {
if (action == Meta.PadActionType.BUTTON)
return this.getButtonLabelCoords(idx);
return this._getItemLabelCoords(...this._getButtonLabels(idx));
else if (action == Meta.PadActionType.RING)
return this.getRingLabelCoords(idx, dir);
return this._getItemLabelCoords(...this._getRingLabels(idx, dir));
else if (action == Meta.PadActionType.STRIP)
return this.getStripLabelCoords(idx, dir);
return this._getItemLabelCoords(...this._getStripLabels(idx, dir));
return [false];
}
@ -557,26 +563,30 @@ var PadDiagram = GObject.registerClass({
this._invalidateSvg();
}
addLabel(label, type, idx, dir) {
this._labels.push([label, type, idx, dir]);
_addLabel(action, idx, dir) {
let [found, x, y, arrangement] = this._getLabelCoords(action, idx, dir);
if (!found)
return false;
let label = new St.Label();
this._labels.push({ label, action, idx, dir, x, y, arrangement });
this.add_actor(label);
return true;
}
updateLabels(getText) {
for (let i = 0; i < this._labels.length; i++) {
let [label, action, idx, dir] = this._labels[i];
const { label, action, idx, dir } = this._labels[i];
let str = getText(action, idx, dir);
label.set_text(str);
}
this.queue_relayout();
}
_applyLabel(label, action, idx, dir, str) {
if (str != null) {
if (str !== null)
label.set_text(str);
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(label, x, y, arrangement);
}
label.show();
}
@ -584,18 +594,20 @@ var PadDiagram = GObject.registerClass({
this._editorActor.hide();
if (this._prevEdited) {
let [label, action, idx, dir] = this._prevEdited;
const { label, action, idx, dir } = this._prevEdited;
this._applyLabel(label, action, idx, dir, str);
this._prevEdited = null;
}
if (this._curEdited) {
let [label, action, idx, dir] = this._curEdited;
const { label, action, idx, dir } = this._curEdited;
this._applyLabel(label, action, idx, dir, str);
if (continues)
this._prevEdited = this._curEdited;
this._curEdited = null;
}
this.queue_relayout();
}
startEdition(action, idx, dir) {
@ -605,21 +617,19 @@ var PadDiagram = GObject.registerClass({
return;
for (let i = 0; i < this._labels.length; i++) {
let [label, itemAction, itemIdx, itemDir] = this._labels[i];
if (action == itemAction && idx == itemIdx && dir == itemDir) {
if (action == this._labels[i].action &&
idx == this._labels[i].idx && dir == this._labels[i].dir) {
this._curEdited = this._labels[i];
editedLabel = label;
editedLabel = this._curEdited.label;
break;
}
}
if (this._curEdited == null)
return;
let [found] = this.getLabelCoords(action, idx, dir);
if (!found)
return;
this._editorActor.show();
editedLabel.hide();
this.queue_relayout();
}
});
@ -693,6 +703,7 @@ var PadOsd = GObject.registerClass({
this._titleLabel = new St.Label({ style: 'font-side: larger; font-weight: bold;',
x_align: Clutter.ActorAlign.CENTER });
this._titleLabel.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this._titleLabel.clutter_text.set_text(padDevice.get_device_name());
labelBox.add_actor(this._titleLabel);
@ -710,31 +721,7 @@ var PadOsd = GObject.registerClass({
x_expand: true,
y_expand: true });
this.add_actor(this._padDiagram);
// FIXME: Fix num buttons.
let i = 0;
for (i = 0; i < 50; i++) {
let [found] = this._padDiagram.getButtonLabelCoords(i);
if (!found)
break;
this._createLabel(Meta.PadActionType.BUTTON, i);
}
for (i = 0; i < padDevice.get_n_rings(); i++) {
let [found] = this._padDiagram.getRingLabelCoords(i, CW);
if (!found)
break;
this._createLabel(Meta.PadActionType.RING, i, CW);
this._createLabel(Meta.PadActionType.RING, i, CCW);
}
for (i = 0; i < padDevice.get_n_strips(); i++) {
let [found] = this._padDiagram.getStripLabelCoords(i, UP);
if (!found)
break;
this._createLabel(Meta.PadActionType.STRIP, i, UP);
this._createLabel(Meta.PadActionType.STRIP, i, DOWN);
}
this._updateActionLabels();
let buttonBox = new St.Widget({ layout_manager: new Clutter.BinLayout(),
x_expand: true,
@ -787,11 +774,6 @@ var PadOsd = GObject.registerClass({
return str ? str : _("None");
}
_createLabel(type, number, dir) {
let label = new St.Label({ text: this._getActionText(type, number) });
this._padDiagram.addLabel(label, type, number, dir);
}
_updateActionLabels() {
this._padDiagram.updateLabels(this._getActionText.bind(this));
}
@ -867,8 +849,7 @@ var PadOsd = GObject.registerClass({
this._tipLabel.set_text(_("Press any key to exit"));
}
this._titleLabel.clutter_text.set_markup(
'<span size="larger"><b>%s</b></span>'.format(title));
this._titleLabel.set_text(title);
}
_isEditedAction(type, number, dir) {

View File

@ -214,7 +214,10 @@ var AppMenuButton = GObject.registerClass({
this._onIconThemeChanged.bind(this));
let iconEffect = new Clutter.DesaturateEffect();
this._iconBox = new St.Bin({ style_class: 'app-menu-icon' });
this._iconBox = new St.Bin({
style_class: 'app-menu-icon',
y_align: Clutter.ActorAlign.CENTER,
});
this._iconBox.add_effect(iconEffect);
this._container.add_actor(this._iconBox);
@ -281,7 +284,7 @@ var AppMenuButton = GObject.registerClass({
this.remove_all_transitions();
this.ease({
opacity: 0,
mode: Clutter.Animation.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: Overview.ANIMATION_TIME,
onComplete: () => this.hide(),
});
@ -839,8 +842,8 @@ class Panel extends St.Widget {
return [0, 0];
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
@ -876,13 +879,13 @@ class Panel extends St.Widget {
childBox.x2 = Math.min(Math.floor(sideWidth),
leftNaturalWidth);
}
this._leftBox.allocate(childBox, flags);
this._leftBox.allocate(childBox);
childBox.x1 = Math.ceil(sideWidth);
childBox.y1 = 0;
childBox.x2 = childBox.x1 + centerWidth;
childBox.y2 = allocHeight;
this._centerBox.allocate(childBox, flags);
this._centerBox.allocate(childBox);
childBox.y1 = 0;
childBox.y2 = allocHeight;
@ -896,7 +899,7 @@ class Panel extends St.Widget {
0);
childBox.x2 = allocWidth;
}
this._rightBox.allocate(childBox, flags);
this._rightBox.allocate(childBox);
let cornerWidth, cornerHeight;
@ -906,7 +909,7 @@ class Panel extends St.Widget {
childBox.x2 = cornerWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._leftCorner.allocate(childBox, flags);
this._leftCorner.allocate(childBox);
[, cornerWidth] = this._rightCorner.get_preferred_width(-1);
[, cornerHeight] = this._rightCorner.get_preferred_height(-1);
@ -914,7 +917,7 @@ class Panel extends St.Widget {
childBox.x2 = allocWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._rightCorner.allocate(childBox, flags);
this._rightCorner.allocate(childBox);
}
_tryDragWindow(event) {
@ -1153,10 +1156,9 @@ class Panel extends St.Widget {
_getDraggableWindowForPosition(stageX) {
let workspaceManager = global.workspace_manager;
let workspace = workspaceManager.get_active_workspace();
let allWindowsByStacking = global.display.sort_windows_by_stacking(
workspace.list_windows()
).reverse();
const windows = workspaceManager.get_active_workspace().list_windows();
const allWindowsByStacking =
global.display.sort_windows_by_stacking(windows).reverse();
return allWindowsByStacking.find(metaWindow => {
let rect = metaWindow.get_frame_rect();

View File

@ -59,8 +59,8 @@ class ButtonBox extends St.Widget {
return [0, 0];
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let child = this.get_first_child();
if (!child)
@ -83,7 +83,7 @@ class ButtonBox extends St.Widget {
childBox.y1 = 0;
childBox.y2 = availHeight;
child.allocate(childBox, flags);
child.allocate(childBox);
}
_onDestroy() {

View File

@ -198,7 +198,7 @@ var ScreenShield = class {
let lockEnabled = this._settings.get_boolean(LOCK_ENABLED_KEY);
let lockLocked = this._lockSettings.get_boolean(DISABLE_LOCK_KEY);
let inhibit = this._loginSession && this._loginSession.Active &&
!this._isActive && lockEnabled && !lockLocked;
!this._isActive && lockEnabled && !lockLocked && Main.sessionMode.unlockDialog;
if (inhibit) {
this._loginManager.inhibit(_("GNOME needs to lock the screen"),
inhibitor => {
@ -345,7 +345,7 @@ var ScreenShield = class {
this._lockDialogGroup.remove_all_transitions();
if (animate) {
// Tween the lock screen out of screen
// Animate the lock screen out of screen
// 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
@ -561,7 +561,8 @@ var ScreenShield = class {
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
this._ensureUnlockDialog(true);
if (!this._ensureUnlockDialog(true))
return;
this.actor.show();

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ScreenshotService */
const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox;
@ -37,7 +37,9 @@ var ScreenshotService = class {
let sender = invocation.get_sender();
if (this._screenShooter.has(sender) || lockedDown) {
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.BUSY,
'There is an ongoing operation for this sender');
return null;
}
@ -259,15 +261,13 @@ var ScreenshotService = class {
}
async PickColorAsync(params, invocation) {
let pickPixel = new PickPixel();
const screenshot = this._createScreenshot(invocation, false);
if (!screenshot)
return;
const pickPixel = new PickPixel(screenshot);
try {
const coords = await pickPixel.pickAsync();
let screenshot = this._createScreenshot(invocation, false);
if (!screenshot)
return;
const [color] = await screenshot.pick_color(coords.x, coords.y);
const color = await pickPixel.pickAsync();
const { red, green, blue } = color;
const retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
@ -276,12 +276,13 @@ var ScreenshotService = class {
blue / 255.0,
]),
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
} catch (e) {
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
'Operation was cancelled');
} finally {
this._removeShooterForSender(invocation.get_sender());
}
}
};
@ -379,12 +380,145 @@ class SelectArea extends St.Widget {
}
});
var RecolorEffect = GObject.registerClass({
Properties: {
color: GObject.ParamSpec.boxed(
'color', 'color', 'replacement color',
GObject.ParamFlags.WRITABLE,
Clutter.Color.$gtype),
chroma: GObject.ParamSpec.boxed(
'chroma', 'chroma', 'color to replace',
GObject.ParamFlags.WRITABLE,
Clutter.Color.$gtype),
threshold: GObject.ParamSpec.float(
'threshold', 'threshold', 'threshold',
GObject.ParamFlags.WRITABLE,
0.0, 1.0, 0.0),
smoothing: GObject.ParamSpec.float(
'smoothing', 'smoothing', 'smoothing',
GObject.ParamFlags.WRITABLE,
0.0, 1.0, 0.0),
},
}, class RecolorEffect extends Shell.GLSLEffect {
_init(params) {
this._color = new Clutter.Color();
this._chroma = new Clutter.Color();
this._threshold = 0;
this._smoothing = 0;
this._colorLocation = null;
this._chromaLocation = null;
this._thresholdLocation = null;
this._smoothingLocation = null;
super._init(params);
this._colorLocation = this.get_uniform_location('recolor_color');
this._chromaLocation = this.get_uniform_location('chroma_color');
this._thresholdLocation = this.get_uniform_location('threshold');
this._smoothingLocation = this.get_uniform_location('smoothing');
this._updateColorUniform(this._colorLocation, this._color);
this._updateColorUniform(this._chromaLocation, this._chroma);
this._updateFloatUniform(this._thresholdLocation, this._threshold);
this._updateFloatUniform(this._smoothingLocation, this._smoothing);
}
_updateColorUniform(location, color) {
if (!location)
return;
this.set_uniform_float(location,
3, [color.red / 255, color.green / 255, color.blue / 255]);
this.queue_repaint();
}
_updateFloatUniform(location, value) {
if (!location)
return;
this.set_uniform_float(location, 1, [value]);
this.queue_repaint();
}
set color(c) {
if (this._color.equal(c))
return;
this._color = c;
this.notify('color');
this._updateColorUniform(this._colorLocation, this._color);
}
set chroma(c) {
if (this._chroma.equal(c))
return;
this._chroma = c;
this.notify('chroma');
this._updateColorUniform(this._chromaLocation, this._chroma);
}
set threshold(value) {
if (this._threshold === value)
return;
this._threshold = value;
this.notify('threshold');
this._updateFloatUniform(this._thresholdLocation, this._threshold);
}
set smoothing(value) {
if (this._smoothing === value)
return;
this._smoothing = value;
this.notify('smoothing');
this._updateFloatUniform(this._smoothingLocation, this._smoothing);
}
vfunc_build_pipeline() {
// Conversion parameters from https://en.wikipedia.org/wiki/YCbCr
const decl = `
vec3 rgb2yCrCb(vec3 c) { \n
float y = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b; \n
float cr = 0.7133 * (c.r - y); \n
float cb = 0.5643 * (c.b - y); \n
return vec3(y, cr, cb); \n
} \n
\n
uniform vec3 chroma_color; \n
uniform vec3 recolor_color; \n
uniform float threshold; \n
uniform float smoothing; \n`;
const src = `
vec3 mask = rgb2yCrCb(chroma_color.rgb); \n
vec3 yCrCb = rgb2yCrCb(cogl_color_out.rgb); \n
float blend = \n
smoothstep(threshold, \n
threshold + smoothing, \n
distance(yCrCb.gb, mask.gb)); \n
cogl_color_out.rgb = \n
mix(recolor_color, cogl_color_out.rgb, blend); \n`;
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, src, false);
}
});
var PickPixel = GObject.registerClass(
class PickPixel extends St.Widget {
_init() {
_init(screenshot) {
super._init({ visible: false, reactive: true });
this._screenshot = screenshot;
this._result = null;
this._color = null;
this._inPick = false;
Main.uiGroup.add_actor(this);
@ -393,16 +527,44 @@ class PickPixel extends St.Widget {
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this.add_constraint(constraint);
const action = new Clutter.ClickAction();
action.connect('clicked', async () => {
await this._pickColor(...action.get_coords());
this._result = this._color;
this._grabHelper.ungrab();
});
this.add_action(action);
this._recolorEffect = new RecolorEffect({
chroma: new Clutter.Color({
red: 80,
green: 219,
blue: 181,
}),
threshold: 0.04,
smoothing: 0.07,
});
this._previewCursor = new St.Icon({
icon_name: 'color-pick',
icon_size: Meta.prefs_get_cursor_size(),
effect: this._recolorEffect,
visible: false,
});
Main.uiGroup.add_actor(this._previewCursor);
}
async pickAsync() {
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
global.display.set_cursor(Meta.Cursor.BLANK);
Main.uiGroup.set_child_above_sibling(this, null);
this.show();
this._pickColor(...global.get_pointer());
await this._grabHelper.grabAsync({ actor: this });
global.display.set_cursor(Meta.Cursor.DEFAULT);
this._previewCursor.destroy();
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this.destroy();
@ -412,10 +574,25 @@ class PickPixel extends St.Widget {
return this._result;
}
vfunc_button_release_event(buttonEvent) {
let { x, y } = buttonEvent;
this._result = new Graphene.Point({ x, y });
this._grabHelper.ungrab();
async _pickColor(x, y) {
if (this._inPick)
return;
this._inPick = true;
this._previewCursor.set_position(x, y);
[this._color] = await this._screenshot.pick_color(x, y);
this._inPick = false;
if (!this._color)
return;
this._recolorEffect.color = this._color;
this._previewCursor.show();
}
vfunc_motion_event(motionEvent) {
const { x, y } = motionEvent;
this._pickColor(x, y);
return Clutter.EVENT_PROPAGATE;
}
});

View File

@ -6,17 +6,17 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const AppDisplay = imports.ui.appDisplay;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const RemoteSearch = imports.ui.remoteSearch;
const Util = imports.misc.util;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
var MAX_LIST_SEARCH_RESULTS_ROWS = 5;
var MAX_GRID_SEARCH_RESULTS_ROWS = 1;
var MaxWidthBox = GObject.registerClass(
class MaxWidthBox extends St.BoxLayout {
vfunc_allocate(box, flags) {
vfunc_allocate(box) {
let themeNode = this.get_theme_node();
let maxWidth = themeNode.get_max_width();
let availWidth = box.x2 - box.x1;
@ -28,7 +28,7 @@ class MaxWidthBox extends St.BoxLayout {
adjustedBox.x2 -= Math.floor(excessWidth / 2);
}
super.vfunc_allocate(adjustedBox, flags);
super.vfunc_allocate(adjustedBox);
}
});
@ -219,8 +219,7 @@ var SearchResultsBase = GObject.registerClass({
_ensureResultActors(results, callback) {
let metasNeeded = results.filter(
resultId => this._resultDisplays[resultId] === undefined
);
resultId => this._resultDisplays[resultId] === undefined);
if (metasNeeded.length === 0) {
callback(true);
@ -349,18 +348,140 @@ class ListSearchResults extends SearchResultsBase {
}
});
var GridSearchResultsLayout = GObject.registerClass({
Properties: {
'spacing': GObject.ParamSpec.int('spacing', 'Spacing', 'Spacing',
GObject.ParamFlags.READWRITE, 0, GLib.MAXINT32, 0),
},
}, class GridSearchResultsLayout extends Clutter.LayoutManager {
_init() {
super._init();
this._spacing = 0;
}
vfunc_set_container(container) {
this._container = container;
}
vfunc_get_preferred_width(container, forHeight) {
let minWidth = 0;
let natWidth = 0;
let first = true;
for (let child of container) {
if (!child.visible)
continue;
const [childMinWidth, childNatWidth] = child.get_preferred_width(forHeight);
minWidth = Math.max(minWidth, childMinWidth);
natWidth += childNatWidth;
if (first)
first = false;
else
natWidth += this._spacing;
}
return [minWidth, natWidth];
}
vfunc_get_preferred_height(container, forWidth) {
let minHeight = 0;
let natHeight = 0;
for (let child of container) {
if (!child.visible)
continue;
const [childMinHeight, childNatHeight] = child.get_preferred_height(forWidth);
minHeight = Math.max(minHeight, childMinHeight);
natHeight = Math.max(natHeight, childNatHeight);
}
return [minHeight, natHeight];
}
vfunc_allocate(container, box) {
const width = box.get_width();
const childBox = new Clutter.ActorBox();
childBox.x1 = 0;
childBox.y1 = 0;
let first = true;
for (let child of container) {
if (!child.visible)
continue;
if (first)
first = false;
else
childBox.x1 += this._spacing;
const [childWidth] = child.get_preferred_width(-1);
const [childHeight] = child.get_preferred_height(-1);
childBox.set_size(childWidth, childHeight);
if (childBox.x1 + childWidth > width)
return;
child.allocate(childBox);
childBox.x1 += childWidth;
}
}
columnsForWidth(width) {
if (!this._container)
return -1;
const [minWidth] = this.get_preferred_width(this._container, -1);
if (minWidth === 0)
return -1;
let nCols = 0;
while (width > minWidth) {
width -= minWidth;
if (nCols > 0)
width -= this._spacing;
nCols++;
}
return nCols;
}
get spacing() {
return this._spacing;
}
set spacing(v) {
if (this._spacing === v)
return;
this._spacing = v;
this.layout_changed();
}
});
var GridSearchResults = GObject.registerClass(
class GridSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._grid = new St.Widget({ style_class: 'grid-search-results' });
this._grid.layout_manager = new GridSearchResultsLayout();
this._bin = new St.Bin({ x_align: Clutter.ActorAlign.CENTER });
this._bin.set_child(this._grid);
this._grid.connect('style-changed', () => {
const node = this._grid.get_theme_node();
this._grid.layout_manager.spacing = node.get_length('spacing');
});
this._resultDisplayBin.set_child(this._bin);
this._resultDisplayBin.set_child(new St.Bin({
child: this._grid,
x_align: Clutter.ActorAlign.CENTER,
}));
}
_onDestroy() {
@ -400,12 +521,11 @@ class GridSearchResults extends SearchResultsBase {
if (width == 0)
return -1;
let nCols = this._grid.columnsForWidth(width);
return nCols * this._grid.getRowLimit();
return this._grid.layout_manager.columnsForWidth(width);
}
_clearResultDisplay() {
this._grid.removeAll();
this._grid.remove_all_children();
}
_createResultDisplay(meta) {
@ -414,14 +534,15 @@ class GridSearchResults extends SearchResultsBase {
}
_addItem(display) {
this._grid.addItem(display);
this._grid.add_child(display);
}
getFirstResult() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0);
else
return null;
for (let child of this._grid) {
if (child.visible)
return child;
}
return null;
}
});
@ -431,6 +552,9 @@ var SearchResultsView = GObject.registerClass({
_init() {
super._init({ name: 'searchResults', vertical: true });
this._parentalControlsManager = ParentalControlsManager.getDefault();
this._parentalControlsManager.connect('app-filter-changed', this._reloadRemoteProviders.bind(this));
this._content = new MaxWidthBox({
name: 'searchResultsContent',
vertical: true,
@ -505,6 +629,11 @@ var SearchResultsView = GObject.registerClass({
_registerProvider(provider) {
provider.searchInProgress = false;
// Filter out unwanted providers.
if (provider.appInfo && !this._parentalControlsManager.shouldShowApp(provider.appInfo))
return;
this._providers.push(provider);
this._ensureProviderDisplay(provider);
}

View File

@ -295,8 +295,8 @@ var ShellMountPasswordDialog = GObject.registerClass({
this._keyfilesLabel = new St.Label({ visible: false });
this._keyfilesLabel.clutter_text.set_markup(
/* Translators: %s is the Disks application */
_("To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead.").format(disksApp.get_name())
);
_('To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead.')
.format(disksApp.get_name()));
this._keyfilesLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._keyfilesLabel.clutter_text.line_wrap = true;
content.add_child(this._keyfilesLabel);
@ -464,8 +464,7 @@ var ShellMountPasswordDialog = GObject.registerClass({
/* Translators: %s is the Disks application */
_("Unable to start %s").format(app.get_name()),
/* Translators: %s is the Disks application */
_("Couldnt find the %s application").format(app.get_name())
);
_('Couldnt find the %s application').format(app.get_name()));
}
this._onCancelButton();
}

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const { Gio, GnomeBluetooth, GObject } = imports.gi;
const { Gio, GLib, GnomeBluetooth, GObject } = imports.gi;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
@ -35,7 +35,7 @@ class Indicator extends PanelMenu.SystemIndicator {
this._sync();
});
this._proxy.connect('g-properties-changed', this._sync.bind(this));
this._proxy.connect('g-properties-changed', this._queueSync.bind(this));
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
this._item.icon.icon_name = 'bluetooth-active-symbolic';
@ -49,15 +49,27 @@ class Indicator extends PanelMenu.SystemIndicator {
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
this.menu.addMenuItem(this._item);
this._syncId = 0;
this._adapter = null;
this._client = new GnomeBluetooth.Client();
this._model = this._client.get_model();
this._model.connect('row-changed', this._sync.bind(this));
this._model.connect('row-deleted', this._sync.bind(this));
this._model.connect('row-deleted', this._queueSync.bind(this));
this._model.connect('row-changed', this._queueSync.bind(this));
this._model.connect('row-inserted', this._sync.bind(this));
Main.sessionMode.connect('updated', this._sync.bind(this));
this._sync();
}
_setHadSetupDevices(value) {
if (this._hadSetupDevices === value)
return;
this._hadSetupDevices = value;
global.settings.set_boolean(
HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
}
_getDefaultAdapter() {
let [ret, iter] = this._model.get_iter_first();
while (ret) {
@ -96,20 +108,28 @@ class Indicator extends PanelMenu.SystemIndicator {
ret = this._model.iter_next(iter);
}
if (this._hadSetupDevices !== (deviceInfos.length > 0)) {
this._hadSetupDevices = !this._hadSetupDevices;
global.settings.set_boolean(HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
}
return deviceInfos;
}
_queueSync() {
if (this._syncId)
return;
this._syncId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._syncId = 0;
this._sync();
return GLib.SOURCE_REMOVE;
});
}
_sync() {
let adapter = this._getDefaultAdapter();
let devices = this._getDeviceInfos(adapter);
const connectedDevices = devices.filter(dev => dev.connected);
const nConnectedDevices = connectedDevices.length;
const nDevices = devices.length;
if (adapter && this._adapter)
this._setHadSetupDevices(devices.length > 0);
this._adapter = adapter;
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
@ -118,7 +138,7 @@ class Indicator extends PanelMenu.SystemIndicator {
// Remember if there were setup devices and show the menu
// if we've seen setup devices and we're not hard blocked
if (nDevices > 0)
if (this._hadSetupDevices)
this._item.visible = !this._proxy.BluetoothHardwareAirplaneMode;
else
this._item.visible = this._proxy.BluetoothHasAirplaneMode && !this._proxy.BluetoothAirplaneMode;

View File

@ -48,7 +48,9 @@ class Indicator extends PanelMenu.SystemIndicator {
this._item.connect('key-press-event', (actor, event) => {
return this._slider.emit('key-press-event', event);
});
this._item.connect('scroll-event', (actor, event) => {
return this._slider.emit('scroll-event', event);
});
}
_sliderChanged() {

View File

@ -805,8 +805,8 @@ class InputSourceIndicatorContainer extends St.Widget {
}, [0, 0]);
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
// translate box to (0, 0)
box.x2 -= box.x1;
@ -815,7 +815,7 @@ class InputSourceIndicatorContainer extends St.Widget {
box.y1 = 0;
this.get_children().forEach(c => {
c.allocate_align_fill(box, 0.5, 0.5, false, false, flags);
c.allocate_align_fill(box, 0.5, 0.5, false, false);
});
}
});

View File

@ -716,8 +716,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
let connections = client.get_connections();
this._connections = connections.filter(
connection => device.connection_valid(connection)
);
connection => device.connection_valid(connection));
this._apAddedId = device.connect('access-point-added', this._accessPointAdded.bind(this));
this._apRemovedId = device.connect('access-point-removed', this._accessPointRemoved.bind(this));
@ -1863,8 +1862,7 @@ class Indicator extends PanelMenu.SystemIndicator {
_syncVpnConnections() {
let activeConnections = this._client.get_active_connections() || [];
let vpnConnections = activeConnections.filter(
a => a instanceof NM.VpnConnection
);
a => a instanceof NM.VpnConnection);
vpnConnections.forEach(a => {
ensureActiveConnectionProps(a);
});

View File

@ -112,12 +112,12 @@ class Indicator extends PanelMenu.SystemIndicator {
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
? '-charging' : '';
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
let icon;
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED ||
fillLevel === 100)
icon = 'battery-level-100-charged-symbolic';
else
icon = 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
const charged =
this._proxy.State === UPower.DeviceState.FULLY_CHARGED ||
(this._proxy.State === UPower.DeviceState.CHARGING && fillLevel === 100);
const icon = charged
? 'battery-level-100-charged-symbolic'
: 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
// Make sure we fall back to fallback-icon-name and not GThemedIcon's
// default fallbacks
@ -139,7 +139,7 @@ class Indicator extends PanelMenu.SystemIndicator {
label = _("%d\u2009%%").format(100);
else
label = _("%d\u2009%%").format(this._proxy.Percentage);
this._percentageLabel.clutter_text.set_markup('<span size="smaller">' + label + '</span>');
this._percentageLabel.text = label;
// The status label
this._item.label.text = this._getStatus();

View File

@ -11,8 +11,7 @@ class RemoteAccessApplet extends PanelMenu.SystemIndicator {
_init() {
super._init();
let backend = Meta.get_backend();
let controller = backend.get_remote_access_controller();
let controller = global.backend.get_remote_access_controller();
if (!controller)
return;

View File

@ -82,8 +82,7 @@ class Indicator extends PanelMenu.SystemIndicator {
});
let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app(
'gnome-control-center.desktop'
);
'gnome-control-center.desktop');
if (app) {
let [icon, name] = [app.app_info.get_icon().names[0],
app.get_name()];

View File

@ -56,6 +56,9 @@ var StreamSlider = class {
this.item.connect('key-press-event', (actor, event) => {
return this._slider.emit('key-press-event', event);
});
this.item.connect('scroll-event', (actor, event) => {
return this._slider.emit('scroll-event', event);
});
this._stream = null;
this._volumeCancellable = null;

View File

@ -66,8 +66,8 @@ var SwitcherPopup = GObject.registerClass({
this._disableHover();
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let childBox = new Clutter.ActorBox();
let primary = Main.layoutManager.primaryMonitor;
@ -84,7 +84,7 @@ var SwitcherPopup = GObject.registerClass({
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.allocate(childBox, flags);
this._switcherList.allocate(childBox);
}
_initialSelection(backward, _binding) {
@ -317,7 +317,7 @@ var SwitcherPopup = GObject.registerClass({
this.ease({
opacity: 0,
duration: POPUP_FADE_OUT_TIME,
mode: Clutter.Animation.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.destroy(),
});
} else {
@ -591,8 +591,8 @@ var SwitcherList = GObject.registerClass({
return themeNode.adjust_preferred_height(maxChildMin, maxChildNat);
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let contentBox = this.get_theme_node().get_content_box(box);
let width = contentBox.x2 - contentBox.x1;
@ -606,7 +606,7 @@ var SwitcherList = GObject.registerClass({
let childBox = new Clutter.ActorBox();
let scrollable = minListWidth > width;
this._scrollView.allocate(contentBox, flags);
this._scrollView.allocate(contentBox);
let arrowWidth = Math.floor(leftPadding / 3);
let arrowHeight = arrowWidth * 2;
@ -614,7 +614,7 @@ var SwitcherList = GObject.registerClass({
childBox.y1 = this.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._leftArrow.allocate(childBox, flags);
this._leftArrow.allocate(childBox);
this._leftArrow.opacity = this._scrollableLeft && scrollable ? 255 : 0;
arrowWidth = Math.floor(rightPadding / 3);
@ -623,7 +623,7 @@ var SwitcherList = GObject.registerClass({
childBox.y1 = this.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._rightArrow.allocate(childBox, flags);
this._rightArrow.allocate(childBox);
this._rightArrow.opacity = this._scrollableRight && scrollable ? 255 : 0;
}
});

View File

@ -1,228 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, addCaller, addTween, getTweenCount, removeTweens,
pauseTweens, resumeTweens, registerSpecialProperty,
registerSpecialPropertyModifier, registerSpecialPropertySplitter */
const { Clutter, GLib, Shell } = imports.gi;
const Signals = imports.signals;
const Tweener = imports.tweener.tweener;
const { adjustAnimationTime } = imports.ui.environment;
// This is a wrapper around imports.tweener.tweener that adds a bit of
// Clutter integration. If the tweening target is a Clutter.Actor, then
// the tweenings will automatically be removed if the actor is destroyed.
// ActionScript Tweener methods that imports.tweener.tweener doesn't
// currently implement: getTweens, getVersion, registerTransition,
// setTimeScale, updateTime.
// imports.tweener.tweener methods that we don't re-export:
// pauseAllTweens, removeAllTweens, resumeAllTweens. (It would be hard
// to clean up properly after removeAllTweens, and also, any code that
// calls any of these is almost certainly wrong anyway, because they
// affect the entire application.)
// Called from Main.start
function init() {
Tweener.setFrameTicker(new ClutterFrameTicker());
}
function addCaller(target, tweeningParameters) {
_wrapTweening(target, tweeningParameters);
Tweener.addCaller(target, tweeningParameters);
}
function addTween(target, tweeningParameters) {
_wrapTweening(target, tweeningParameters);
Tweener.addTween(target, tweeningParameters);
}
function _wrapTweening(target, tweeningParameters) {
let state = _getTweenState(target);
if (!state.destroyedId) {
if (target instanceof Clutter.Actor) {
state.actor = target;
state.destroyedId = target.connect('destroy', _actorDestroyed);
} else if (target.actor && target.actor instanceof Clutter.Actor) {
state.actor = target.actor;
state.destroyedId = target.actor.connect('destroy', () => _actorDestroyed(target));
}
}
let { time, delay } = tweeningParameters;
if (!isNaN(time))
tweeningParameters['time'] = adjustAnimationTime(1000 * time) / 1000;
if (!isNaN(delay))
tweeningParameters['delay'] = adjustAnimationTime(1000 * delay) / 1000;
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
}
function _getTweenState(target) {
// If we were paranoid, we could keep a plist mapping targets to
// states... but we're not that paranoid.
if (!target.__ShellTweenerState)
target.__ShellTweenerState = {};
return target.__ShellTweenerState;
}
function _resetTweenState(target) {
let state = target.__ShellTweenerState;
if (state) {
if (state.destroyedId)
state.actor.disconnect(state.destroyedId);
}
target.__ShellTweenerState = {};
}
function _addHandler(target, params, name, handler) {
if (params[name]) {
let oldHandler = params[name];
let oldScope = params[`${name}Scope`];
let oldParams = params[`${name}Params`];
let eventScope = oldScope ? oldScope : target;
params[name] = () => {
oldHandler.apply(eventScope, oldParams);
handler(target);
};
} else {
params[name] = () => handler(target);
}
}
function _actorDestroyed(target) {
_resetTweenState(target);
Tweener.removeTweens(target);
}
function _tweenCompleted(target) {
if (!isTweening(target))
_resetTweenState(target);
}
function getTweenCount(scope) {
return Tweener.getTweenCount(scope);
}
// imports.tweener.tweener doesn't provide this method (which exists
// in the ActionScript version) but it's easy to implement.
function isTweening(scope) {
return Tweener.getTweenCount(scope) != 0;
}
function removeTweens(...args) {
if (Tweener.removeTweens(args)) {
let [scope] = args;
// If we just removed the last active tween, clean up
if (Tweener.getTweenCount(scope) == 0)
_tweenCompleted(scope);
return true;
} else {
return false;
}
}
function pauseTweens(...args) {
return Tweener.pauseTweens(...args);
}
function resumeTweens(...args) {
return Tweener.resumeTweens(...args);
}
function registerSpecialProperty(...args) {
Tweener.registerSpecialProperty(...args);
}
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
Tweener.registerSpecialPropertyModifier(name, modifyFunction, getFunction);
}
function registerSpecialPropertySplitter(name, splitFunction, parameters) {
Tweener.registerSpecialPropertySplitter(name, splitFunction, parameters);
}
// The 'FrameTicker' object is an object used to feed new frames to
// Tweener so it can update values and redraw. The default frame
// ticker for Tweener just uses a simple timeout at a fixed frame rate
// and has no idea of "catching up" by dropping frames.
//
// We substitute it with custom frame ticker here that connects
// Tweener to a Clutter.TimeLine. Now, Clutter.Timeline itself isn't a
// whole lot more sophisticated than a simple timeout at a fixed frame
// rate, but at least it knows how to drop frames. (See
// HippoAnimationManager for a more sophisticated view of continuous
// time updates; even better is to pay attention to the vertical
// vblank and sync to that when possible.)
//
var ClutterFrameTicker = class {
constructor() {
// We don't have a finite duration; tweener will tell us to stop
// when we need to stop, so use 1000 seconds as "infinity", and
// set the timeline to loop. Doing this means we have to track
// time ourselves, since clutter timeline's time will cycle
// instead of strictly increase.
this._timeline = new Clutter.Timeline({ duration: 1000 * 1000 });
this._timeline.set_loop(true);
this._startTime = -1;
this._currentTime = -1;
this._timeline.connect('new-frame', () => {
this._onNewFrame();
});
let perfLog = Shell.PerfLog.get_default();
perfLog.define_event("tweener.framePrepareStart",
"Start of a new animation frame",
"");
perfLog.define_event("tweener.framePrepareDone",
"Finished preparing frame",
"");
}
get FRAME_RATE() {
return 60;
}
_onNewFrame() {
// If there is a lot of setup to start the animation, then
// first frame number we get from clutter might be a long ways
// into the animation (or the animation might even be done).
// That looks bad, so we always start at the first frame of the
// animation then only do frame dropping from there.
if (this._startTime < 0)
this._startTime = GLib.get_monotonic_time() / 1000.0;
// currentTime is in milliseconds
let perfLog = Shell.PerfLog.get_default();
this._currentTime = GLib.get_monotonic_time() / 1000.0 - this._startTime;
perfLog.event("tweener.framePrepareStart");
this.emit('prepare-frame');
perfLog.event("tweener.framePrepareDone");
}
getTime() {
return this._currentTime;
}
start() {
this._timeline.start();
global.begin_work();
}
stop() {
this._timeline.stop();
this._startTime = -1;
this._currentTime = -1;
global.end_work();
}
};
Signals.addSignalMethods(ClutterFrameTicker.prototype);

View File

@ -405,7 +405,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
return this._stack.get_preferred_height(forWidth);
}
vfunc_allocate(container, box, flags) {
vfunc_allocate(container, box) {
let [width, height] = box.get_size();
let tenthOfHeight = height / 10.0;
@ -432,7 +432,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
actorBox.x2 = columnX1 + columnWidth;
actorBox.y2 = actorBox.y1 + maxNotificationsHeight;
this._notifications.allocate(actorBox, flags);
this._notifications.allocate(actorBox);
// Authentication Box
let stackY = Math.min(
@ -444,7 +444,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
actorBox.x2 = columnX1 + columnWidth;
actorBox.y2 = stackY + stackHeight;
this._stack.allocate(actorBox, flags);
this._stack.allocate(actorBox);
// Switch User button
if (this._switchUserButton.visible) {
@ -461,7 +461,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
actorBox.x2 = actorBox.x1 + natWidth;
actorBox.y2 = actorBox.y1 + natHeight;
this._switchUserButton.allocate(actorBox, flags);
this._switchUserButton.allocate(actorBox);
}
}
});
@ -605,7 +605,7 @@ var UnlockDialog = GObject.registerClass({
this._showPrompt();
if (GLib.unichar_isgraph(unichar))
this.addCharacter(unichar);
this._authPrompt.addCharacter(unichar);
return Clutter.EVENT_PROPAGATE;
}
@ -835,11 +835,6 @@ var UnlockDialog = GObject.registerClass({
this._authPrompt.cancel();
}
addCharacter(unichar) {
this._showPrompt();
this._authPrompt.addCharacter(unichar);
}
finish(onComplete) {
this._ensureAuthPrompt();
this._authPrompt.finish(onComplete);

View File

@ -144,8 +144,8 @@ class UserWidgetLabel extends St.Widget {
}
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
@ -164,7 +164,7 @@ class UserWidgetLabel extends St.Widget {
childBox.x2 = availWidth;
childBox.y2 = availHeight;
this._currentLabel.allocate(childBox, flags);
this._currentLabel.allocate(childBox);
}
vfunc_paint(paintContext) {

View File

@ -82,8 +82,10 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
}
_formatCountDown() {
let fmt = ngettext("Settings changes will revert in %d second",
"Settings changes will revert in %d seconds");
const fmt = ngettext(
'Settings changes will revert in %d second',
'Settings changes will revert in %d seconds',
this._countDown);
return fmt.format(this._countDown);
}
@ -898,35 +900,47 @@ var WindowManager = class {
global.display.connect('init-xserver', (display, task) => {
IBusManager.getIBusManager().restartDaemon(['--xim']);
Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail');
/* Leave this watchdog timeout so don't block indefinitely here */
let timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 5, () => {
Gio.DBus.session.unwatch_name(watchId);
log('Warning: Failed to start gsd-xsettings');
task.return_boolean(true);
timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
try {
if (!Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail'))
log('Not starting gsd-xsettings; waiting for gnome-session to do so');
/* When gsd-xsettings daemon is started, we are good to resume */
let watchId = Gio.DBus.session.watch_name(
'org.gnome.SettingsDaemon.XSettings',
Gio.BusNameWatcherFlags.NONE,
() => {
/* Leave this watchdog timeout so don't block indefinitely here */
let timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 5, () => {
Gio.DBus.session.unwatch_name(watchId);
if (timeoutId > 0) {
task.return_boolean(true);
GLib.source_remove(timeoutId);
}
},
null);
log('Warning: Failed to start gsd-xsettings');
task.return_boolean(true);
timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
/* When gsd-xsettings daemon is started, we are good to resume */
let watchId = Gio.DBus.session.watch_name(
'org.gnome.SettingsDaemon.XSettings',
Gio.BusNameWatcherFlags.NONE,
() => {
Gio.DBus.session.unwatch_name(watchId);
if (timeoutId > 0) {
task.return_boolean(true);
GLib.source_remove(timeoutId);
}
},
null);
} catch (e) {
log('Error starting gsd-xsettings: %s'.format(e.message));
task.return_boolean(true);
}
return true;
});
global.display.connect('x11-display-closing', () => {
if (!Meta.is_wayland_compositor())
return;
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
try {
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
} catch (e) {
log('Error stopping gsd-xsettings: %s'.format(e.message));
}
IBusManager.getIBusManager().restartDaemon();
});

View File

@ -51,35 +51,22 @@ class WindowCloneLayout extends Clutter.LayoutManager {
this.layout_changed();
}
_makeBoxForWindow(window) {
// We need to adjust the position of the actor because of the
// consequences of invisible borders -- in reality, the texture
// has an extra set of "padding" around it that we need to trim
// down.
// The bounding box is based on the (visible) frame rect, while
// the buffer rect contains everything, including the invisible
// border padding.
let bufferRect = window.get_buffer_rect();
let box = new Clutter.ActorBox();
box.set_origin(bufferRect.x - this._boundingBox.x,
bufferRect.y - this._boundingBox.y);
box.set_size(bufferRect.width, bufferRect.height);
return box;
}
vfunc_get_preferred_height(_container, _forWidth) {
return [this._boundingBox.height, this._boundingBox.height];
return [0, this._boundingBox.height];
}
vfunc_get_preferred_width(_container, _forHeight) {
return [this._boundingBox.width, this._boundingBox.width];
return [0, this._boundingBox.width];
}
vfunc_allocate(container, box, flags) {
vfunc_allocate(container, box) {
// If the scale isn't 1, we weren't allocated our preferred size
// and have to scale the children allocations accordingly.
const scaleX = box.get_width() / this._boundingBox.width;
const scaleY = box.get_height() / this._boundingBox.height;
const childBox = new Clutter.ActorBox();
container.get_children().forEach(child => {
let realWindow;
if (child == container._windowClone)
@ -87,8 +74,20 @@ class WindowCloneLayout extends Clutter.LayoutManager {
else
realWindow = child.source;
child.allocate(this._makeBoxForWindow(realWindow.meta_window),
flags);
const bufferRect = realWindow.meta_window.get_buffer_rect();
childBox.set_origin(
bufferRect.x - this._boundingBox.x,
bufferRect.y - this._boundingBox.y);
const [, , natWidth, natHeight] = child.get_preferred_size();
childBox.set_size(natWidth, natHeight);
childBox.x1 *= scaleX;
childBox.x2 *= scaleX;
childBox.y1 *= scaleY;
childBox.y2 *= scaleY;
child.allocate(childBox);
});
}
});
@ -155,7 +154,8 @@ var WindowClone = GObject.registerClass({
this._updateAttachedDialogs();
this._computeBoundingBox();
this.set_translation(this._boundingBox.x, this._boundingBox.y, 0);
this.x = this._boundingBox.x;
this.y = this._boundingBox.y;
this._computeWindowCenter();
@ -240,6 +240,9 @@ var WindowClone = GObject.registerClass({
this._onMetaWindowSizeChanged();
});
Shell.util_set_hidden_from_pick(clone, true);
this.add_child(clone);
}
@ -263,18 +266,6 @@ var WindowClone = GObject.registerClass({
return this._boundingBox;
}
get width() {
return this._boundingBox.width;
}
get height() {
return this._boundingBox.height;
}
getOriginalPosition() {
return [this._boundingBox.x, this._boundingBox.y];
}
_computeBoundingBox() {
let rect = this.metaWindow.get_frame_rect();
@ -868,7 +859,7 @@ var LayoutStrategy = class {
// thumbnails is much more important to preserve than the width of
// them, so two windows with equal height, but maybe differering
// widths line up.
let ratio = window.height / this._monitor.height;
let ratio = window.boundingBox.height / this._monitor.height;
// The purpose of this manipulation here is to prevent windows
// from getting too small. For something like a calculator window,
@ -988,11 +979,12 @@ var LayoutStrategy = class {
let window = row.windows[j];
let s = scale * this._computeWindowScale(window) * row.additionalScale;
let cellWidth = window.width * s;
let cellHeight = window.height * s;
let cellWidth = window.boundingBox.width * s;
let cellHeight = window.boundingBox.height * s;
s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE);
let cloneWidth = window.width * s;
let cloneWidth = window.boundingBox.width * s;
const cloneHeight = window.boundingBox.height * s;
let cloneX = x + (cellWidth - cloneWidth) / 2;
let cloneY = row.y + row.height * row.additionalScale - cellHeight + compensation;
@ -1001,7 +993,7 @@ var LayoutStrategy = class {
cloneX = Math.floor(cloneX);
cloneY = Math.floor(cloneY);
slots.push([cloneX, cloneY, s, window]);
slots.push([cloneX, cloneY, cloneWidth, cloneHeight, window]);
x += cellWidth + this._columnSpacing;
}
}
@ -1046,7 +1038,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
for (let i = 0; i < windows.length; i++) {
let window = windows[i];
let s = this._computeWindowScale(window);
totalWidth += window.width * s;
totalWidth += window.boundingBox.width * s;
}
let idealRowWidth = totalWidth / numRows;
@ -1064,8 +1056,8 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
for (; windowIdx < sortedWindows.length; windowIdx++) {
let window = sortedWindows[windowIdx];
let s = this._computeWindowScale(window);
let width = window.width * s;
let height = window.height * s;
let width = window.boundingBox.width * s;
let height = window.boundingBox.height * s;
row.fullHeight = Math.max(row.fullHeight, height);
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
@ -1340,7 +1332,7 @@ class Workspace extends St.Widget {
for (let i = 0; i < slots.length; i++) {
let slot = slots[i];
let [x, y, scale, clone] = slot;
const [x, y, cellWidth, cellHeight, clone] = slot;
clone.slotId = i;
@ -1349,8 +1341,8 @@ class Workspace extends St.Widget {
if (clone.inDrag)
continue;
let cloneWidth = clone.width * scale;
let cloneHeight = clone.height * scale;
const cloneWidth = cellWidth;
const cloneHeight = cellHeight;
clone.slot = [x, y, cloneWidth, cloneHeight];
let cloneCenter = x + cloneWidth / 2;
@ -1365,10 +1357,10 @@ class Workspace extends St.Widget {
if (!clone.positioned) {
// This window appeared after the overview was already up
// Grow the clone from the center of the slot
clone.translation_x = x + cloneWidth / 2;
clone.translation_y = y + cloneHeight / 2;
clone.scale_x = 0;
clone.scale_y = 0;
clone.x = x + cloneWidth / 2;
clone.y = y + cloneHeight / 2;
clone.width = 0;
clone.height = 0;
clone.positioned = true;
}
@ -1379,10 +1371,10 @@ class Workspace extends St.Widget {
* can be scaled up later */
if (initialPositioning) {
clone.opacity = 0;
clone.scale_x = 0;
clone.scale_y = 0;
clone.translation_x = x;
clone.translation_y = y;
clone.x = x;
clone.y = y;
clone.width = cloneWidth;
clone.height = cloneHeight;
}
clone.ease({
@ -1392,12 +1384,12 @@ class Workspace extends St.Widget {
});
}
this._animateClone(clone, clone.overlay, x, y, scale);
this._animateClone(clone, clone.overlay, x, y, cloneWidth, cloneHeight);
} else {
// cancel any active tweens (otherwise they might override our changes)
clone.remove_all_transitions();
clone.set_translation(x, y, 0);
clone.set_scale(scale, scale);
clone.set_position(x, y);
clone.set_size(cloneWidth, cloneHeight);
clone.set_opacity(255);
clone.overlay.relayout(false);
this._showWindowOverlay(clone, clone.overlay);
@ -1424,12 +1416,10 @@ class Workspace extends St.Widget {
}
}
_animateClone(clone, overlay, x, y, scale) {
_animateClone(clone, overlay, x, y, width, height) {
clone.ease({
translation_x: x,
translation_y: y,
scale_x: scale,
scale_y: scale,
x, y,
width, height,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
@ -1486,11 +1476,14 @@ class Workspace extends St.Widget {
// this point.)
if (win) {
let [stageX, stageY] = clone.get_transformed_position();
let [stageWidth] = clone.get_transformed_size();
const [transformedWidth, transformedHeight] =
clone.get_transformed_size();
win._overviewHint = {
x: stageX,
y: stageY,
scale: stageWidth / clone.width,
width: transformedWidth,
height: transformedHeight,
};
}
clone.destroy();
@ -1566,14 +1559,15 @@ class Workspace extends St.Widget {
if (win._overviewHint) {
let x = win._overviewHint.x - this.x;
let y = win._overviewHint.y - this.y;
let scale = win._overviewHint.scale;
const width = win._overviewHint.width;
const height = win._overviewHint.height;
delete win._overviewHint;
clone.slot = [x, y, clone.width * scale, clone.height * scale];
clone.slot = [x, y, width, height];
clone.positioned = true;
clone.set_translation(x, y, 0);
clone.set_scale(scale, scale);
clone.set_position(x, y);
clone.set_size(width, height);
clone.overlay.relayout(false);
}
@ -1724,11 +1718,10 @@ class Workspace extends St.Widget {
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
clone.scale_x = 1;
clone.scale_y = 1;
clone.translation_x = origX;
clone.translation_y = origY;
clone.x = clone.boundingBox.x;
clone.y = clone.boundingBox.y;
clone.width = clone.boundingBox.width;
clone.height = clone.boundingBox.height;
clone.ease({
opacity,
duration,
@ -1776,12 +1769,11 @@ class Workspace extends St.Widget {
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
clone.ease({
translation_x: origX,
translation_y: origY,
scale_x: 1,
scale_y: 1,
x: clone.boundingBox.x,
y: clone.boundingBox.y,
width: clone.boundingBox.width,
height: clone.boundingBox.height,
opacity: 255,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -1789,8 +1781,8 @@ class Workspace extends St.Widget {
} else {
// The window is hidden, make it shrink and fade it out
clone.ease({
scale_x: 0,
scale_y: 0,
width: 0,
height: 0,
opacity: 0,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -2035,7 +2027,8 @@ class Workspace extends St.Widget {
win._overviewHint = {
x: actor.x,
y: actor.y,
scale: actor.scale_x,
width: actor.width,
heigth: actor.height,
};
let metaWindow = win.get_meta_window();

View File

@ -86,8 +86,8 @@ class WorkspaceSwitcherPopupList extends St.Widget {
return this._getSizeForOppositeOrientation();
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
@ -111,7 +111,7 @@ class WorkspaceSwitcherPopupList extends St.Widget {
} else {
y += this._childHeight + this._itemSpacing;
}
child.allocate(childBox, flags);
child.allocate(childBox);
}
}
});

View File

@ -1204,8 +1204,8 @@ var ThumbnailsBox = GObject.registerClass({
this.queue_relayout();
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
this.set_allocation(box);
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
@ -1299,7 +1299,7 @@ var ThumbnailsBox = GObject.registerClass({
childBox.x2 = x2;
childBox.y1 = Math.round(y);
childBox.y2 = Math.round(y + placeholderHeight);
this._dropPlaceholder.allocate(childBox, flags);
this._dropPlaceholder.allocate(childBox);
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.show();
});
@ -1331,7 +1331,7 @@ var ThumbnailsBox = GObject.registerClass({
childBox.y2 = y1 + portholeHeight;
thumbnail.set_scale(roundedHScale, roundedVScale);
thumbnail.allocate(childBox, flags);
thumbnail.allocate(childBox);
// We round the collapsing portion so that we don't get thumbnails resizing
// during an animation due to differences in rounded, but leave the uncollapsed
@ -1355,6 +1355,6 @@ var ThumbnailsBox = GObject.registerClass({
childBox.x2 += indicatorRightFullBorder;
childBox.y1 = indicatorY1 - indicatorTopFullBorder;
childBox.y2 = indicatorY2 + indicatorBottomFullBorder;
this._indicator.allocate(childBox, flags);
this._indicator.allocate(childBox);
}
});

View File

@ -8,6 +8,7 @@ const SwipeTracker = imports.ui.swipeTracker;
const Workspace = imports.ui.workspace;
var WORKSPACE_SWITCH_TIME = 250;
var SCROLL_TIMEOUT_TIME = 150;
var AnimationType = {
ZOOM: 0,
@ -815,12 +816,11 @@ class WorkspacesDisplay extends St.Widget {
this._canScroll = false;
this._scrollTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
WORKSPACE_SWITCH_TIME, () => {
SCROLL_TIMEOUT_TIME, () => {
this._canScroll = true;
this._scrollTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
);
});
return Clutter.EVENT_STOP;
}

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Meta } = imports.gi;
const { Clutter } = imports.gi;
const Signals = imports.signals;
const DND = imports.ui.dnd;
@ -17,7 +17,7 @@ var XdndHandler = class {
Main.uiGroup.add_actor(this._dummy);
this._dummy.hide();
var dnd = Meta.get_backend().get_dnd();
var dnd = global.backend.get_dnd();
dnd.connect('dnd-enter', this._onEnter.bind(this));
dnd.connect('dnd-position-change', this._onPositionChanged.bind(this));
dnd.connect('dnd-leave', this._onLeave.bind(this));

View File

@ -218,12 +218,12 @@ globals:
ARGV: readonly
Debugger: readonly
GIRepositoryGType: readonly
globalThis: readonly
imports: readonly
Intl: readonly
log: readonly
logError: readonly
print: readonly
printerr: readonly
window: readonly
parserOptions:
ecmaVersion: 2019

View File

@ -1,6 +1,6 @@
project('gnome-shell', 'c',
version: '3.37.0',
meson_version: '>= 0.47.0',
version: '3.37.2',
meson_version: '>= 0.53.0',
license: 'GPLv2+'
)
@ -19,13 +19,13 @@ cogl_pango_pc = 'mutter-cogl-pango-' + mutter_api_version
libmutter_pc = 'libmutter-' + mutter_api_version
ecal_req = '>= 3.33.1'
eds_req = '>= 3.17.2'
eds_req = '>= 3.33.1'
gcr_req = '>= 3.7.5'
gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1'
gjs_req = '>= 1.63.2'
gjs_req = '>= 1.65.1'
gtk_req = '>= 3.15.0'
mutter_req = '>= 3.36.0'
mutter_req = '>= 3.37.2'
polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1'
startup_req = '>= 0.11'
@ -63,16 +63,9 @@ portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals')
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
servicedir = join_paths(datadir, 'dbus-1', 'services')
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
# depend on this version, replace with something like:
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
# define_variable: ['prefix', prefix])
# and uncomment systemd_dep below
systemduserunitdir = join_paths(prefix, 'lib', 'systemd', 'user')
keybindings_dep = dependency('gnome-keybindings', required: false)
if keybindings_dep.found()
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir')
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir', define_variable: ['datadir', datadir])
else
keysdir = join_paths(datadir, 'gnome-control-center', 'keybindings')
endif
@ -122,8 +115,9 @@ endif
if get_option('systemd')
libsystemd_dep = dependency('libsystemd')
# XXX: see systemduserunitdir
# systemd_dep = dependency('systemd')
systemd_dep = dependency('systemd')
systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
define_variable: ['prefix', prefix])
have_systemd = true
else
libsystemd_dep = []
@ -321,8 +315,6 @@ if get_option('man')
summary_dirs += { 'mandir': get_option('mandir') }
endif
if meson.version().version_compare('>= 0.53.0')
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
endif
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')

View File

@ -56,6 +56,7 @@ nl
nn
oc
or
os
pa
pl
pt

View File

@ -94,5 +94,7 @@ subprojects/extensions-tool/src/command-prefs.c
subprojects/extensions-tool/src/command-reset.c
subprojects/extensions-tool/src/command-uninstall.c
subprojects/extensions-tool/src/main.c
subprojects/extensions-tool/src/templates/00-plain.desktop.in
subprojects/extensions-tool/src/templates/indicator.desktop.in
# Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it.
subprojects/gvc/gvc-mixer-control.c

1
po/POTFILES.skip Normal file
View File

@ -0,0 +1 @@
subprojects/extensions-tool/src/templates/indicator/extension.js

1303
po/ca.po

File diff suppressed because it is too large Load Diff

863
po/cs.po

File diff suppressed because it is too large Load Diff

439
po/de.po
View File

@ -22,9 +22,9 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-03-19 14:34+0000\n"
"PO-Revision-Date: 2020-03-20 06:42+0100\n"
"Last-Translator: Wolfgang Stoeggl <c72578@yahoo.de>\n"
"POT-Creation-Date: 2020-05-15 03:04+0000\n"
"PO-Revision-Date: 2020-05-24 00:19+0200\n"
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
@ -409,68 +409,12 @@ msgstr ""
msgid "Network Login"
msgstr "Netzwerkanmeldung"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:4
#: js/extensionPrefs/js/main.js:242
#: js/extensionPrefs/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Erweiterungen"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: js/extensionPrefs/js/main.js:243
msgid "Manage your GNOME Extensions"
msgstr "Ihre GNOME-Erweiterungen verwalten"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"GNOME-Erweiterungen dient der Aktualisierung von Erweiterungen, dem "
"Konfigurieren der Voreinstellungen von Erweiterungen und dem Entfernen oder "
"Deaktivieren nicht gewünschter Erweiterungen."
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "GNOME-Shell-Erweiterungen einrichten"
#: js/extensionPrefs/js/main.js:164
#, javascript-format
msgid "Remove “%s”?"
msgstr "»%s« entfernen?"
#: js/extensionPrefs/js/main.js:165
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Wenn Sie die Erweiterung entfernen, müssen Sie sie erneut herunterladen, um "
"sie wieder zu aktivieren"
#: js/extensionPrefs/js/main.js:168 js/gdm/authPrompt.js:135
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913
msgid "Cancel"
msgstr "Abbrechen"
#: js/extensionPrefs/js/main.js:169
msgid "Remove"
msgstr "Entfernen"
#: js/extensionPrefs/js/main.js:241
msgid "translator-credits"
msgstr ""
"Tim Sabsch <tim@sabsch.com>\n"
"Christian Kirbach <christian.kirbach@gmail.com>, 2020"
#: js/extensionPrefs/js/main.js:285
#: js/extensionPrefs/data/ui/extensions-window.ui:223
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
#: subprojects/extensions-app/data/ui/extensions-window.ui:224
msgid "Somethings gone wrong"
msgstr "Etwas ist schiefgelaufen"
#: js/extensionPrefs/js/main.js:292
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
msgid ""
"Were very sorry, but theres been a problem: the settings for this "
"extension cant be displayed. We recommend that you report the issue to the "
@ -480,106 +424,25 @@ msgstr ""
"Erweiterung können nicht angezeigt werden. Wir empfehlen, dass Sie diesen "
"Fehler den Autoren der Erweiterung melden."
#: js/extensionPrefs/js/main.js:299
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
msgid "Technical Details"
msgstr "Technische Details"
#: js/extensionPrefs/js/main.js:334
msgid "Copy Error"
msgstr "Kopierfehler"
#: js/extensionPrefs/js/main.js:361
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
msgid "Homepage"
msgstr "Homepage"
#: js/extensionPrefs/js/main.js:362
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
msgid "Visit extension homepage"
msgstr "Internetseite der Erweiterung besuchen"
#: js/extensionPrefs/js/main.js:479
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d Erweiterung wird bei der nächsten Anmeldung aktualisiert."
msgstr[1] "%d Erweiterungen werden bei der nächsten Anmeldung aktualisiert."
#: js/extensionPrefs/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Beschreibung"
#: js/extensionPrefs/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Version"
#: js/extensionPrefs/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Autor"
#: js/extensionPrefs/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Webseite"
#: js/extensionPrefs/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Entfernen …"
#: js/extensionPrefs/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Hilfe"
#: js/extensionPrefs/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Info zu Erweiterungen"
#: js/extensionPrefs/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Besuchen Sie <a href=\"https://extensions.gnome.org\">extensions.gnome.org</"
"a>, um Erweiterungen zu finden und hinzuzufügen."
#: js/extensionPrefs/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Warnung"
#: js/extensionPrefs/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Erweiterungen können Probleme am System verursachen, darunter auch "
"Leistungsprobleme. Sollten Sie auf Probleme mit Ihrem System stoßen, wird "
"die Deaktivierung aller Erweiterungen empfohlen."
#: js/extensionPrefs/data/ui/extensions-window.ui:134
msgid "Manually Installed"
msgstr "Manuell installiert"
#: js/extensionPrefs/data/ui/extensions-window.ui:158
msgid "Built-In"
msgstr "Mitgeliefert"
#: js/extensionPrefs/data/ui/extensions-window.ui:199
msgid "No Installed Extensions"
msgstr "Keine installierten Erweiterungen"
#: js/extensionPrefs/data/ui/extensions-window.ui:235
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Tut uns sehr leid, wir konnten keine Liste der installierten Erweiterungen "
"aufstellen. Stellen Sie sicher, dass Sie in GNOME angemeldet sind und "
"versuchen Sie es dann erneut."
#: js/extensionPrefs/data/ui/extensions-window.ui:288
msgid "Log Out…"
msgstr "Abmelden …"
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:372 js/ui/extensionDownloader.js:181
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
msgid "Cancel"
msgstr "Abbrechen"
#. Cisco LEAP
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
@ -631,71 +494,71 @@ msgid "(or swipe finger)"
msgstr "(oder wischen Sie mit einem Finger)"
#. Translators: The name of the power-off action in search
#: js/misc/systemActions.js:89
#: js/misc/systemActions.js:93
msgctxt "search-result"
msgid "Power Off"
msgstr "Ausschalten"
#. Translators: A list of keywords that match the power-off action, separated by semicolons
#: js/misc/systemActions.js:92
#: js/misc/systemActions.js:96
msgid "power off;shutdown;reboot;restart;halt;stop"
msgstr "ausschalten;herunterfahren;neustarten;halten;stoppen"
#. Translators: The name of the lock screen action in search
#: js/misc/systemActions.js:97
#: js/misc/systemActions.js:101
msgctxt "search-result"
msgid "Lock Screen"
msgstr "Bildschirm sperren"
#. Translators: A list of keywords that match the lock screen action, separated by semicolons
#: js/misc/systemActions.js:100
#: js/misc/systemActions.js:104
msgid "lock screen"
msgstr "Bildschirm sperren"
#. Translators: The name of the logout action in search
#: js/misc/systemActions.js:105
#: js/misc/systemActions.js:109
msgctxt "search-result"
msgid "Log Out"
msgstr "Abmelden"
#. Translators: A list of keywords that match the logout action, separated by semicolons
#: js/misc/systemActions.js:108
#: js/misc/systemActions.js:112
msgid "logout;log out;sign off"
msgstr "abmelden;verlassen"
#. Translators: The name of the suspend action in search
#: js/misc/systemActions.js:113
#: js/misc/systemActions.js:117
msgctxt "search-result"
msgid "Suspend"
msgstr "Bereitschaft"
#. Translators: A list of keywords that match the suspend action, separated by semicolons
#: js/misc/systemActions.js:116
#: js/misc/systemActions.js:120
msgid "suspend;sleep"
msgstr "Bereitschaft;Schlafen"
#. Translators: The name of the switch user action in search
#: js/misc/systemActions.js:121
#: js/misc/systemActions.js:125
msgctxt "search-result"
msgid "Switch User"
msgstr "Benutzer wechseln"
#. Translators: A list of keywords that match the switch user action, separated by semicolons
#: js/misc/systemActions.js:124
#: js/misc/systemActions.js:128
msgid "switch user"
msgstr "Benutzer wechseln"
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
#: js/misc/systemActions.js:131
#: js/misc/systemActions.js:135
msgid "lock orientation;unlock orientation;screen;rotation"
msgstr "Hochformat;Querformat;sperren;entsperren;Bildschirm;Drehung;drehen"
#: js/misc/systemActions.js:251
#: js/misc/systemActions.js:255
msgctxt "search-result"
msgid "Unlock Screen Rotation"
msgstr "Bildschirmdrehung entsperren"
#: js/misc/systemActions.js:252
#: js/misc/systemActions.js:256
msgctxt "search-result"
msgid "Lock Screen Rotation"
msgstr "Bildschirmdrehung sperren"
@ -861,54 +724,54 @@ msgstr "Zugriff verhindern"
msgid "Grant Access"
msgstr "Zugriff gewähren"
#: js/ui/appDisplay.js:898
#: js/ui/appDisplay.js:939
msgid "Unnamed Folder"
msgstr "Unbenannter Ordner"
#: js/ui/appDisplay.js:921
#: js/ui/appDisplay.js:962
msgid "Frequently used applications will appear here"
msgstr "Häufig genutzte Anwendungen erscheinen hier"
#: js/ui/appDisplay.js:1056
#: js/ui/appDisplay.js:1097
msgid "Frequent"
msgstr "Häufig"
#: js/ui/appDisplay.js:1063
#: js/ui/appDisplay.js:1104
msgid "All"
msgstr "Alle"
# Fensterüberschrift
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2446 js/ui/panel.js:75
#: js/ui/appDisplay.js:2480 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Offene Fenster"
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82
#: js/ui/appDisplay.js:2500 js/ui/panel.js:82
msgid "New Window"
msgstr "Neues Fenster"
#: js/ui/appDisplay.js:2477
#: js/ui/appDisplay.js:2511
msgid "Launch using Dedicated Graphics Card"
msgstr "Mit dedizierter Grafikkarte starten"
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239
#: js/ui/appDisplay.js:2539 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Aus Favoriten entfernen"
#: js/ui/appDisplay.js:2511
#: js/ui/appDisplay.js:2545
msgid "Add to Favorites"
msgstr "Zu Favoriten hinzufügen"
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93
#: js/ui/appDisplay.js:2555 js/ui/panel.js:93
msgid "Show Details"
msgstr "Details anzeigen"
#: js/ui/appFavorites.js:152
#: js/ui/appFavorites.js:153
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s wurde zu Ihren Favoriten hinzugefügt."
#: js/ui/appFavorites.js:185
#: js/ui/appFavorites.js:186
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s wurde aus Ihren Favoriten entfernt."
@ -929,7 +792,7 @@ msgstr "Kopfhörer"
msgid "Headset"
msgstr "Headset"
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
msgid "Microphone"
msgstr "Mikrofon"
@ -1070,7 +933,7 @@ msgstr "Keine Termine"
msgid "Do Not Disturb"
msgstr "Nicht stören"
#: js/ui/calendar.js:1171
#: js/ui/calendar.js:1176
msgid "Clear"
msgstr "Leeren"
@ -1223,7 +1086,7 @@ msgstr ""
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: js/ui/components/telepathyClient.js:787
#: js/ui/components/telepathyClient.js:823
#, javascript-format
msgid "%s is now known as %s"
msgstr "%s heißt jetzt %s"
@ -1268,23 +1131,23 @@ msgstr "Weltuhren hinzufügen …"
msgid "World Clocks"
msgstr "Weltuhren"
#: js/ui/dateMenu.js:279
#: js/ui/dateMenu.js:289
msgid "Weather"
msgstr "Wetter"
#: js/ui/dateMenu.js:394
#: js/ui/dateMenu.js:418
msgid "Select a location…"
msgstr "Ort auswählen …"
#: js/ui/dateMenu.js:407
#: js/ui/dateMenu.js:426
msgid "Loading…"
msgstr "Wird geladen …"
#: js/ui/dateMenu.js:417
#: js/ui/dateMenu.js:436
msgid "Go online for weather information"
msgstr "Gehen Sie Online, um Wetterinformationen beziehen zu können"
#: js/ui/dateMenu.js:419
#: js/ui/dateMenu.js:438
msgid "Weather information is currently unavailable"
msgstr "Wetterinformationen sind momentan nicht verfügbar"
@ -1425,35 +1288,35 @@ msgid "Other users are logged in"
msgstr "Andere Benutzer sind angemeldet"
#. Translators: Remote here refers to a remote session, like a ssh login
#: js/ui/endSessionDialog.js:588
#: js/ui/endSessionDialog.js:586
#, javascript-format
msgid "%s (remote)"
msgstr "%s (Entfernt)"
#. Translators: Console here refers to a tty like a VT console
#: js/ui/endSessionDialog.js:591
#: js/ui/endSessionDialog.js:589
#, javascript-format
msgid "%s (console)"
msgstr "%s (Konsole)"
#: js/ui/extensionDownloader.js:181
#: js/ui/extensionDownloader.js:185
msgid "Install"
msgstr "Installieren"
#: js/ui/extensionDownloader.js:187
#: js/ui/extensionDownloader.js:191
msgid "Install Extension"
msgstr "Erweiterung installieren"
#: js/ui/extensionDownloader.js:188
#: js/ui/extensionDownloader.js:192
#, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "»%s« von extensions.gnome.org herunterladen und installieren?"
#: js/ui/extensionSystem.js:228
#: js/ui/extensionSystem.js:252
msgid "Extension Updates Available"
msgstr "Aktualisierungen für Erweiterungen verfügbar"
#: js/ui/extensionSystem.js:229
#: js/ui/extensionSystem.js:253
msgid "Extension updates are ready to be installed."
msgstr "Aktualisierungen für Erweiterungen stehen bereit zur Installation."
@ -1602,11 +1465,11 @@ msgstr "Quelle zeigen"
msgid "Web Page"
msgstr "Webseite"
#: js/ui/main.js:274
#: js/ui/main.js:279
msgid "Logged in as a privileged user"
msgstr "Als privilegierter Benutzer angemeldet"
#: js/ui/main.js:275
#: js/ui/main.js:280
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@ -1615,23 +1478,23 @@ msgstr ""
"Sicherheitsgründen unterlassen werden. Falls möglich, melden Sie sich bitte "
"als normaler Benutzer an."
#: js/ui/main.js:281
#: js/ui/main.js:319
msgid "Screen Lock disabled"
msgstr "Bildschirmsperre deaktiviert"
#: js/ui/main.js:282
#: js/ui/main.js:320
msgid "Screen Locking requires the GNOME display manager."
msgstr "Die Sperrung des Bildschirms erfordert den GNOME Display-Manager."
#: js/ui/messageTray.js:1554
#: js/ui/messageTray.js:1548
msgid "System Information"
msgstr "Systeminformationen"
#: js/ui/mpris.js:199
#: js/ui/mpris.js:204
msgid "Unknown artist"
msgstr "Unbekannter Künstler"
#: js/ui/mpris.js:209
#: js/ui/mpris.js:214
msgid "Unknown title"
msgstr "Unbekannter Titel"
@ -1703,16 +1566,16 @@ msgstr "Beenden"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:434
#: js/ui/panel.js:437
msgid "Activities"
msgstr "Aktivitäten"
#: js/ui/panel.js:713
#: js/ui/panel.js:716
msgctxt "System menu in the top bar"
msgid "System"
msgstr "System"
#: js/ui/panel.js:826
#: js/ui/panel.js:829
msgid "Top Bar"
msgstr "Oberes Panel"
@ -1743,11 +1606,11 @@ msgstr "GNOME muss den Bildschirm sperren"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: js/ui/screenShield.js:244 js/ui/screenShield.js:598
#: js/ui/screenShield.js:244 js/ui/screenShield.js:601
msgid "Unable to lock"
msgstr "Sperrung fehlgeschlagen"
#: js/ui/screenShield.js:245 js/ui/screenShield.js:599
#: js/ui/screenShield.js:245 js/ui/screenShield.js:602
msgid "Lock was blocked by an application"
msgstr "Sperrung wurde von einer Anwendung blockiert"
@ -1830,13 +1693,13 @@ msgid "The PIM must be a number or empty."
msgstr "Die PIM muss eine Nummer oder leer sein."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:469
#: js/ui/shellMountOperation.js:465
#, javascript-format
msgid "Unable to start %s"
msgstr "%s konnte nicht gestartet werden"
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:471
#: js/ui/shellMountOperation.js:467
#, javascript-format
msgid "Couldnt find the %s application"
msgstr "Die Anwendung %s konnte nicht gefunden werden"
@ -2320,11 +2183,11 @@ msgstr "Thunderbolt-Legitimierungsfehler"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Das Thunderbolt-Gerät %s konnte nicht legitimiert werden"
#: js/ui/status/volume.js:150
#: js/ui/status/volume.js:151
msgid "Volume changed"
msgstr "Lautstärke geändert"
#: js/ui/status/volume.js:221
#: js/ui/status/volume.js:222
msgid "Volume"
msgstr "Lautstärke"
@ -2358,23 +2221,23 @@ msgstr "Nur eingebaut"
#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:370
#: js/ui/unlockDialog.js:371
msgid "%A %B %-d"
msgstr "%A, %d. %B"
#: js/ui/unlockDialog.js:376
#: js/ui/unlockDialog.js:377
msgid "Swipe up to unlock"
msgstr "Nach oben wischen zum Entsperren"
#: js/ui/unlockDialog.js:377
#: js/ui/unlockDialog.js:378
msgid "Click or press a key to unlock"
msgstr "Durch Mausklick oder Tastendruck entsperren"
#: js/ui/unlockDialog.js:549
#: js/ui/unlockDialog.js:550
msgid "Unlock Window"
msgstr "Fenster entsperren"
#: js/ui/unlockDialog.js:558
#: js/ui/unlockDialog.js:559
msgid "Log in as another user"
msgstr "Als anderer Benutzer anmelden"
@ -2407,7 +2270,7 @@ msgstr "Zurücksetzen"
msgid "Keep Changes"
msgstr "Beibehalten"
#: js/ui/windowManager.js:85
#: js/ui/windowManager.js:86
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"
@ -2417,7 +2280,7 @@ msgstr[1] ""
#. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height.
#: js/ui/windowManager.js:544
#: js/ui/windowManager.js:546
#, javascript-format
msgid "%d × %d"
msgstr "%d × %d"
@ -2512,12 +2375,12 @@ msgstr ""
msgid "List possible modes"
msgstr "Die möglichen Modi auflisten"
#: src/shell-app.c:279
#: src/shell-app.c:286
msgctxt "program"
msgid "Unknown"
msgstr "Unbekannt"
#: src/shell-app.c:530
#: src/shell-app.c:537
#, c-format
msgid "Failed to launch “%s”"
msgstr "»%s« konnte nicht gestartet werden"
@ -2534,6 +2397,143 @@ msgstr "Es muss ein Passwort angegeben werden"
msgid "Authentication dialog was dismissed by the user"
msgstr "Der Dialog zur Anmeldung wurde vom Benutzer geschlossen"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
#: subprojects/extensions-app/js/main.js:182
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Erweiterungen"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: subprojects/extensions-app/js/main.js:183
msgid "Manage your GNOME Extensions"
msgstr "Ihre GNOME-Erweiterungen verwalten"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"GNOME-Erweiterungen dient der Aktualisierung von Erweiterungen, dem "
"Konfigurieren der Voreinstellungen von Erweiterungen und dem Entfernen oder "
"Deaktivieren nicht gewünschter Erweiterungen."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "GNOME-Shell-Erweiterungen einrichten"
#: subprojects/extensions-app/js/main.js:144
#, javascript-format
msgid "Remove “%s”?"
msgstr "»%s« entfernen?"
#: subprojects/extensions-app/js/main.js:145
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Wenn Sie die Erweiterung entfernen, müssen Sie sie erneut herunterladen, um "
"sie wieder zu aktivieren"
#: subprojects/extensions-app/js/main.js:149
msgid "Remove"
msgstr "Entfernen"
#: subprojects/extensions-app/js/main.js:181
msgid "translator-credits"
msgstr ""
"Tim Sabsch <tim@sabsch.com>\n"
"Christian Kirbach <christian.kirbach@gmail.com>, 2020"
#: subprojects/extensions-app/js/main.js:316
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d Erweiterung wird bei der nächsten Anmeldung aktualisiert."
msgstr[1] "%d Erweiterungen werden bei der nächsten Anmeldung aktualisiert."
#: subprojects/extensions-app/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Beschreibung"
#: subprojects/extensions-app/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Version"
#: subprojects/extensions-app/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Autor"
#: subprojects/extensions-app/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Webseite"
#: subprojects/extensions-app/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Entfernen …"
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Hilfe"
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Info zu Erweiterungen"
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Besuchen Sie <a href=\"https://extensions.gnome.org\">extensions.gnome.org</"
"a>, um Erweiterungen zu finden und hinzuzufügen."
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Warnung"
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Erweiterungen können Probleme am System verursachen, darunter auch "
"Leistungsprobleme. Sollten Sie auf Probleme mit Ihrem System stoßen, wird "
"die Deaktivierung aller Erweiterungen empfohlen."
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
msgid "Manually Installed"
msgstr "Manuell installiert"
#: subprojects/extensions-app/data/ui/extensions-window.ui:159
msgid "Built-In"
msgstr "Mitgeliefert"
#: subprojects/extensions-app/data/ui/extensions-window.ui:200
msgid "No Installed Extensions"
msgstr "Keine installierten Erweiterungen"
#: subprojects/extensions-app/data/ui/extensions-window.ui:236
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Tut uns sehr leid, wir konnten keine Liste der installierten Erweiterungen "
"aufstellen. Stellen Sie sicher, dass Sie in GNOME angemeldet sind und "
"versuchen Sie es dann erneut."
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
msgid "Extension Updates Ready"
msgstr "Aktualisierungen für Erweiterungen stehen bereit"
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
msgid "Log Out…"
msgstr "Abmelden …"
#. Translators: a file path to an extension directory
#: subprojects/extensions-tool/src/command-create.c:125
#, c-format
@ -2872,6 +2872,9 @@ msgstr[1] "%u Eingänge"
msgid "System Sounds"
msgstr "Systemklänge"
#~ msgid "Copy Error"
#~ msgstr "Kopierfehler"
#~ msgid "Username…"
#~ msgstr "Benutzername …"

View File

@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-02-21 09:52+0000\n"
"PO-Revision-Date: 2020-02-23 12:49+0000\n"
"POT-Creation-Date: 2020-03-31 07:15+0000\n"
"PO-Revision-Date: 2020-05-06 19:54+0100\n"
"Last-Translator: Bruce Cowan <bruce@bcowan.me.uk>\n"
"Language-Team: English - United Kingdom <en@li.org>\n"
"Language: en_GB\n"
@ -19,7 +19,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: Gtranslator 3.34.0\n"
"X-Generator: Gtranslator 3.36.0\n"
"X-Project-Style: gnome\n"
#: data/50-gnome-shell-system.xml:6
@ -46,15 +46,6 @@ msgstr "Show all applications"
msgid "Open the application menu"
msgstr "Open the application menu"
#: data/org.gnome.Extensions.desktop.in.in:4 js/extensionPrefs/main.js:218
#: js/extensionPrefs/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensions"
#: data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configure GNOME Shell Extensions"
#: data/org.gnome.Shell.desktop.in.in:4
msgid "GNOME Shell"
msgstr "GNOME Shell"
@ -395,49 +386,12 @@ msgstr "Delay focus changes in mouse mode until the pointer stops moving"
msgid "Network Login"
msgstr "Network Login"
#: js/extensionPrefs/main.js:140
#, javascript-format
msgid "Remove “%s”?"
msgstr "Remove “%s”?"
#: js/extensionPrefs/main.js:141
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
#: js/extensionPrefs/main.js:144 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:107 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:165
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913
msgid "Cancel"
msgstr "Cancel"
#: js/extensionPrefs/main.js:145
msgid "Remove"
msgstr "Remove"
#: js/extensionPrefs/main.js:217
msgid "translator-credits"
msgstr ""
"Philip Withnall <philip@tecnocode.co.uk>\n"
"Bruce Cowan <bruce@bcowan.me.uk>\n"
"Chris Leonard <cjl@laptop.org>\n"
"David King <amigadave@amigadave.com>\n"
"Zander Brown <zbrown@gnome.org>"
#: js/extensionPrefs/main.js:219
msgid "Manage your GNOME Extensions"
msgstr "Manage your GNOME Extensions"
#: js/extensionPrefs/main.js:261 js/extensionPrefs/ui/extensions-window.ui:222
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
#: subprojects/extensions-app/data/ui/extensions-window.ui:223
msgid "Somethings gone wrong"
msgstr "Somethings gone wrong"
#: js/extensionPrefs/main.js:268
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
msgid ""
"Were very sorry, but theres been a problem: the settings for this "
"extension cant be displayed. We recommend that you report the issue to the "
@ -447,113 +401,32 @@ msgstr ""
"extension cant be displayed. We recommend that you report the issue to the "
"extension authors."
#: js/extensionPrefs/main.js:275
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
msgid "Technical Details"
msgstr "Technical Details"
#: js/extensionPrefs/main.js:310
msgid "Copy Error"
msgstr "Copy Error"
#: js/extensionPrefs/main.js:337
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
msgid "Homepage"
msgstr "Homepage"
#: js/extensionPrefs/main.js:338
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
msgid "Visit extension homepage"
msgstr "Visit extension homepage"
#: js/extensionPrefs/main.js:449
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extension will be updated on next login."
msgstr[1] "%d extensions will be updated on next login."
#: js/extensionPrefs/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Description"
#: js/extensionPrefs/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Version"
#: js/extensionPrefs/ui/extension-row.ui:151
msgid "Author"
msgstr "Author"
#: js/extensionPrefs/ui/extension-row.ui:175
msgid "Website"
msgstr "Website"
#: js/extensionPrefs/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Remove…"
#: js/extensionPrefs/ui/extensions-window.ui:8
msgid "Help"
msgstr "Help"
#: js/extensionPrefs/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "About Extensions"
#: js/extensionPrefs/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
#: js/extensionPrefs/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Warning"
#: js/extensionPrefs/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
#: js/extensionPrefs/ui/extensions-window.ui:133
msgid "Manually Installed"
msgstr "Manually Installed"
#: js/extensionPrefs/ui/extensions-window.ui:157
msgid "Built-In"
msgstr "Built-In"
#: js/extensionPrefs/ui/extensions-window.ui:198
msgid "No Installed Extensions"
msgstr "No Installed Extensions"
#: js/extensionPrefs/ui/extensions-window.ui:234
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
#: js/extensionPrefs/ui/extensions-window.ui:287
msgid "Log Out…"
msgstr "Log Out…"
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:181
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
msgid "Cancel"
msgstr "Cancel"
#. Cisco LEAP
#: js/gdm/authPrompt.js:236 js/ui/components/networkAgent.js:202
#: js/ui/components/networkAgent.js:218 js/ui/components/networkAgent.js:242
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:283
#: js/ui/components/networkAgent.js:293 js/ui/components/polkitAgent.js:277
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
#: js/ui/components/networkAgent.js:220 js/ui/components/networkAgent.js:244
#: js/ui/components/networkAgent.js:265 js/ui/components/networkAgent.js:285
#: js/ui/components/networkAgent.js:295 js/ui/components/polkitAgent.js:277
#: js/ui/shellMountOperation.js:326
#| msgid "Password:"
msgid "Password"
msgstr "Password"
@ -575,9 +448,8 @@ msgstr "(e.g., user or %s)"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:238
#: js/ui/components/networkAgent.js:261 js/ui/components/networkAgent.js:279
#| msgid "Username: "
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:240
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:281
msgid "Username"
msgstr "Username"
@ -758,7 +630,7 @@ msgstr "%A, %H%M"
#: js/misc/util.js:255
#, no-c-format
msgid "%B %-d, %H%M"
msgstr "%d %B, %H%M"
msgstr "%-d %B, %H%M"
#. Translators: this is the month name, day number, year
#. number followed by a time string in 24h format.
@ -766,7 +638,7 @@ msgstr "%d %B, %H%M"
#: js/misc/util.js:261
#, no-c-format
msgid "%B %-d %Y, %H%M"
msgstr "%d %B %Y, %H%M"
msgstr "%-d %B %Y, %H%M"
#. Show only the time if date is on today
#. eslint-disable-line no-lonely-if
@ -795,7 +667,7 @@ msgstr "%A, %l:%M %p"
#: js/misc/util.js:284
#, no-c-format
msgid "%B %-d, %l%M %p"
msgstr "%d %B, %l%M %p"
msgstr "%-d %B, %l%M %p"
#. Translators: this is the month name, day number, year
#. number followed by a time string in 12h format.
@ -803,7 +675,7 @@ msgstr "%d %B, %l%M %p"
#: js/misc/util.js:290
#, no-c-format
msgid "%B %-d %Y, %l%M %p"
msgstr "%d %B %Y, %l%M %p"
msgstr "%-d %B %Y, %l%M %p"
#. TRANSLATORS: this is the title of the wifi captive portal login window
#: js/portalHelper/main.js:41
@ -828,44 +700,44 @@ msgstr "Deny Access"
msgid "Grant Access"
msgstr "Grant Access"
#: js/ui/appDisplay.js:906
#: js/ui/appDisplay.js:932
msgid "Unnamed Folder"
msgstr "Unnamed Folder"
#: js/ui/appDisplay.js:929
#: js/ui/appDisplay.js:955
msgid "Frequently used applications will appear here"
msgstr "Frequently used applications will appear here"
#: js/ui/appDisplay.js:1064
#: js/ui/appDisplay.js:1090
msgid "Frequent"
msgstr "Frequent"
#: js/ui/appDisplay.js:1071
#: js/ui/appDisplay.js:1097
msgid "All"
msgstr "All"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2450 js/ui/panel.js:75
#: js/ui/appDisplay.js:2473 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Open Windows"
#: js/ui/appDisplay.js:2470 js/ui/panel.js:82
#: js/ui/appDisplay.js:2493 js/ui/panel.js:82
msgid "New Window"
msgstr "New Window"
#: js/ui/appDisplay.js:2481
#: js/ui/appDisplay.js:2504
msgid "Launch using Dedicated Graphics Card"
msgstr "Launch using Dedicated Graphics Card"
#: js/ui/appDisplay.js:2509 js/ui/dash.js:239
#: js/ui/appDisplay.js:2532 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Remove from Favourites"
#: js/ui/appDisplay.js:2515
#: js/ui/appDisplay.js:2538
msgid "Add to Favorites"
msgstr "Add to Favourites"
#: js/ui/appDisplay.js:2525 js/ui/panel.js:93
#: js/ui/appDisplay.js:2548 js/ui/panel.js:93
msgid "Show Details"
msgstr "Show Details"
@ -895,7 +767,7 @@ msgstr "Headphones"
msgid "Headset"
msgstr "Headset"
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
msgid "Microphone"
msgstr "Microphone"
@ -1013,30 +885,30 @@ msgid "All Day"
msgstr "All Day"
#. Translators: Shown on calendar heading when selected day occurs on current year
#: js/ui/calendar.js:867
#: js/ui/calendar.js:868
msgctxt "calendar heading"
msgid "%A, %B %-d"
msgstr "%A, %d %B"
msgstr "%A, %-d %B"
#. Translators: Shown on calendar heading when selected day occurs on different year
#: js/ui/calendar.js:870
#: js/ui/calendar.js:871
msgctxt "calendar heading"
msgid "%A, %B %-d, %Y"
msgstr "%A, %d %B, %Y"
msgstr "%A, %-d %B, %Y"
#: js/ui/calendar.js:1096
#: js/ui/calendar.js:1100
msgid "No Notifications"
msgstr "No Notifications"
#: js/ui/calendar.js:1099
#: js/ui/calendar.js:1103
msgid "No Events"
msgstr "No Events"
#: js/ui/calendar.js:1153
#: js/ui/calendar.js:1157
msgid "Do Not Disturb"
msgstr "Do Not Disturb"
#: js/ui/calendar.js:1167
#: js/ui/calendar.js:1176
msgid "Clear"
msgstr "Clear"
@ -1083,43 +955,39 @@ msgstr "The installed udisks version does not support the PIM setting"
msgid "Open with %s"
msgstr "Open with %s"
#: js/ui/components/networkAgent.js:89
#: js/ui/components/networkAgent.js:91
msgid ""
"Alternatively you can connect by pushing the “WPS” button on your router."
msgstr ""
"Alternatively you can connect by pushing the “WPS” button on your router."
#: js/ui/components/networkAgent.js:101 js/ui/status/network.js:223
#: js/ui/components/networkAgent.js:103 js/ui/status/network.js:223
#: js/ui/status/network.js:314 js/ui/status/network.js:916
msgid "Connect"
msgstr "Connect"
#: js/ui/components/networkAgent.js:208
#| msgid "Key: "
#: js/ui/components/networkAgent.js:210
msgid "Key"
msgstr "Key"
#: js/ui/components/networkAgent.js:246 js/ui/components/networkAgent.js:269
#| msgid "Private key password: "
#: js/ui/components/networkAgent.js:248 js/ui/components/networkAgent.js:271
msgid "Private key password"
msgstr "Private key password"
#: js/ui/components/networkAgent.js:267
#| msgid "Identity: "
#: js/ui/components/networkAgent.js:269
msgid "Identity"
msgstr "Identity"
#: js/ui/components/networkAgent.js:281
#| msgid "Service: "
#: js/ui/components/networkAgent.js:283
msgid "Service"
msgstr "Service"
#: js/ui/components/networkAgent.js:310 js/ui/components/networkAgent.js:338
#: js/ui/components/networkAgent.js:685 js/ui/components/networkAgent.js:706
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:340
#: js/ui/components/networkAgent.js:679 js/ui/components/networkAgent.js:700
msgid "Authentication required"
msgstr "Authentication required"
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:686
#: js/ui/components/networkAgent.js:313 js/ui/components/networkAgent.js:680
#, javascript-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -1128,44 +996,42 @@ msgstr ""
"Passwords or encryption keys are required to access the wireless network "
"“%s”."
#: js/ui/components/networkAgent.js:315 js/ui/components/networkAgent.js:690
#: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:684
msgid "Wired 802.1X authentication"
msgstr "Wired 802.1X authentication"
#: js/ui/components/networkAgent.js:317
#| msgid "Network name: "
#: js/ui/components/networkAgent.js:319
msgid "Network name"
msgstr "Network name"
#: js/ui/components/networkAgent.js:322 js/ui/components/networkAgent.js:694
#: js/ui/components/networkAgent.js:324 js/ui/components/networkAgent.js:688
msgid "DSL authentication"
msgstr "DSL authentication"
#: js/ui/components/networkAgent.js:329 js/ui/components/networkAgent.js:699
#: js/ui/components/networkAgent.js:331 js/ui/components/networkAgent.js:693
msgid "PIN code required"
msgstr "PIN code required"
#: js/ui/components/networkAgent.js:330 js/ui/components/networkAgent.js:700
#: js/ui/components/networkAgent.js:332 js/ui/components/networkAgent.js:694
msgid "PIN code is needed for the mobile broadband device"
msgstr "PIN code is needed for the mobile broadband device"
#: js/ui/components/networkAgent.js:331
#| msgid "PIN: "
#: js/ui/components/networkAgent.js:333
msgid "PIN"
msgstr "PIN"
#: js/ui/components/networkAgent.js:339 js/ui/components/networkAgent.js:691
#: js/ui/components/networkAgent.js:695 js/ui/components/networkAgent.js:707
#: js/ui/components/networkAgent.js:711
#: js/ui/components/networkAgent.js:341 js/ui/components/networkAgent.js:685
#: js/ui/components/networkAgent.js:689 js/ui/components/networkAgent.js:701
#: js/ui/components/networkAgent.js:705
#, javascript-format
msgid "A password is required to connect to “%s”."
msgstr "A password is required to connect to “%s”."
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1691
#: js/ui/components/networkAgent.js:668 js/ui/status/network.js:1691
msgid "Network Manager"
msgstr "Network Manager"
#: js/ui/components/networkAgent.js:710
#: js/ui/components/networkAgent.js:704
msgid "VPN password"
msgstr "VPN password"
@ -1191,7 +1057,7 @@ msgstr "Sorry, that didnt work. Please try again."
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: js/ui/components/telepathyClient.js:787
#: js/ui/components/telepathyClient.js:823
#, javascript-format
msgid "%s is now known as %s"
msgstr "%s is now known as %s"
@ -1217,7 +1083,7 @@ msgstr "Dash"
#.
#: js/ui/dateMenu.js:75
msgid "%B %-d %Y"
msgstr "%e %B %Y"
msgstr "%-d %B %Y"
#. Translators: This is the accessible name of the date button shown
#. * below the time in the shell; it should combine the weekday and the
@ -1235,106 +1101,106 @@ msgstr "Add world clocks…"
msgid "World Clocks"
msgstr "World Clocks"
#: js/ui/dateMenu.js:276
#: js/ui/dateMenu.js:289
msgid "Weather"
msgstr "Weather"
#: js/ui/dateMenu.js:391
#: js/ui/dateMenu.js:418
msgid "Select a location…"
msgstr "Select a location…"
#: js/ui/dateMenu.js:404
#: js/ui/dateMenu.js:426
msgid "Loading…"
msgstr "Loading…"
#: js/ui/dateMenu.js:414
#: js/ui/dateMenu.js:436
msgid "Go online for weather information"
msgstr "Go online for weather information"
#: js/ui/dateMenu.js:416
#: js/ui/dateMenu.js:438
msgid "Weather information is currently unavailable"
msgstr "Weather information is currently unavailable"
#: js/ui/endSessionDialog.js:37
#: js/ui/endSessionDialog.js:39
#, javascript-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Log Out %s"
#: js/ui/endSessionDialog.js:38
#: js/ui/endSessionDialog.js:40
msgctxt "title"
msgid "Log Out"
msgstr "Log Out"
#: js/ui/endSessionDialog.js:40
#: js/ui/endSessionDialog.js:42
#, javascript-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 will be logged out automatically in %d second."
msgstr[1] "%s will be logged out automatically in %d seconds."
#: js/ui/endSessionDialog.js:45
#: js/ui/endSessionDialog.js:47
#, javascript-format
msgid "You will be logged out automatically in %d second."
msgid_plural "You will be logged out automatically in %d seconds."
msgstr[0] "You will be logged out automatically in %d second."
msgstr[1] "You will be logged out automatically in %d seconds."
#: js/ui/endSessionDialog.js:51
#: js/ui/endSessionDialog.js:53
msgctxt "button"
msgid "Log Out"
msgstr "Log Out"
#: js/ui/endSessionDialog.js:56
#: js/ui/endSessionDialog.js:58
msgctxt "title"
msgid "Power Off"
msgstr "Power Off"
#: js/ui/endSessionDialog.js:57
#: js/ui/endSessionDialog.js:59
msgctxt "title"
msgid "Install Updates & Power Off"
msgstr "Install Updates & Power Off"
#: js/ui/endSessionDialog.js:59
#: js/ui/endSessionDialog.js:61
#, javascript-format
msgid "The system will power off automatically in %d second."
msgid_plural "The system will power off automatically in %d seconds."
msgstr[0] "The system will power off automatically in %d second."
msgstr[1] "The system will power off automatically in %d seconds."
#: js/ui/endSessionDialog.js:63
#: js/ui/endSessionDialog.js:65
msgctxt "checkbox"
msgid "Install pending software updates"
msgstr "Install pending software updates"
#: js/ui/endSessionDialog.js:66 js/ui/endSessionDialog.js:82
#: js/ui/endSessionDialog.js:68 js/ui/endSessionDialog.js:84
msgctxt "button"
msgid "Restart"
msgstr "Restart"
#: js/ui/endSessionDialog.js:68
#: js/ui/endSessionDialog.js:70
msgctxt "button"
msgid "Power Off"
msgstr "Power Off"
#: js/ui/endSessionDialog.js:74
#: js/ui/endSessionDialog.js:76
msgctxt "title"
msgid "Restart"
msgstr "Restart"
#: js/ui/endSessionDialog.js:76
#: js/ui/endSessionDialog.js:78
#, javascript-format
msgid "The system will restart automatically in %d second."
msgid_plural "The system will restart automatically in %d seconds."
msgstr[0] "The system will restart automatically in %d second."
msgstr[1] "The system will restart automatically in %d seconds."
#: js/ui/endSessionDialog.js:89
#: js/ui/endSessionDialog.js:91
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Restart & Install Updates"
#: js/ui/endSessionDialog.js:91
#: js/ui/endSessionDialog.js:93
#, javascript-format
msgid "The system will automatically restart and install updates in %d second."
msgid_plural ""
@ -1344,22 +1210,22 @@ msgstr[0] ""
msgstr[1] ""
"The system will automatically restart and install updates in %d seconds."
#: js/ui/endSessionDialog.js:97 js/ui/endSessionDialog.js:116
#: js/ui/endSessionDialog.js:99 js/ui/endSessionDialog.js:118
msgctxt "button"
msgid "Restart &amp; Install"
msgstr "Restart &amp; Install"
#: js/ui/endSessionDialog.js:98
#: js/ui/endSessionDialog.js:100
msgctxt "button"
msgid "Install &amp; Power Off"
msgstr "Install &amp; Power Off"
#: js/ui/endSessionDialog.js:99
#: js/ui/endSessionDialog.js:101
msgctxt "checkbox"
msgid "Power off after updates are installed"
msgstr "Power off after updates are installed"
#: js/ui/endSessionDialog.js:106
#: js/ui/endSessionDialog.js:108
msgctxt "title"
msgid "Restart & Install Upgrade"
msgstr "Restart & Install Upgrade"
@ -1367,7 +1233,7 @@ msgstr "Restart & Install Upgrade"
#. Translators: This is the text displayed for system upgrades in the
#. shut down dialog. First %s gets replaced with the distro name and
#. second %s with the distro version to upgrade to
#: js/ui/endSessionDialog.js:111
#: js/ui/endSessionDialog.js:113
#, javascript-format
msgid ""
"%s %s will be installed after restart. Upgrade installation can take a long "
@ -1376,15 +1242,15 @@ msgstr ""
"%s %s will be installed after restart. Upgrade installation can take a long "
"time: ensure that you have backed up and that the computer is plugged in."
#: js/ui/endSessionDialog.js:259
#: js/ui/endSessionDialog.js:261
msgid "Running on battery power: Please plug in before installing updates."
msgstr "Running on battery power: Please plug in before installing updates."
#: js/ui/endSessionDialog.js:268
#: js/ui/endSessionDialog.js:270
msgid "Some applications are busy or have unsaved work"
msgstr "Some applications are busy or have unsaved work"
#: js/ui/endSessionDialog.js:273
#: js/ui/endSessionDialog.js:275
msgid "Other users are logged in"
msgstr "Other users are logged in"
@ -1400,24 +1266,24 @@ msgstr "%s (remote)"
msgid "%s (console)"
msgstr "%s (console)"
#: js/ui/extensionDownloader.js:169
#: js/ui/extensionDownloader.js:185
msgid "Install"
msgstr "Install"
#: js/ui/extensionDownloader.js:175
#: js/ui/extensionDownloader.js:191
msgid "Install Extension"
msgstr "Install Extension"
#: js/ui/extensionDownloader.js:176
#: js/ui/extensionDownloader.js:192
#, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Download and install “%s” from extensions.gnome.org?"
#: js/ui/extensionSystem.js:228
#: js/ui/extensionSystem.js:233
msgid "Extension Updates Available"
msgstr "Extension Updates Available"
#: js/ui/extensionSystem.js:229
#: js/ui/extensionSystem.js:234
msgid "Extension updates are ready to be installed."
msgstr "Extension updates are ready to be installed."
@ -1564,11 +1430,11 @@ msgstr "View Source"
msgid "Web Page"
msgstr "Web Page"
#: js/ui/main.js:269
#: js/ui/main.js:277
msgid "Logged in as a privileged user"
msgstr "Logged in as a privileged user"
#: js/ui/main.js:270
#: js/ui/main.js:278
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@ -1576,15 +1442,15 @@ msgstr ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
#: js/ui/main.js:276
#: js/ui/main.js:317
msgid "Screen Lock disabled"
msgstr "Screen Lock disabled"
#: js/ui/main.js:277
#: js/ui/main.js:318
msgid "Screen Locking requires the GNOME display manager."
msgstr "Screen Locking requires the GNOME display manager."
#: js/ui/messageTray.js:1554
#: js/ui/messageTray.js:1551
msgid "System Information"
msgstr "System Information"
@ -1611,7 +1477,6 @@ msgstr "Overview"
#. active; it should not exceed ~30
#. characters.
#: js/ui/overview.js:107
#| msgid "Type to search…"
msgid "Type to search"
msgstr "Type to search"
@ -1669,12 +1534,12 @@ msgstr "Quit"
msgid "Activities"
msgstr "Activities"
#: js/ui/panel.js:707
#: js/ui/panel.js:713
msgctxt "System menu in the top bar"
msgid "System"
msgstr "System"
#: js/ui/panel.js:820
#: js/ui/panel.js:826
msgid "Top Bar"
msgstr "Top Bar"
@ -1769,7 +1634,6 @@ msgstr ""
"To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead."
#: js/ui/shellMountOperation.js:306
#| msgid "Enter PIM Number…"
msgid "PIM Number"
msgstr "PIM Number"
@ -1792,13 +1656,13 @@ msgid "The PIM must be a number or empty."
msgstr "The PIM must be a number or empty."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:469
#: js/ui/shellMountOperation.js:465
#, javascript-format
msgid "Unable to start %s"
msgstr "Unable to start %s"
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:471
#: js/ui/shellMountOperation.js:467
#, javascript-format
msgid "Couldnt find the %s application"
msgstr "Couldnt find the %s application"
@ -2271,11 +2135,11 @@ msgstr "Thunderbolt authorisation error"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Could not authorise the Thunderbolt device: %s"
#: js/ui/status/volume.js:150
#: js/ui/status/volume.js:151
msgid "Volume changed"
msgstr "Volume changed"
#: js/ui/status/volume.js:221
#: js/ui/status/volume.js:222
msgid "Volume"
msgstr "Volume"
@ -2309,24 +2173,26 @@ msgstr "Built-in Only"
#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:372
#| msgctxt "calendar heading"
#| msgid "%A, %B %-d"
#: js/ui/unlockDialog.js:371
msgid "%A %B %-d"
msgstr "%A %-d %B"
#: js/ui/unlockDialog.js:378
#: js/ui/unlockDialog.js:377
msgid "Swipe up to unlock"
msgstr "Swipe up to unlock"
#: js/ui/unlockDialog.js:379
#: js/ui/unlockDialog.js:378
msgid "Click or press a key to unlock"
msgstr "Click or press a key to unlock"
#: js/ui/unlockDialog.js:552
#: js/ui/unlockDialog.js:550
msgid "Unlock Window"
msgstr "Unlock Window"
#: js/ui/unlockDialog.js:559
msgid "Log in as another user"
msgstr "Log in as another user"
#: js/ui/viewSelector.js:181
msgid "Applications"
msgstr "Applications"
@ -2442,19 +2308,19 @@ msgstr "Close"
msgid "Evolution Calendar"
msgstr "Evolution Calendar"
#: src/main.c:460 subprojects/extensions-tool/src/main.c:249
#: src/main.c:458 subprojects/extensions-tool/src/main.c:249
msgid "Print version"
msgstr "Print version"
#: src/main.c:466
#: src/main.c:464
msgid "Mode used by GDM for login screen"
msgstr "Mode used by GDM for login screen"
#: src/main.c:472
#: src/main.c:470
msgid "Use a specific mode, e.g. “gdm” for login screen"
msgstr "Use a specific mode, e.g. “gdm” for login screen"
#: src/main.c:478
#: src/main.c:476
msgid "List possible modes"
msgstr "List possible modes"
@ -2480,6 +2346,140 @@ msgstr "Password cannot be blank"
msgid "Authentication dialog was dismissed by the user"
msgstr "Authentication dialogue was dismissed by the user"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
#: subprojects/extensions-app/js/main.js:182
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensions"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: subprojects/extensions-app/js/main.js:183
msgid "Manage your GNOME Extensions"
msgstr "Manage your GNOME Extensions"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configure GNOME Shell Extensions"
#: subprojects/extensions-app/js/main.js:144
#, javascript-format
msgid "Remove “%s”?"
msgstr "Remove “%s”?"
#: subprojects/extensions-app/js/main.js:145
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
#: subprojects/extensions-app/js/main.js:149
msgid "Remove"
msgstr "Remove"
#: subprojects/extensions-app/js/main.js:181
msgid "translator-credits"
msgstr ""
"Philip Withnall <philip@tecnocode.co.uk>\n"
"Bruce Cowan <bruce@bcowan.me.uk>\n"
"Chris Leonard <cjl@laptop.org>\n"
"David King <amigadave@amigadave.com>\n"
"Zander Brown <zbrown@gnome.org>"
#: subprojects/extensions-app/js/main.js:316
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extension will be updated on next login."
msgstr[1] "%d extensions will be updated on next login."
#: subprojects/extensions-app/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Description"
#: subprojects/extensions-app/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Version"
#: subprojects/extensions-app/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Author"
#: subprojects/extensions-app/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Website"
#: subprojects/extensions-app/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Remove…"
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Help"
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "About Extensions"
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Warning"
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
#: subprojects/extensions-app/data/ui/extensions-window.ui:134
msgid "Manually Installed"
msgstr "Manually Installed"
#: subprojects/extensions-app/data/ui/extensions-window.ui:158
msgid "Built-In"
msgstr "Built-In"
#: subprojects/extensions-app/data/ui/extensions-window.ui:199
msgid "No Installed Extensions"
msgstr "No Installed Extensions"
#: subprojects/extensions-app/data/ui/extensions-window.ui:235
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
#: subprojects/extensions-app/data/ui/extensions-window.ui:288
msgid "Log Out…"
msgstr "Log Out…"
#. Translators: a file path to an extension directory
#: subprojects/extensions-tool/src/command-create.c:125
#, c-format
@ -2627,7 +2627,6 @@ msgid "Show extensions with preferences"
msgstr "Show extensions with preferences"
#: subprojects/extensions-tool/src/command-list.c:140
#| msgid "Show extensions with preferences"
msgid "Show extensions with updates"
msgstr "Show extensions with updates"
@ -2818,6 +2817,9 @@ msgstr[1] "%u Inputs"
msgid "System Sounds"
msgstr "System Sounds"
#~ msgid "Copy Error"
#~ msgstr "Copy Error"
#~ msgid "Next"
#~ msgstr "Next"
@ -2844,9 +2846,6 @@ msgstr "System Sounds"
#~ msgstr[0] "%d new notification"
#~ msgstr[1] "%d new notifications"
#~ msgid "Log in as another user"
#~ msgstr "Log in as another user"
#~| msgid "Shell Extensions"
#~ msgid "org.gnome.Extensions"
#~ msgstr "org.gnome.Extensions"

1252
po/eo.po

File diff suppressed because it is too large Load Diff

933
po/es.po

File diff suppressed because it is too large Load Diff

780
po/eu.po

File diff suppressed because it is too large Load Diff

698
po/fa.po

File diff suppressed because it is too large Load Diff

161
po/fi.po
View File

@ -25,8 +25,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-03-31 07:15+0000\n"
"PO-Revision-Date: 2020-04-02 12:43+0300\n"
"POT-Creation-Date: 2020-05-15 03:04+0000\n"
"PO-Revision-Date: 2020-05-16 14:02+0300\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos+l10n@iki.fi>\n"
"Language-Team: suomi <lokalisointi-lista@googlegroups.com>\n"
"Language: fi\n"
@ -421,7 +421,7 @@ msgid "Network Login"
msgstr "Verkkokirjautuminen"
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
#: subprojects/extensions-app/data/ui/extensions-window.ui:223
#: subprojects/extensions-app/data/ui/extensions-window.ui:224
msgid "Somethings gone wrong"
msgstr "Jokin meni pieleen"
@ -448,7 +448,7 @@ msgstr "Käy laajennuksen verkkosivulla"
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:181
#: js/ui/endSessionDialog.js:372 js/ui/extensionDownloader.js:181
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
msgid "Cancel"
@ -504,74 +504,74 @@ msgid "(or swipe finger)"
msgstr "(tai pyyhkäise sormella)"
#. Translators: The name of the power-off action in search
#: js/misc/systemActions.js:89
#: js/misc/systemActions.js:93
msgctxt "search-result"
msgid "Power Off"
msgstr "Sammuta"
#. Translators: A list of keywords that match the power-off action, separated by semicolons
#: js/misc/systemActions.js:92
#: js/misc/systemActions.js:96
msgid "power off;shutdown;reboot;restart;halt;stop"
msgstr ""
"power off;shutdown;reboot;restart;halt;stop;sammuta;käynnistä uudelleen"
#. Translators: The name of the lock screen action in search
#: js/misc/systemActions.js:97
#: js/misc/systemActions.js:101
msgctxt "search-result"
msgid "Lock Screen"
msgstr "Lukitse näyttö"
#. Translators: A list of keywords that match the lock screen action, separated by semicolons
#: js/misc/systemActions.js:100
#: js/misc/systemActions.js:104
msgid "lock screen"
msgstr "lock screen"
#. Translators: The name of the logout action in search
#: js/misc/systemActions.js:105
#: js/misc/systemActions.js:109
msgctxt "search-result"
msgid "Log Out"
msgstr "Kirjaudu ulos"
#. Translators: A list of keywords that match the logout action, separated by semicolons
#: js/misc/systemActions.js:108
#: js/misc/systemActions.js:112
msgid "logout;log out;sign off"
msgstr "logout;log out;sign off;kirjaudu ulos;uloskirjautuminen;poistu"
#. Translators: The name of the suspend action in search
#: js/misc/systemActions.js:113
#: js/misc/systemActions.js:117
msgctxt "search-result"
msgid "Suspend"
msgstr "Valmiustila"
#. Translators: A list of keywords that match the suspend action, separated by semicolons
#: js/misc/systemActions.js:116
#: js/misc/systemActions.js:120
msgid "suspend;sleep"
msgstr "suspend;sleep"
#. Translators: The name of the switch user action in search
#: js/misc/systemActions.js:121
#: js/misc/systemActions.js:125
msgctxt "search-result"
msgid "Switch User"
msgstr "Vaihda käyttäjää"
#. Translators: A list of keywords that match the switch user action, separated by semicolons
#: js/misc/systemActions.js:124
#: js/misc/systemActions.js:128
msgid "switch user"
msgstr "switch user"
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
#: js/misc/systemActions.js:131
#: js/misc/systemActions.js:135
msgid "lock orientation;unlock orientation;screen;rotation"
msgstr ""
"lock orientation;unlock orientation;screen;rotation;lukitse kierto;lukitse "
"suunta;suunta;kääntö"
#: js/misc/systemActions.js:251
#: js/misc/systemActions.js:255
msgctxt "search-result"
msgid "Unlock Screen Rotation"
msgstr "Vapauta näytön kierto"
#: js/misc/systemActions.js:252
#: js/misc/systemActions.js:256
msgctxt "search-result"
msgid "Lock Screen Rotation"
msgstr "Lukitse näytön kierto"
@ -736,53 +736,53 @@ msgstr "Estä pääsy"
msgid "Grant Access"
msgstr "Salli pääsy"
#: js/ui/appDisplay.js:932
#: js/ui/appDisplay.js:939
msgid "Unnamed Folder"
msgstr "Nimetön kansio"
#: js/ui/appDisplay.js:955
#: js/ui/appDisplay.js:962
msgid "Frequently used applications will appear here"
msgstr "Usein käytetyt sovellukset ilmestyvät tänne"
#: js/ui/appDisplay.js:1090
#: js/ui/appDisplay.js:1097
msgid "Frequent"
msgstr "Käytetyimmät"
#: js/ui/appDisplay.js:1097
#: js/ui/appDisplay.js:1104
msgid "All"
msgstr "Kaikki"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2473 js/ui/panel.js:75
#: js/ui/appDisplay.js:2480 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Avoimet ikkunat"
#: js/ui/appDisplay.js:2493 js/ui/panel.js:82
#: js/ui/appDisplay.js:2500 js/ui/panel.js:82
msgid "New Window"
msgstr "Uusi ikkuna"
#: js/ui/appDisplay.js:2504
#: js/ui/appDisplay.js:2511
msgid "Launch using Dedicated Graphics Card"
msgstr "Käynnistä erillisnäytönohjainta käyttäen"
#: js/ui/appDisplay.js:2532 js/ui/dash.js:239
#: js/ui/appDisplay.js:2539 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Poista suosikeista"
#: js/ui/appDisplay.js:2538
#: js/ui/appDisplay.js:2545
msgid "Add to Favorites"
msgstr "Lisää suosikkeihin"
#: js/ui/appDisplay.js:2548 js/ui/panel.js:93
#: js/ui/appDisplay.js:2555 js/ui/panel.js:93
msgid "Show Details"
msgstr "Näytä tiedot"
#: js/ui/appFavorites.js:152
#: js/ui/appFavorites.js:153
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s on lisätty suosikkeihin."
#: js/ui/appFavorites.js:185
#: js/ui/appFavorites.js:186
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s on poistettu suosikeista."
@ -1155,74 +1155,74 @@ msgstr "Yhdistä verkkoon saadaksesi säätietoja"
msgid "Weather information is currently unavailable"
msgstr "Säätiedot eivät ole juuri nyt saatavilla"
#: js/ui/endSessionDialog.js:39
#: js/ui/endSessionDialog.js:37
#, javascript-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Kirjaa %s ulos"
#: js/ui/endSessionDialog.js:40
#: js/ui/endSessionDialog.js:38
msgctxt "title"
msgid "Log Out"
msgstr "Kirjaudu ulos"
#: js/ui/endSessionDialog.js:42
#: js/ui/endSessionDialog.js:40
#, javascript-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 - kirjaudutaan ulos automaattisesti %d sekunnin kuluttua."
msgstr[1] "%s - kirjaudutaan ulos automaattisesti %d sekunnin kuluttua."
#: js/ui/endSessionDialog.js:47
#: js/ui/endSessionDialog.js:45
#, javascript-format
msgid "You will be logged out automatically in %d second."
msgid_plural "You will be logged out automatically in %d seconds."
msgstr[0] "Sinut kirjataan ulos automaattisesti %d sekunnin kuluttua."
msgstr[1] "Sinut kirjataan ulos automaattisesti %d sekunnin kuluttua."
#: js/ui/endSessionDialog.js:53
#: js/ui/endSessionDialog.js:51
msgctxt "button"
msgid "Log Out"
msgstr "Kirjaudu ulos"
#: js/ui/endSessionDialog.js:58
#: js/ui/endSessionDialog.js:56
msgctxt "title"
msgid "Power Off"
msgstr "Sammuta"
#: js/ui/endSessionDialog.js:59
#: js/ui/endSessionDialog.js:57
msgctxt "title"
msgid "Install Updates & Power Off"
msgstr "Asenna päivitykset ja sammuta"
#: js/ui/endSessionDialog.js:61
#: js/ui/endSessionDialog.js:59
#, javascript-format
msgid "The system will power off automatically in %d second."
msgid_plural "The system will power off automatically in %d seconds."
msgstr[0] "Järjestelmä sammuu automaattisesti %d sekunnin kuluttua."
msgstr[1] "Järjestelmä sammuu automaattisesti %d sekunnin kuluttua."
#: js/ui/endSessionDialog.js:65
#: js/ui/endSessionDialog.js:63
msgctxt "checkbox"
msgid "Install pending software updates"
msgstr "Asenna odottavat ohjelmistopäivitykset"
#: js/ui/endSessionDialog.js:68 js/ui/endSessionDialog.js:84
#: js/ui/endSessionDialog.js:66 js/ui/endSessionDialog.js:82
msgctxt "button"
msgid "Restart"
msgstr "Käynnistä uudelleen"
#: js/ui/endSessionDialog.js:70
#: js/ui/endSessionDialog.js:68
msgctxt "button"
msgid "Power Off"
msgstr "Sammuta"
#: js/ui/endSessionDialog.js:76
#: js/ui/endSessionDialog.js:74
msgctxt "title"
msgid "Restart"
msgstr "Käynnistä uudelleen"
#: js/ui/endSessionDialog.js:78
#: js/ui/endSessionDialog.js:76
#, javascript-format
msgid "The system will restart automatically in %d second."
msgid_plural "The system will restart automatically in %d seconds."
@ -1231,12 +1231,12 @@ msgstr[0] ""
msgstr[1] ""
"Järjestelmä käynnistyy automaattisesti uudelleen %d sekunnin kuluttua."
#: js/ui/endSessionDialog.js:91
#: js/ui/endSessionDialog.js:89
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Käynnistä uudelleen ja asenna päivitykset"
#: js/ui/endSessionDialog.js:93
#: js/ui/endSessionDialog.js:91
#, javascript-format
msgid "The system will automatically restart and install updates in %d second."
msgid_plural ""
@ -1248,22 +1248,22 @@ msgstr[1] ""
"Järjestelmä käynnistyy automaattisesti uudelleen ja asentaa päivitykset %d "
"sekunnin kuluttua."
#: js/ui/endSessionDialog.js:99 js/ui/endSessionDialog.js:118
#: js/ui/endSessionDialog.js:97 js/ui/endSessionDialog.js:116
msgctxt "button"
msgid "Restart &amp; Install"
msgstr "Käynnistä uudelleen ja asenna"
#: js/ui/endSessionDialog.js:100
#: js/ui/endSessionDialog.js:98
msgctxt "button"
msgid "Install &amp; Power Off"
msgstr "Asenna ja sammuta"
#: js/ui/endSessionDialog.js:101
#: js/ui/endSessionDialog.js:99
msgctxt "checkbox"
msgid "Power off after updates are installed"
msgstr "Sammuta päivitysten asennuksen jälkeen"
#: js/ui/endSessionDialog.js:108
#: js/ui/endSessionDialog.js:106
msgctxt "title"
msgid "Restart & Install Upgrade"
msgstr "Käynnistä uudelleen ja asenna päivitys"
@ -1271,7 +1271,7 @@ msgstr "Käynnistä uudelleen ja asenna päivitys"
#. Translators: This is the text displayed for system upgrades in the
#. shut down dialog. First %s gets replaced with the distro name and
#. second %s with the distro version to upgrade to
#: js/ui/endSessionDialog.js:113
#: js/ui/endSessionDialog.js:111
#, javascript-format
msgid ""
"%s %s will be installed after restart. Upgrade installation can take a long "
@ -1281,27 +1281,27 @@ msgstr ""
"voi kestää kauan: varmista varmuuskopioidesi ajantasaisuus ja toimivuus. "
"Kiinnitä kone myös verkkovirtaan."
#: js/ui/endSessionDialog.js:261
#: js/ui/endSessionDialog.js:259
msgid "Running on battery power: Please plug in before installing updates."
msgstr ""
"Laite käy akkuvirralla: kiinnitä verkkovirtaan ennen päivitysten asennusta."
#: js/ui/endSessionDialog.js:270
#: js/ui/endSessionDialog.js:268
msgid "Some applications are busy or have unsaved work"
msgstr "Jotkin sovellukset ovat kiireisiä tai sisältävät tallentamatonta työtä"
#: js/ui/endSessionDialog.js:275
#: js/ui/endSessionDialog.js:273
msgid "Other users are logged in"
msgstr "Muita käyttäjiä on kirjautuneena"
#. Translators: Remote here refers to a remote session, like a ssh login
#: js/ui/endSessionDialog.js:588
#: js/ui/endSessionDialog.js:586
#, javascript-format
msgid "%s (remote)"
msgstr "%s (etä)"
#. Translators: Console here refers to a tty like a VT console
#: js/ui/endSessionDialog.js:591
#: js/ui/endSessionDialog.js:589
#, javascript-format
msgid "%s (console)"
msgstr "%s (konsoli)"
@ -1319,11 +1319,11 @@ msgstr "Asenna laajennus"
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Ladataanko ja asennetaanko ”%s” sivustolta extensions.gnome.org?"
#: js/ui/extensionSystem.js:233
#: js/ui/extensionSystem.js:252
msgid "Extension Updates Available"
msgstr "Laajennusten päivityksiä saatavilla"
#: js/ui/extensionSystem.js:234
#: js/ui/extensionSystem.js:253
msgid "Extension updates are ready to be installed."
msgstr "Laajennusten päivitykset ovat valmiina asennettavaksi."
@ -1472,11 +1472,11 @@ msgstr "Näytä lähde"
msgid "Web Page"
msgstr "Verkkosivusto"
#: js/ui/main.js:277
#: js/ui/main.js:279
msgid "Logged in as a privileged user"
msgstr "Kirjautuneena etuoikeutettuna käyttäjänä"
#: js/ui/main.js:278
#: js/ui/main.js:280
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@ -1484,23 +1484,23 @@ msgstr ""
"Istunnon suorittamista etuoikeutettuna käyttäjänä tulisi välttää "
"tietoturvasyistä. Jos mahdollista, kirjaudu tavallisena käyttäjänä."
#: js/ui/main.js:317
#: js/ui/main.js:319
msgid "Screen Lock disabled"
msgstr "Näytön lukitus pois käytöstä"
#: js/ui/main.js:318
#: js/ui/main.js:320
msgid "Screen Locking requires the GNOME display manager."
msgstr "Näytön lukitus vaatii Gnomen kirjautumishallinnan."
#: js/ui/messageTray.js:1551
#: js/ui/messageTray.js:1548
msgid "System Information"
msgstr "Järjestelmän tiedot"
#: js/ui/mpris.js:199
#: js/ui/mpris.js:204
msgid "Unknown artist"
msgstr "Tuntematon esittäjä"
#: js/ui/mpris.js:209
#: js/ui/mpris.js:214
msgid "Unknown title"
msgstr "Tuntematon kappale"
@ -1574,16 +1574,16 @@ msgstr "Lopeta"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:434
#: js/ui/panel.js:437
msgid "Activities"
msgstr "Toiminnot"
#: js/ui/panel.js:713
#: js/ui/panel.js:716
msgctxt "System menu in the top bar"
msgid "System"
msgstr "Järjestelmä"
#: js/ui/panel.js:826
#: js/ui/panel.js:829
msgid "Top Bar"
msgstr "Yläpalkki"
@ -1614,11 +1614,11 @@ msgstr "Gnomen täytyy lukita näyttö"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: js/ui/screenShield.js:244 js/ui/screenShield.js:598
#: js/ui/screenShield.js:244 js/ui/screenShield.js:601
msgid "Unable to lock"
msgstr "Lukitus epäonnistui"
#: js/ui/screenShield.js:245 js/ui/screenShield.js:599
#: js/ui/screenShield.js:245 js/ui/screenShield.js:602
msgid "Lock was blocked by an application"
msgstr "Lukitus estettiin sovelluksen toimesta"
@ -2266,7 +2266,7 @@ msgstr "Palauta asetukset"
msgid "Keep Changes"
msgstr "Säilytä muutokset"
#: js/ui/windowManager.js:85
#: js/ui/windowManager.js:86
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"
@ -2275,7 +2275,7 @@ msgstr[1] "Asetusmuutokset palautetaan %d sekunnissa"
#. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height.
#: js/ui/windowManager.js:544
#: js/ui/windowManager.js:546
#, javascript-format
msgid "%d × %d"
msgstr "%d × %d"
@ -2368,12 +2368,12 @@ msgstr "Käytä tiettyä tilaa (esim. “gdm”) kirjautumisnäkymää varten"
msgid "List possible modes"
msgstr "Listaa mahdolliset tilat"
#: src/shell-app.c:279
#: src/shell-app.c:286
msgctxt "program"
msgid "Unknown"
msgstr "Tuntematon"
#: src/shell-app.c:530
#: src/shell-app.c:537
#, c-format
msgid "Failed to launch “%s”"
msgstr "Sovelluksen “%s” käynnistäminen epäonnistui"
@ -2407,6 +2407,9 @@ msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"Gnomen laajennussovellus Laajennukset käsittelee laajennusten päivitykset, "
"niiden asetukset ja sen avulla voi poistaa laajennuksia käytöstä tai "
"kokonaan järjestelmästä."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
@ -2493,19 +2496,19 @@ msgstr ""
"Jos kohtaat ongelmia järjestelmän kanssa, on suositeltavaa poistaa kaikki "
"laajennukset käytöstä."
#: subprojects/extensions-app/data/ui/extensions-window.ui:134
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
msgid "Manually Installed"
msgstr "Manuaalisesti asennettu"
#: subprojects/extensions-app/data/ui/extensions-window.ui:158
#: subprojects/extensions-app/data/ui/extensions-window.ui:159
msgid "Built-In"
msgstr "Sisäänrakennettu"
#: subprojects/extensions-app/data/ui/extensions-window.ui:199
#: subprojects/extensions-app/data/ui/extensions-window.ui:200
msgid "No Installed Extensions"
msgstr "Ei asennettuja laajennuksia"
#: subprojects/extensions-app/data/ui/extensions-window.ui:235
#: subprojects/extensions-app/data/ui/extensions-window.ui:236
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
@ -2513,7 +2516,11 @@ msgstr ""
"Valitettavasti asennettujen laajennusten listaa ei voitu muodostaa. Varmista "
"että olet kirjautunut Gnomeen ja yritä uudelleen."
#: subprojects/extensions-app/data/ui/extensions-window.ui:288
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
msgid "Extension Updates Ready"
msgstr "Laajennuspäivitykset valmiina"
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
msgid "Log Out…"
msgstr "Kirjaudu ulos…"

466
po/fr.po
View File

@ -21,16 +21,16 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master fr\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-03-19 14:34+0000\n"
"PO-Revision-Date: 2020-03-19 21:59+0100\n"
"Last-Translator: Guillaume Bernard <associations@guillaume-bernard.fr>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"Language: fr_FR\n"
"POT-Creation-Date: 2020-05-11 14:00+0000\n"
"PO-Revision-Date: 2020-05-12 15:16+0200\n"
"Last-Translator: Charles Monzat <charles.monzat@free.fr>\n"
"Language-Team: French <gnomefr@traduc.org>\n"
"Language: fr\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: Poedit 2.3\n"
"X-Generator: Gtranslator 3.36.0\n"
#: data/50-gnome-shell-system.xml:6
msgid "System"
@ -415,80 +415,12 @@ msgstr ""
msgid "Network Login"
msgstr "Identification réseau"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:4
#: js/extensionPrefs/js/main.js:242
#: js/extensionPrefs/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensions"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: js/extensionPrefs/js/main.js:243
msgid "Manage your GNOME Extensions"
msgstr "Gérer vos extensions GNOME"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"Extensions de GNOME gère la mise à jour des extensions, la configuration des "
"préférences des extensions et la suppression ou la désactivation des "
"extensions non désirées."
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configurer les extensions Shell de GNOME"
#: js/extensionPrefs/js/main.js:164
#, javascript-format
msgid "Remove “%s”?"
msgstr "Enlever « %s » ?"
#: js/extensionPrefs/js/main.js:165
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Si vous enlevez cette extension, vous devrez recommencer son téléchargement "
"si vous souhaitez la réactiver plus tard"
#: js/extensionPrefs/js/main.js:168 js/gdm/authPrompt.js:135
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913
msgid "Cancel"
msgstr "Annuler"
#: js/extensionPrefs/js/main.js:169
msgid "Remove"
msgstr "Enlever"
#: js/extensionPrefs/js/main.js:241
msgid "translator-credits"
msgstr ""
"Mathieu Bridon <bochecha@fedoraproject.org>\n"
"Pablo Martin-Gomez <pablo.martin-gomez@laposte.net>\n"
"Bruno Brouard <annoa.b@gmail.com>\n"
"Cyril Arnaud <cyril dot arnaud at gmail dot com>\n"
"Luc Guillemin <luc.guillemin@gmail.com>\n"
"Luc Pionchon <pionchon.luc@gmail.com>\n"
"Pierre Henry <pierrehenry73@yahoo.fr>\n"
"Alexandre Franke <alexandre.franke@gmail.com>\n"
"Mathieu Stumpf <psychoslave@culture-libre.org>\n"
"Alain Lojewski <allomervan@gmail.com>\n"
"Erwan Georget <egeorget@opmbx.org>\n"
"Julien Humbert <julroy67@gmail.com>\n"
"Claude Paroz <claude@2xlibre.net>\n"
"Charles Monzat <charles.monzat@free.fr>"
#: js/extensionPrefs/js/main.js:285
#: js/extensionPrefs/data/ui/extensions-window.ui:223
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
#: subprojects/extensions-app/data/ui/extensions-window.ui:224
msgid "Somethings gone wrong"
msgstr "Quelque chose sest mal passé"
#: js/extensionPrefs/js/main.js:292
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
msgid ""
"Were very sorry, but theres been a problem: the settings for this "
"extension cant be displayed. We recommend that you report the issue to the "
@ -498,106 +430,25 @@ msgstr ""
"extension ne peuvent être affichés. Nous vous recommandons de signaler ce "
"problème aux auteurs de lextension."
#: js/extensionPrefs/js/main.js:299
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
msgid "Technical Details"
msgstr "Détails techniques"
#: js/extensionPrefs/js/main.js:334
msgid "Copy Error"
msgstr "Copier lerreur"
#: js/extensionPrefs/js/main.js:361
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
msgid "Homepage"
msgstr "Site Web"
#: js/extensionPrefs/js/main.js:362
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
msgid "Visit extension homepage"
msgstr "Visiter le site Web de lextension"
#: js/extensionPrefs/js/main.js:479
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extension sera mise à jour à la prochaine connexion."
msgstr[1] "%d extensions seront mises à jour à la prochaine connexion."
#: js/extensionPrefs/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Description"
#: js/extensionPrefs/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Version"
#: js/extensionPrefs/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Auteur"
#: js/extensionPrefs/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Site Web"
#: js/extensionPrefs/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Enlever…"
#: js/extensionPrefs/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Aide"
#: js/extensionPrefs/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "À propos des extensions"
#: js/extensionPrefs/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Pour trouver et ajouter des extensions, visitez <a href=\"https://extensions."
"gnome.org\">extensions.gnome.org</a>."
#: js/extensionPrefs/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Avertissement"
#: js/extensionPrefs/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Les extensions peuvent poser des problèmes au système, y compris au niveau "
"des performances. Si vous pensez être dans ce cas, il est recommandé de "
"désactiver toutes les extensions."
#: js/extensionPrefs/data/ui/extensions-window.ui:134
msgid "Manually Installed"
msgstr "Installée manuellement"
#: js/extensionPrefs/data/ui/extensions-window.ui:158
msgid "Built-In"
msgstr "Intégrée"
#: js/extensionPrefs/data/ui/extensions-window.ui:199
msgid "No Installed Extensions"
msgstr "Aucune extension installée"
#: js/extensionPrefs/data/ui/extensions-window.ui:235
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Nous sommes désolés, mais il nest pas possible dobtenir la liste des "
"extensions installées. Vérifiez que vous êtes bien connecté à GNOME et "
"essayez encore une fois."
#: js/extensionPrefs/data/ui/extensions-window.ui:288
msgid "Log Out…"
msgstr "Fermer la session…"
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:372 js/ui/extensionDownloader.js:181
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
msgid "Cancel"
msgstr "Annuler"
#. Cisco LEAP
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
@ -649,71 +500,71 @@ msgid "(or swipe finger)"
msgstr "(ou faites glisser le doigt)"
#. Translators: The name of the power-off action in search
#: js/misc/systemActions.js:89
#: js/misc/systemActions.js:93
msgctxt "search-result"
msgid "Power Off"
msgstr "Éteindre"
#. Translators: A list of keywords that match the power-off action, separated by semicolons
#: js/misc/systemActions.js:92
#: js/misc/systemActions.js:96
msgid "power off;shutdown;reboot;restart;halt;stop"
msgstr "éteindre;fermer;débrancher;redémarrer;rallumer;reboot;arrêter;stop"
#. Translators: The name of the lock screen action in search
#: js/misc/systemActions.js:97
#: js/misc/systemActions.js:101
msgctxt "search-result"
msgid "Lock Screen"
msgstr "Verrouillage de lécran"
#. Translators: A list of keywords that match the lock screen action, separated by semicolons
#: js/misc/systemActions.js:100
#: js/misc/systemActions.js:104
msgid "lock screen"
msgstr "verrouillage;écran;"
#. Translators: The name of the logout action in search
#: js/misc/systemActions.js:105
#: js/misc/systemActions.js:109
msgctxt "search-result"
msgid "Log Out"
msgstr "Fermer la session"
#. Translators: A list of keywords that match the logout action, separated by semicolons
#: js/misc/systemActions.js:108
#: js/misc/systemActions.js:112
msgid "logout;log out;sign off"
msgstr "fermer;session;déconnecter;"
#. Translators: The name of the suspend action in search
#: js/misc/systemActions.js:113
#: js/misc/systemActions.js:117
msgctxt "search-result"
msgid "Suspend"
msgstr "Mettre en veille"
#. Translators: A list of keywords that match the suspend action, separated by semicolons
#: js/misc/systemActions.js:116
#: js/misc/systemActions.js:120
msgid "suspend;sleep"
msgstr "mettre en veille;sommeil;"
#. Translators: The name of the switch user action in search
#: js/misc/systemActions.js:121
#: js/misc/systemActions.js:125
msgctxt "search-result"
msgid "Switch User"
msgstr "Changer dutilisateur"
#. Translators: A list of keywords that match the switch user action, separated by semicolons
#: js/misc/systemActions.js:124
#: js/misc/systemActions.js:128
msgid "switch user"
msgstr "changer;utilisateur;"
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
#: js/misc/systemActions.js:131
#: js/misc/systemActions.js:135
msgid "lock orientation;unlock orientation;screen;rotation"
msgstr "verrouillage;déverrouillage;orientation;écran;rotation"
#: js/misc/systemActions.js:251
#: js/misc/systemActions.js:255
msgctxt "search-result"
msgid "Unlock Screen Rotation"
msgstr "Déverrouiller la rotation de lécran"
#: js/misc/systemActions.js:252
#: js/misc/systemActions.js:256
msgctxt "search-result"
msgid "Lock Screen Rotation"
msgstr "Verrouiller la rotation de lécran"
@ -879,53 +730,53 @@ msgstr "Refuser laccès"
msgid "Grant Access"
msgstr "Accorder laccès"
#: js/ui/appDisplay.js:898
#: js/ui/appDisplay.js:939
msgid "Unnamed Folder"
msgstr "Dossier sans nom"
#: js/ui/appDisplay.js:921
#: js/ui/appDisplay.js:962
msgid "Frequently used applications will appear here"
msgstr "Les applications fréquemment utilisées apparaîtront ici"
#: js/ui/appDisplay.js:1056
#: js/ui/appDisplay.js:1097
msgid "Frequent"
msgstr "Fréquemment utilisées"
#: js/ui/appDisplay.js:1063
#: js/ui/appDisplay.js:1104
msgid "All"
msgstr "Toutes"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2446 js/ui/panel.js:75
#: js/ui/appDisplay.js:2480 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Fenêtres ouvertes"
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82
#: js/ui/appDisplay.js:2500 js/ui/panel.js:82
msgid "New Window"
msgstr "Nouvelle fenêtre"
#: js/ui/appDisplay.js:2477
#: js/ui/appDisplay.js:2511
msgid "Launch using Dedicated Graphics Card"
msgstr "Démarrer en utilisant la carte graphique dédiée"
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239
#: js/ui/appDisplay.js:2539 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Enlever des favoris"
#: js/ui/appDisplay.js:2511
#: js/ui/appDisplay.js:2545
msgid "Add to Favorites"
msgstr "Ajouter aux favoris"
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93
#: js/ui/appDisplay.js:2555 js/ui/panel.js:93
msgid "Show Details"
msgstr "Afficher les détails"
#: js/ui/appFavorites.js:152
#: js/ui/appFavorites.js:153
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s a été ajouté à vos favoris."
#: js/ui/appFavorites.js:185
#: js/ui/appFavorites.js:186
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s a été supprimé de vos favoris."
@ -946,7 +797,7 @@ msgstr "Casque audio"
msgid "Headset"
msgstr "Micro-casque"
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
msgid "Microphone"
msgstr "Microphone"
@ -1102,7 +953,7 @@ msgstr "Aucun évènement"
msgid "Do Not Disturb"
msgstr "Ne pas déranger"
#: js/ui/calendar.js:1171
#: js/ui/calendar.js:1176
msgid "Clear"
msgstr "Effacer"
@ -1252,7 +1103,7 @@ msgstr "Échec de lauthentification. Essayez à nouveau."
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: js/ui/components/telepathyClient.js:787
#: js/ui/components/telepathyClient.js:823
#, javascript-format
msgid "%s is now known as %s"
msgstr "%s est maintenant connu sous le nom de %s"
@ -1308,23 +1159,23 @@ msgstr "Ajouter des horloges locales…"
msgid "World Clocks"
msgstr "Horloges locales"
#: js/ui/dateMenu.js:279
#: js/ui/dateMenu.js:289
msgid "Weather"
msgstr "Météo"
#: js/ui/dateMenu.js:394
#: js/ui/dateMenu.js:418
msgid "Select a location…"
msgstr "Choisir un emplacement…"
#: js/ui/dateMenu.js:407
#: js/ui/dateMenu.js:426
msgid "Loading…"
msgstr "Chargement…"
#: js/ui/dateMenu.js:417
#: js/ui/dateMenu.js:436
msgid "Go online for weather information"
msgstr "Chercher les informations météorologiques en ligne"
#: js/ui/dateMenu.js:419
#: js/ui/dateMenu.js:438
msgid "Weather information is currently unavailable"
msgstr "Les informations météorologiques ne sont pas disponibles actuellement"
@ -1464,35 +1315,35 @@ msgid "Other users are logged in"
msgstr "Dautres utilisateurs sont connectés"
#. Translators: Remote here refers to a remote session, like a ssh login
#: js/ui/endSessionDialog.js:588
#: js/ui/endSessionDialog.js:586
#, javascript-format
msgid "%s (remote)"
msgstr "%s (distant)"
#. Translators: Console here refers to a tty like a VT console
#: js/ui/endSessionDialog.js:591
#: js/ui/endSessionDialog.js:589
#, javascript-format
msgid "%s (console)"
msgstr "%s (console)"
#: js/ui/extensionDownloader.js:181
#: js/ui/extensionDownloader.js:185
msgid "Install"
msgstr "Installer"
#: js/ui/extensionDownloader.js:187
#: js/ui/extensionDownloader.js:191
msgid "Install Extension"
msgstr "Installer lextension"
#: js/ui/extensionDownloader.js:188
#: js/ui/extensionDownloader.js:192
#, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Télécharger et installer « %s » à partir de extensions.gnome.org ?"
#: js/ui/extensionSystem.js:228
#: js/ui/extensionSystem.js:252
msgid "Extension Updates Available"
msgstr "Mises à jour dextensions disponibles"
#: js/ui/extensionSystem.js:229
#: js/ui/extensionSystem.js:253
msgid "Extension updates are ready to be installed."
msgstr "Des mises à jour dextensions sont prêtes à être installées."
@ -1641,11 +1492,11 @@ msgstr "Afficher la source"
msgid "Web Page"
msgstr "Page Web"
#: js/ui/main.js:274
#: js/ui/main.js:279
msgid "Logged in as a privileged user"
msgstr "Connecté en tant quutilisateur privilégié"
#: js/ui/main.js:275
#: js/ui/main.js:280
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@ -1654,16 +1505,16 @@ msgstr ""
"des raisons de sécurité. Si possible, connectez-vous comme utilisateur "
"normal."
#: js/ui/main.js:281
#: js/ui/main.js:319
msgid "Screen Lock disabled"
msgstr "Verrouillage décran désactivé"
#: js/ui/main.js:282
#: js/ui/main.js:320
msgid "Screen Locking requires the GNOME display manager."
msgstr ""
"Le verrouillage de lécran nécessite le gestionnaire daffichage GNOME."
#: js/ui/messageTray.js:1554
#: js/ui/messageTray.js:1548
msgid "System Information"
msgstr "Informations du système"
@ -1743,16 +1594,16 @@ msgstr "Quitter"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:434
#: js/ui/panel.js:437
msgid "Activities"
msgstr "Activités"
#: js/ui/panel.js:713
#: js/ui/panel.js:716
msgctxt "System menu in the top bar"
msgid "System"
msgstr "Système"
#: js/ui/panel.js:826
#: js/ui/panel.js:829
msgid "Top Bar"
msgstr "Barre supérieure"
@ -1783,11 +1634,11 @@ msgstr "GNOME a besoin de verrouiller lécran"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: js/ui/screenShield.js:244 js/ui/screenShield.js:598
#: js/ui/screenShield.js:244 js/ui/screenShield.js:601
msgid "Unable to lock"
msgstr "Impossible de verrouiller"
#: js/ui/screenShield.js:245 js/ui/screenShield.js:599
#: js/ui/screenShield.js:245 js/ui/screenShield.js:602
msgid "Lock was blocked by an application"
msgstr "Le verrouillage a été bloqué par une application"
@ -1870,13 +1721,13 @@ msgid "The PIM must be a number or empty."
msgstr "Le numéro PIM doit être un nombre ou être vide."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:469
#: js/ui/shellMountOperation.js:465
#, javascript-format
msgid "Unable to start %s"
msgstr "Impossible de démarrer %s"
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:471
#: js/ui/shellMountOperation.js:467
#, javascript-format
msgid "Couldnt find the %s application"
msgstr "Impossible de trouver lapplication %s"
@ -2352,11 +2203,11 @@ msgstr "Erreur dautorisation Thunderbolt"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Impossible dautoriser le périphérique Thunderbolt : %s"
#: js/ui/status/volume.js:150
#: js/ui/status/volume.js:151
msgid "Volume changed"
msgstr "Volume modifié"
#: js/ui/status/volume.js:221
#: js/ui/status/volume.js:222
msgid "Volume"
msgstr "Volume"
@ -2390,23 +2241,23 @@ msgstr "Intégré seulement"
#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:370
#: js/ui/unlockDialog.js:371
msgid "%A %B %-d"
msgstr "%A %-d %B"
#: js/ui/unlockDialog.js:376
#: js/ui/unlockDialog.js:377
msgid "Swipe up to unlock"
msgstr "Faire glisser vers le haut pour déverrouiller"
#: js/ui/unlockDialog.js:377
#: js/ui/unlockDialog.js:378
msgid "Click or press a key to unlock"
msgstr "Cliquer ou appuyer sur une touche pour déverrouiller"
#: js/ui/unlockDialog.js:549
#: js/ui/unlockDialog.js:550
msgid "Unlock Window"
msgstr "Fenêtre de déverrouillage"
#: js/ui/unlockDialog.js:558
#: js/ui/unlockDialog.js:559
msgid "Log in as another user"
msgstr "Se connecter en tant quautre utilisateur"
@ -2439,7 +2290,7 @@ msgstr "Restaurer les paramètres"
msgid "Keep Changes"
msgstr "Conserver les modifications"
#: js/ui/windowManager.js:85
#: js/ui/windowManager.js:86
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"
@ -2448,7 +2299,7 @@ msgstr[1] "Les paramètres seront restaurés dans %d secondes"
#. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height.
#: js/ui/windowManager.js:544
#: js/ui/windowManager.js:546
#, javascript-format
msgid "%d × %d"
msgstr "%d × %d"
@ -2542,12 +2393,12 @@ msgstr ""
msgid "List possible modes"
msgstr "Lister les modes possibles"
#: src/shell-app.c:279
#: src/shell-app.c:286
msgctxt "program"
msgid "Unknown"
msgstr "Inconnu"
#: src/shell-app.c:530
#: src/shell-app.c:537
#, c-format
msgid "Failed to launch “%s”"
msgstr "Impossible de lancer « %s »"
@ -2564,6 +2415,156 @@ msgstr "Le mot de passe ne peut pas être vide"
msgid "Authentication dialog was dismissed by the user"
msgstr "La fenêtre dauthentification a été écartée par lutilisateur"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
#: subprojects/extensions-app/js/main.js:182
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensions"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: subprojects/extensions-app/js/main.js:183
msgid "Manage your GNOME Extensions"
msgstr "Gérer vos extensions GNOME"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"Extensions de GNOME gère la mise à jour des extensions, la configuration des "
"préférences des extensions et la suppression ou la désactivation des "
"extensions non désirées."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configurer les extensions Shell de GNOME"
#: subprojects/extensions-app/js/main.js:144
#, javascript-format
msgid "Remove “%s”?"
msgstr "Enlever « %s » ?"
#: subprojects/extensions-app/js/main.js:145
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Si vous enlevez cette extension, vous devrez recommencer son téléchargement "
"si vous souhaitez la réactiver plus tard"
#: subprojects/extensions-app/js/main.js:149
msgid "Remove"
msgstr "Enlever"
#: subprojects/extensions-app/js/main.js:181
msgid "translator-credits"
msgstr ""
"Mathieu Bridon <bochecha@fedoraproject.org>\n"
"Pablo Martin-Gomez <pablo.martin-gomez@laposte.net>\n"
"Bruno Brouard <annoa.b@gmail.com>\n"
"Cyril Arnaud <cyril dot arnaud at gmail dot com>\n"
"Luc Guillemin <luc.guillemin@gmail.com>\n"
"Luc Pionchon <pionchon.luc@gmail.com>\n"
"Pierre Henry <pierrehenry73@yahoo.fr>\n"
"Alexandre Franke <alexandre.franke@gmail.com>\n"
"Mathieu Stumpf <psychoslave@culture-libre.org>\n"
"Alain Lojewski <allomervan@gmail.com>\n"
"Erwan Georget <egeorget@opmbx.org>\n"
"Julien Humbert <julroy67@gmail.com>\n"
"Claude Paroz <claude@2xlibre.net>\n"
"Charles Monzat <charles.monzat@free.fr>"
#: subprojects/extensions-app/js/main.js:316
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extension sera mise à jour à la prochaine connexion."
msgstr[1] "%d extensions seront mises à jour à la prochaine connexion."
#: subprojects/extensions-app/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Description"
#: subprojects/extensions-app/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Version"
#: subprojects/extensions-app/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Auteur"
#: subprojects/extensions-app/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Site Web"
#: subprojects/extensions-app/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Enlever…"
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Aide"
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "À propos des extensions"
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Pour trouver et ajouter des extensions, visitez <a href=\"https://extensions."
"gnome.org\">extensions.gnome.org</a>."
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Avertissement"
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Les extensions peuvent poser des problèmes au système, y compris au niveau "
"des performances. Si vous pensez être dans ce cas, il est recommandé de "
"désactiver toutes les extensions."
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
msgid "Manually Installed"
msgstr "Installée manuellement"
#: subprojects/extensions-app/data/ui/extensions-window.ui:159
msgid "Built-In"
msgstr "Intégrée"
#: subprojects/extensions-app/data/ui/extensions-window.ui:200
msgid "No Installed Extensions"
msgstr "Aucune extension installée"
#: subprojects/extensions-app/data/ui/extensions-window.ui:236
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Nous sommes désolés, mais il nest pas possible dobtenir la liste des "
"extensions installées. Vérifiez que vous êtes bien connecté à GNOME et "
"essayez encore une fois."
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
#| msgid "Extension Updates Available"
msgid "Extension Updates Ready"
msgstr "Mises à jour dextensions prêtes"
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
msgid "Log Out…"
msgstr "Fermer la session…"
#. Translators: a file path to an extension directory
#: subprojects/extensions-tool/src/command-create.c:125
#, c-format
@ -2902,6 +2903,9 @@ msgstr[1] "%u entrées"
msgid "System Sounds"
msgstr "Sons système"
#~ msgid "Copy Error"
#~ msgstr "Copier lerreur"
#~| msgid "Username: "
#~ msgid "Username…"
#~ msgstr "Nom dutilisateur…"

597
po/fur.po

File diff suppressed because it is too large Load Diff

437
po/id.po
View File

@ -11,8 +11,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-03-19 14:34+0000\n"
"PO-Revision-Date: 2020-03-20 14:13+0700\n"
"POT-Creation-Date: 2020-05-11 14:00+0000\n"
"PO-Revision-Date: 2020-05-14 16:29+0700\n"
"Last-Translator: Kukuh Syafaat <kukuhsyafaat@gnome.org>\n"
"Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n"
"Language: id\n"
@ -20,7 +20,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: Poedit 2.3\n"
"X-Generator: Poedit 2.3.1\n"
"X-DamnedLies-Scope: partial\n"
"X-Poedit-SourceCharset: UTF-8\n"
@ -396,70 +396,12 @@ msgstr ""
msgid "Network Login"
msgstr "Log Masuk Jaringan"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:4
#: js/extensionPrefs/js/main.js:242
#: js/extensionPrefs/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Ekstensi"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: js/extensionPrefs/js/main.js:243
msgid "Manage your GNOME Extensions"
msgstr "Kelola Ekstensi GNOME Anda"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"Ekstensi GNOME menangani pemutakhiran ekstensi, mengkonfigurasi preferensi "
"ekstensi, dan menghapus atau menonaktifkan ekstensi yang tidak diinginkan."
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Konfigurasi Ekstensi GNOME Shell"
#: js/extensionPrefs/js/main.js:164
#, javascript-format
msgid "Remove “%s”?"
msgstr "Hapus \"%s\"?"
#: js/extensionPrefs/js/main.js:165
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Jika Anda menghapus ekstensi, Anda harus kembali untuk mengunduhnya jika "
"Anda ingin mengaktifkannya lagi"
#: js/extensionPrefs/js/main.js:168 js/gdm/authPrompt.js:135
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913
msgid "Cancel"
msgstr "Batal"
#: js/extensionPrefs/js/main.js:169
msgid "Remove"
msgstr "Hapus"
#: js/extensionPrefs/js/main.js:241
msgid "translator-credits"
msgstr ""
"Andika Triwidada <andika@gmail.com>, 2010-2014, 2017.\n"
"Dirgita <dirgitadevina@yahoo.co.id>, 2011, 2012, 2014.\n"
"Wibiharto <wibinem@yahoo.com>, 2011.\n"
"Kukuh Syafaat <kukuhsyafaat@gnome.org>, 2017-2020.\n"
"Sucipto <sucipto@pm.me>, 2020."
#: js/extensionPrefs/js/main.js:285
#: js/extensionPrefs/data/ui/extensions-window.ui:223
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
#: subprojects/extensions-app/data/ui/extensions-window.ui:224
msgid "Somethings gone wrong"
msgstr "Ada yang tidak beres"
#: js/extensionPrefs/js/main.js:292
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
msgid ""
"Were very sorry, but theres been a problem: the settings for this "
"extension cant be displayed. We recommend that you report the issue to the "
@ -469,105 +411,25 @@ msgstr ""
"tidak dapat ditampilkan. Kami menyarankan Anda melaporkan masalah ini kepada "
"penulis ekstensi."
#: js/extensionPrefs/js/main.js:299
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
msgid "Technical Details"
msgstr "Detail Teknis"
#: js/extensionPrefs/js/main.js:334
msgid "Copy Error"
msgstr "Salin Galat"
#: js/extensionPrefs/js/main.js:361
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
msgid "Homepage"
msgstr "Halaman Web"
#: js/extensionPrefs/js/main.js:362
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
msgid "Visit extension homepage"
msgstr "Kunjungi halaman web ekstensi"
#: js/extensionPrefs/js/main.js:479
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d ekstensi akan diperbarui pada log masuk berikutnya."
msgstr[1] "%d ekstensi akan diperbarui pada log masuk berikutnya."
#: js/extensionPrefs/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Deskripsi"
#: js/extensionPrefs/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Versi"
#: js/extensionPrefs/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Penulis"
#: js/extensionPrefs/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Situs Web"
#: js/extensionPrefs/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Hapus…"
#: js/extensionPrefs/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Bantuan"
#: js/extensionPrefs/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Tentang Ekstensi"
#: js/extensionPrefs/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Untuk menemukan dan menambahkan ekstensi, kunjungi <a href=\"https://"
"extensions.gnome.org\">extensions.gnome.org</a>."
#: js/extensionPrefs/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Peringatan"
#: js/extensionPrefs/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Ekstensi dapat menyebabkan masalah sistem, termasuk masalah kinerja. Jika "
"Anda mengalami masalah dengan sistem Anda, disarankan untuk menonaktifkan "
"semua ekstensi."
#: js/extensionPrefs/data/ui/extensions-window.ui:134
msgid "Manually Installed"
msgstr "Dipasang Secara Manual"
#: js/extensionPrefs/data/ui/extensions-window.ui:158
msgid "Built-In"
msgstr "Bawaan"
#: js/extensionPrefs/data/ui/extensions-window.ui:199
msgid "No Installed Extensions"
msgstr "Tidak Ada Ekstensi Terpasang"
#: js/extensionPrefs/data/ui/extensions-window.ui:235
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Kami sangat menyesal, tetapi tidak mungkin mendapatkan daftar ekstensi yang "
"dipasang. Pastikan Anda masuk ke GNOME dan coba lagi."
#: js/extensionPrefs/data/ui/extensions-window.ui:288
msgid "Log Out…"
msgstr "Keluar…"
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:372 js/ui/extensionDownloader.js:181
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
msgid "Cancel"
msgstr "Batal"
#. Cisco LEAP
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
@ -619,71 +481,71 @@ msgid "(or swipe finger)"
msgstr "(atau gesekkan jari)"
#. Translators: The name of the power-off action in search
#: js/misc/systemActions.js:89
#: js/misc/systemActions.js:93
msgctxt "search-result"
msgid "Power Off"
msgstr "Matikan"
#. Translators: A list of keywords that match the power-off action, separated by semicolons
#: js/misc/systemActions.js:92
#: js/misc/systemActions.js:96
msgid "power off;shutdown;reboot;restart;halt;stop"
msgstr "matikan;nyalakan ulang;berhenti"
#. Translators: The name of the lock screen action in search
#: js/misc/systemActions.js:97
#: js/misc/systemActions.js:101
msgctxt "search-result"
msgid "Lock Screen"
msgstr "Kunci Layar"
#. Translators: A list of keywords that match the lock screen action, separated by semicolons
#: js/misc/systemActions.js:100
#: js/misc/systemActions.js:104
msgid "lock screen"
msgstr "kunci layar"
#. Translators: The name of the logout action in search
#: js/misc/systemActions.js:105
#: js/misc/systemActions.js:109
msgctxt "search-result"
msgid "Log Out"
msgstr "Keluar"
#. Translators: A list of keywords that match the logout action, separated by semicolons
#: js/misc/systemActions.js:108
#: js/misc/systemActions.js:112
msgid "logout;log out;sign off"
msgstr "keluar;logout;log out;sign off"
#. Translators: The name of the suspend action in search
#: js/misc/systemActions.js:113
#: js/misc/systemActions.js:117
msgctxt "search-result"
msgid "Suspend"
msgstr "Suspensi"
#. Translators: A list of keywords that match the suspend action, separated by semicolons
#: js/misc/systemActions.js:116
#: js/misc/systemActions.js:120
msgid "suspend;sleep"
msgstr "suspensi;tidur"
#. Translators: The name of the switch user action in search
#: js/misc/systemActions.js:121
#: js/misc/systemActions.js:125
msgctxt "search-result"
msgid "Switch User"
msgstr "Ganti Pengguna"
#. Translators: A list of keywords that match the switch user action, separated by semicolons
#: js/misc/systemActions.js:124
#: js/misc/systemActions.js:128
msgid "switch user"
msgstr "ganti pengguna"
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
#: js/misc/systemActions.js:131
#: js/misc/systemActions.js:135
msgid "lock orientation;unlock orientation;screen;rotation"
msgstr "kunci orientasi;buka kunci orientasi;layar;rotasi"
#: js/misc/systemActions.js:251
#: js/misc/systemActions.js:255
msgctxt "search-result"
msgid "Unlock Screen Rotation"
msgstr "Buka Kunci Rotasi Layar"
#: js/misc/systemActions.js:252
#: js/misc/systemActions.js:256
msgctxt "search-result"
msgid "Lock Screen Rotation"
msgstr "Kunci Rotasi Layar"
@ -849,53 +711,53 @@ msgstr "Tolak Akses"
msgid "Grant Access"
msgstr "Beri Akses"
#: js/ui/appDisplay.js:898
#: js/ui/appDisplay.js:939
msgid "Unnamed Folder"
msgstr "Folder Tanpa Nama"
#: js/ui/appDisplay.js:921
#: js/ui/appDisplay.js:962
msgid "Frequently used applications will appear here"
msgstr "Aplikasi yang sering dipakai akan muncul di sini"
#: js/ui/appDisplay.js:1056
#: js/ui/appDisplay.js:1097
msgid "Frequent"
msgstr "Sering"
#: js/ui/appDisplay.js:1063
#: js/ui/appDisplay.js:1104
msgid "All"
msgstr "Semua"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2446 js/ui/panel.js:75
#: js/ui/appDisplay.js:2480 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Buka Jendela"
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82
#: js/ui/appDisplay.js:2500 js/ui/panel.js:82
msgid "New Window"
msgstr "Jendela Baru"
#: js/ui/appDisplay.js:2477
#: js/ui/appDisplay.js:2511
msgid "Launch using Dedicated Graphics Card"
msgstr "Luncurkan menggunakan Kartu Grafis Terdedikasi"
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239
#: js/ui/appDisplay.js:2539 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Hapus dari Favorit"
#: js/ui/appDisplay.js:2511
#: js/ui/appDisplay.js:2545
msgid "Add to Favorites"
msgstr "Tambah ke Favorit"
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93
#: js/ui/appDisplay.js:2555 js/ui/panel.js:93
msgid "Show Details"
msgstr "Tampilkan Rincian"
#: js/ui/appFavorites.js:152
#: js/ui/appFavorites.js:153
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s telah ditambahkan ke favorit Anda."
#: js/ui/appFavorites.js:185
#: js/ui/appFavorites.js:186
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s telah dihapus dari favorit Anda."
@ -916,7 +778,7 @@ msgstr "Headphone"
msgid "Headset"
msgstr "Headset"
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
msgid "Microphone"
msgstr "Mikrofon"
@ -1057,7 +919,7 @@ msgstr "Tak Ada Kejadian"
msgid "Do Not Disturb"
msgstr "Jangan Ganggu"
#: js/ui/calendar.js:1171
#: js/ui/calendar.js:1176
msgid "Clear"
msgstr "Bersihkan"
@ -1207,7 +1069,7 @@ msgstr "Maaf, tidak berhasil. Silakan coba lagi."
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: js/ui/components/telepathyClient.js:787
#: js/ui/components/telepathyClient.js:823
#, javascript-format
msgid "%s is now known as %s"
msgstr "%s sekarang dikenal sebagai %s"
@ -1251,23 +1113,23 @@ msgstr "Tambah jam dunia…"
msgid "World Clocks"
msgstr "Jam Dunia"
#: js/ui/dateMenu.js:279
#: js/ui/dateMenu.js:289
msgid "Weather"
msgstr "Cuaca"
#: js/ui/dateMenu.js:394
#: js/ui/dateMenu.js:418
msgid "Select a location…"
msgstr "Pilih lokasi…"
#: js/ui/dateMenu.js:407
#: js/ui/dateMenu.js:426
msgid "Loading…"
msgstr "Memuat…"
#: js/ui/dateMenu.js:417
#: js/ui/dateMenu.js:436
msgid "Go online for weather information"
msgstr "Pergi daring untuk informasi cuaca"
#: js/ui/dateMenu.js:419
#: js/ui/dateMenu.js:438
msgid "Weather information is currently unavailable"
msgstr "Informasi cuaca saat ini tidak tersedia"
@ -1409,35 +1271,35 @@ msgid "Other users are logged in"
msgstr "Pengguna lain sedang log masuk"
#. Translators: Remote here refers to a remote session, like a ssh login
#: js/ui/endSessionDialog.js:588
#: js/ui/endSessionDialog.js:586
#, javascript-format
msgid "%s (remote)"
msgstr "%s (jarak jauh)"
#. Translators: Console here refers to a tty like a VT console
#: js/ui/endSessionDialog.js:591
#: js/ui/endSessionDialog.js:589
#, javascript-format
msgid "%s (console)"
msgstr "%s (konsol)"
#: js/ui/extensionDownloader.js:181
#: js/ui/extensionDownloader.js:185
msgid "Install"
msgstr "Pasang"
#: js/ui/extensionDownloader.js:187
#: js/ui/extensionDownloader.js:191
msgid "Install Extension"
msgstr "Pasang Ekstensi"
#: js/ui/extensionDownloader.js:188
#: js/ui/extensionDownloader.js:192
#, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Unduh dan pasang \"%s\" dari extensions.gnome.org?"
#: js/ui/extensionSystem.js:228
#: js/ui/extensionSystem.js:252
msgid "Extension Updates Available"
msgstr "Pemutakhiran Ekstensi Tersedia"
#: js/ui/extensionSystem.js:229
#: js/ui/extensionSystem.js:253
msgid "Extension updates are ready to be installed."
msgstr "Pemutakhiran ekstensi siap dipasang."
@ -1584,11 +1446,11 @@ msgstr "Tilik Sumber"
msgid "Web Page"
msgstr "Halaman Web"
#: js/ui/main.js:274
#: js/ui/main.js:279
msgid "Logged in as a privileged user"
msgstr "Masuk sebagai pengguna istimewa"
#: js/ui/main.js:275
#: js/ui/main.js:280
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@ -1596,15 +1458,15 @@ msgstr ""
"Menjalankan sesi sebagai pengguna istimewa harus dihindari untuk alasan "
"keamanan. Jika memungkinkan, Anda harus masuk sebagai pengguna biasa."
#: js/ui/main.js:281
#: js/ui/main.js:319
msgid "Screen Lock disabled"
msgstr "Kunci Layar dinonaktifkan"
#: js/ui/main.js:282
#: js/ui/main.js:320
msgid "Screen Locking requires the GNOME display manager."
msgstr "Penguncian Layar memerlukan manajer tampilan GNOME."
#: js/ui/messageTray.js:1554
#: js/ui/messageTray.js:1548
msgid "System Information"
msgstr "Informasi Sistem"
@ -1684,16 +1546,16 @@ msgstr "Keluar"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:434
#: js/ui/panel.js:437
msgid "Activities"
msgstr "Aktivitas"
#: js/ui/panel.js:713
#: js/ui/panel.js:716
msgctxt "System menu in the top bar"
msgid "System"
msgstr "Sistem"
#: js/ui/panel.js:826
#: js/ui/panel.js:829
msgid "Top Bar"
msgstr "Bar Atas"
@ -1724,11 +1586,11 @@ msgstr "GNOME perlu mengunci layar"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: js/ui/screenShield.js:244 js/ui/screenShield.js:598
#: js/ui/screenShield.js:244 js/ui/screenShield.js:601
msgid "Unable to lock"
msgstr "Tak bisa mengunci"
#: js/ui/screenShield.js:245 js/ui/screenShield.js:599
#: js/ui/screenShield.js:245 js/ui/screenShield.js:602
msgid "Lock was blocked by an application"
msgstr "Kunci diblokir oleh suatu aplikasi"
@ -1811,13 +1673,13 @@ msgid "The PIM must be a number or empty."
msgstr "PIM harus berupa angka atau kosong."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:469
#: js/ui/shellMountOperation.js:465
#, javascript-format
msgid "Unable to start %s"
msgstr "Tak bisa memulai %s"
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:471
#: js/ui/shellMountOperation.js:467
#, javascript-format
msgid "Couldnt find the %s application"
msgstr "Tak bisa menemukan aplikasi %s"
@ -2290,11 +2152,11 @@ msgstr "Autorisasi Thunderbolt galat"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Tidak dapat mengautorisasi perangkat Thunderbolt: %s"
#: js/ui/status/volume.js:150
#: js/ui/status/volume.js:151
msgid "Volume changed"
msgstr "Volume diubah"
#: js/ui/status/volume.js:221
#: js/ui/status/volume.js:222
msgid "Volume"
msgstr "Volume"
@ -2334,23 +2196,23 @@ msgstr "Hanya Bawaan"
# %d: 1
#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:370
#: js/ui/unlockDialog.js:371
msgid "%A %B %-d"
msgstr "%A, %d %B"
#: js/ui/unlockDialog.js:376
#: js/ui/unlockDialog.js:377
msgid "Swipe up to unlock"
msgstr "Gesek ke atas untuk membuka kunci"
#: js/ui/unlockDialog.js:377
#: js/ui/unlockDialog.js:378
msgid "Click or press a key to unlock"
msgstr "Klik atau tekan tombol untuk membuka kunci"
#: js/ui/unlockDialog.js:549
#: js/ui/unlockDialog.js:550
msgid "Unlock Window"
msgstr "Buka Kunci Jendela"
#: js/ui/unlockDialog.js:558
#: js/ui/unlockDialog.js:559
msgid "Log in as another user"
msgstr "Masuk sebagai pengguna lain"
@ -2383,7 +2245,7 @@ msgstr "Balikkan Tatanan"
msgid "Keep Changes"
msgstr "Simpan Perubahan"
#: js/ui/windowManager.js:85
#: js/ui/windowManager.js:86
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"
@ -2392,7 +2254,7 @@ msgstr[1] "Perubahan tatanan akan dikembalikan dalam %d detik"
#. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height.
#: js/ui/windowManager.js:544
#: js/ui/windowManager.js:546
#, javascript-format
msgid "%d × %d"
msgstr "%d × %d"
@ -2485,12 +2347,12 @@ msgstr "Menggunakan mode tertentu, mis. \"gdm\" untuk layar masuk"
msgid "List possible modes"
msgstr "Menampilkan mode yang mungkin"
#: src/shell-app.c:279
#: src/shell-app.c:286
msgctxt "program"
msgid "Unknown"
msgstr "Tak dikenal"
#: src/shell-app.c:530
#: src/shell-app.c:537
#, c-format
msgid "Failed to launch “%s”"
msgstr "Gagal meluncurkan \"%s\""
@ -2507,6 +2369,144 @@ msgstr "Kata sandi tidak boleh kosong"
msgid "Authentication dialog was dismissed by the user"
msgstr "Dialog autentikasi ditolak oleh pengguna"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
#: subprojects/extensions-app/js/main.js:182
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Ekstensi"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: subprojects/extensions-app/js/main.js:183
msgid "Manage your GNOME Extensions"
msgstr "Kelola Ekstensi GNOME Anda"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"Ekstensi GNOME menangani pemutakhiran ekstensi, mengkonfigurasi preferensi "
"ekstensi, dan menghapus atau menonaktifkan ekstensi yang tidak diinginkan."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Konfigurasi Ekstensi GNOME Shell"
#: subprojects/extensions-app/js/main.js:144
#, javascript-format
msgid "Remove “%s”?"
msgstr "Hapus \"%s\"?"
#: subprojects/extensions-app/js/main.js:145
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Jika Anda menghapus ekstensi, Anda harus kembali untuk mengunduhnya jika "
"Anda ingin mengaktifkannya lagi"
#: subprojects/extensions-app/js/main.js:149
msgid "Remove"
msgstr "Hapus"
#: subprojects/extensions-app/js/main.js:181
msgid "translator-credits"
msgstr ""
"Andika Triwidada <andika@gmail.com>, 2010-2014, 2017.\n"
"Dirgita <dirgitadevina@yahoo.co.id>, 2011, 2012, 2014.\n"
"Wibiharto <wibinem@yahoo.com>, 2011.\n"
"Kukuh Syafaat <kukuhsyafaat@gnome.org>, 2017-2020.\n"
"Sucipto <sucipto@pm.me>, 2020."
#: subprojects/extensions-app/js/main.js:316
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d ekstensi akan diperbarui pada log masuk berikutnya."
msgstr[1] "%d ekstensi akan diperbarui pada log masuk berikutnya."
#: subprojects/extensions-app/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Deskripsi"
#: subprojects/extensions-app/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Versi"
#: subprojects/extensions-app/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Penulis"
#: subprojects/extensions-app/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Situs Web"
#: subprojects/extensions-app/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Hapus…"
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Bantuan"
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Tentang Ekstensi"
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Untuk menemukan dan menambahkan ekstensi, kunjungi <a href=\"https://"
"extensions.gnome.org\">extensions.gnome.org</a>."
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Peringatan"
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Ekstensi dapat menyebabkan masalah sistem, termasuk masalah kinerja. Jika "
"Anda mengalami masalah dengan sistem Anda, disarankan untuk menonaktifkan "
"semua ekstensi."
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
msgid "Manually Installed"
msgstr "Dipasang Secara Manual"
#: subprojects/extensions-app/data/ui/extensions-window.ui:159
msgid "Built-In"
msgstr "Bawaan"
#: subprojects/extensions-app/data/ui/extensions-window.ui:200
msgid "No Installed Extensions"
msgstr "Tidak Ada Ekstensi Terpasang"
#: subprojects/extensions-app/data/ui/extensions-window.ui:236
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Kami sangat menyesal, tetapi tidak mungkin mendapatkan daftar ekstensi yang "
"dipasang. Pastikan Anda masuk ke GNOME dan coba lagi."
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
msgid "Extension Updates Ready"
msgstr "Pemutakhiran Ekstensi Siap"
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
msgid "Log Out…"
msgstr "Keluar…"
#. Translators: a file path to an extension directory
#: subprojects/extensions-tool/src/command-create.c:125
#, c-format
@ -2844,6 +2844,9 @@ msgstr[1] "%u Masukan"
msgid "System Sounds"
msgstr "Suara Sistem"
#~ msgid "Copy Error"
#~ msgstr "Salin Galat"
#~ msgid "Username…"
#~ msgstr "Nama pengguna…"

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