Compare commits

..

126 Commits

Author SHA1 Message Date
b642f9275e Bump version to 3.36.3
Update NEWS.
2020-06-03 01:38:26 +02:00
4220cd6624 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-06-03 01:37:39 +02:00
47bcc09516 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


(cherry picked from commit b487846c0a)
2020-06-02 23:33:48 +00:00
1889a975ce Updated Slovenian translation 2020-06-01 22:09:31 +02:00
4b8e090d19 Updated Lithuanian translation 2020-05-31 22:50:19 +03:00
e74e691d84 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-29 21:59:10 +02:00
3ad2baede0 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 20:26:57 +02:00
3c69cb5677 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 20:26:57 +02:00
bd3f8de1e3 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 20:26:57 +02:00
27455c4458 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 20:26:57 +02:00
5fca21b943 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 20:26:57 +02:00
064633f4d5 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 20:26:57 +02:00
159ac3f180 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 20:26:57 +02:00
ba435e5f2d 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 20:26:56 +02:00
b0a12fee51 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 20:26:56 +02:00
b5591fef10 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 20:26:56 +02:00
04e8ebcb2d 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 20:26:56 +02:00
99ebef504d 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 10:46:13 +02:00
c8d91b2c30 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 10:45:06 +02:00
4099c446da Update Korean translation 2020-05-27 23:50:25 +00:00
d625618d1b 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 23:25:54 +02:00
a09feb4b47 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


(cherry picked from commit d81237b9d6)
2020-05-25 13:14:26 +00:00
bc3c1e5a68 Update German translation 2020-05-24 16:06:24 +00:00
b148a8bc60 Update Slovak translation 2020-05-24 07:27:55 +00:00
2327fc9287 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


(cherry picked from commit 0f947d4ff9)
2020-05-21 22:47:15 +00:00
28407c95b3 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


(cherry picked from commit d2583aa47b)
2020-05-21 21:43:35 +00:00
e210d3138b 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


(cherry picked from commit 3309031fd1)
2020-05-21 21:42:44 +00:00
3f24721c76 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


(cherry picked from commit 4e2ae30a47)
2020-05-18 23:39:55 +00:00
1a045bb210 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


(cherry picked from commit 32bc064d10)
2020-05-18 17:02:13 +00:00
db2917479a Update Serbian translation 2020-05-17 19:22:39 +00:00
5815f9ac0e Update Finnish translation 2020-05-16 11:02:59 +00:00
e84d10bf87 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


(cherry picked from commit 64a3ecf9b1)
2020-05-15 21:21:32 +00:00
40481314d2 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


(cherry picked from commit a47e0f9845)
2020-05-15 16:22:35 +00:00
daf25f273d Update Turkish translation 2020-05-15 03:04:25 +00:00
bc6a3329b4 Update Indonesian translation 2020-05-14 09:42:52 +00:00
d3934bd685 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


(cherry picked from commit 6d5e93b00b)
2020-05-13 19:15:37 +00:00
504d4b7ea4 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


(cherry picked from commit f526e592fe)
2020-05-13 18:00:55 +00:00
fde8519002 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-13 19:51:09 +02:00
e8ae2ea432 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-13 19:50:57 +02:00
57e67e0f31 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-13 19:50:21 +02:00
894ca0dd07 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-13 19:50:20 +02:00
5f945294c8 Update Japanese translation 2020-05-13 15:16:38 +00:00
a4d0f15edb Update Japanese translation 2020-05-13 15:07:29 +00:00
f781bdbcc8 Update Romanian translation 2020-05-12 20:10:31 +00:00
e8e79173d9 Update French translation 2020-05-12 14:14:34 +00:00
884a2623a0 Update Swedish translation 2020-05-11 22:35:45 +00:00
fbdb56eb6d Update Italian translation 2020-05-11 15:52:39 +00:00
e2c5e471c0 Updated Spanish translation 2020-05-11 17:29:09 +02:00
34306d7326 Update Ukrainian translation 2020-05-11 14:05:38 +00:00
c3bdaf7e41 extensions-app: Fix translatable string
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1232
2020-05-11 13:54:29 +00:00
c9950442d9 workspacesView: Lower scroll timeout
Looks like 250ms is too high, lower it to 150ms.

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

(cherry picked from commit e59ca7053b)
2020-05-11 13:34:57 +02:00
5cf104933e appDisplay: Lower scroll timeout
Looks like 250ms is too high, lower it to 150ms.

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

(cherry picked from commit 6895592a7b)
2020-05-11 13:34:36 +02:00
79aeabcf76 Update Romanian translation 2020-05-08 16:28:31 +00:00
1974724cb1 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

(cherry picked from commit 7d60f418e7)
2020-05-07 19:43:05 +00:00
d159bbfd79 Updated Spanish translation 2020-05-07 16:48:09 +02:00
881d330bc0 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


(cherry picked from commit a9d73b1017)
2020-05-07 13:10:26 +00:00
6a9ce0f18c Update British English translation 2020-05-07 10:48:02 +00:00
473a666cc0 Update Dutch translation 2020-05-06 11:13:18 +00:00
4872d5969c 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


(cherry picked from commit 5e254666b0)
2020-05-04 14:34:24 +00:00
048796d145 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


(cherry picked from commit 6aa1b817c9)
2020-05-04 14:33:50 +00:00
dfc016894e Updated Spanish translation 2020-05-04 09:57:25 +02:00
7b19a6f9b6 Update Polish translation
Fixes https://gitlab.gnome.org/Teams/Translation/pl/-/issues/6
2020-05-02 21:44:46 +02:00
e4199c71cc Update Slovak translation 2020-05-02 14:07:10 +00:00
abb401eaa8 appFavorites: Add eog to rename list
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1233


(cherry picked from commit 31cd8f738c)
2020-05-01 22:42:55 +00:00
118676bffb 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


(cherry picked from commit e06109c23c)
2020-05-01 14:32:38 +00:00
dff855942e Update Chinese (Taiwan) translation 2020-04-30 17:31:56 +00:00
1d3c1b1ee3 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-30 00:57:27 +02:00
7b75e9f5ed 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-30 00:57:27 +02:00
4336952822 Update Friulian translation 2020-04-29 22:25:52 +00:00
2a2634439c Bump version to 3.36.2
Update NEWS.
2020-04-29 22:39:21 +02:00
0d2d8cf623 Revert "endSessionDialog: apply updates by default"
Turns out it's not that clear in which cases we want to apply updates
and in which ones we shouldn't. For example one case is when the device
is running on battery, where we currently display a warning, but still
install updates by default.

So let's revert that again for now and hopefully work out a proper
concept for updates in the future.

This reverts commit ddb85c03c3.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1228
2020-04-29 19:51:05 +00:00
d64b1e6efb 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


(cherry picked from commit d3880c0bff)
2020-04-29 17:36:06 +00:00
bbf3a09e2a shell Always draw the cursor ourself when capturing stage
Mutter changed to never draw the cursor with the used API, as it can't
be done in a predictable manner, so always draw it ourself.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1224
2020-04-29 12:38:01 +00:00
e57a4e0937 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


(cherry picked from commit 4dfa39457e)
2020-04-28 20:11:15 +00:00
443d615edf 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


(cherry picked from commit 7d7a15f978)
2020-04-28 20:05:23 +00:00
006d0e8521 theme: tone down weekend with events
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2588


(cherry picked from commit e8f5a842b1)
2020-04-28 20:04:18 +00:00
1a5a01622a 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


(cherry picked from commit 3199620a83)
2020-04-28 20:03:44 +00:00
38e31b9f0d 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

(cherry picked from commit 325ff73c5b)
2020-04-28 22:00:32 +02:00
fb7e70d562 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


(cherry picked from commit 8d139bbd95)
2020-04-28 16:45:27 +00:00
63a6c0d6f9 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


(cherry picked from commit fb1bb291eb)
2020-04-28 16:45:08 +00:00
05c1a6dce6 Update Czech translation 2020-04-28 16:37:25 +00:00
4097f7943f 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


(cherry picked from commit 49d6db34b7)
2020-04-28 16:24:25 +00:00
802c2fe532 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


(cherry picked from commit 63a0e521fd)
2020-04-28 16:24:05 +00:00
9497ddd68a 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

(cherry picked from commit 2e80995f19)
2020-04-28 10:14:16 +02:00
890f5b591f 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


(cherry picked from commit 3ba4304da9)
2020-04-27 22:04:16 +00:00
5b0d013229 Update Czech translation 2020-04-22 12:51:51 +00:00
60ee6ab4b7 Update Brazilian Portuguese translation 2020-04-22 12:32:56 +00:00
18a5c74362 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


(cherry picked from commit b191e9ef91)
2020-04-17 22:59:00 +00:00
4895032054 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


(cherry picked from commit 5ec5978d4a)
2020-04-17 22:36:04 +00:00
6b24ab572c 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


(cherry picked from commit f4d90bc127)
2020-04-17 16:59:38 +00:00
35a3320851 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


(cherry picked from commit 3fac0632a8)
2020-04-13 15:05:18 +00:00
156e05fe90 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


(cherry picked from commit c2b518929d)
2020-04-13 15:04:31 +00:00
cc0fac895c Update Finnish translation 2020-04-13 15:03:18 +00:00
a6783692c5 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 14:37:35 -03:00
1c27b68bcc 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 14:37:35 -03:00
717c05a288 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 14:37:35 -03:00
e68604b1aa 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 14:37:35 -03:00
0368ad29e9 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 14:37:35 -03:00
b982ce394e 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


(cherry picked from commit 85846d88f0)
2020-04-06 15:00:05 +00:00
025647f585 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


(cherry picked from commit bc973b80d7)
2020-04-06 14:59:45 +00:00
7125b726ad 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


(cherry picked from commit 6b7c85b079)
2020-04-05 13:48:39 +00:00
aebfab7207 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


(cherry picked from commit 360f5b1642)
2020-04-05 12:46:11 +00:00
698bd5b3a9 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


(cherry picked from commit 1ca39e8586)
2020-04-04 19:40:10 +00:00
51e9f19f2f 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


(cherry picked from commit 07deda593a)
2020-04-04 19:30:49 +00:00
6d38a4a7b3 Update Latvian translation 2020-04-04 16:14:40 +00:00
dfcc5ffb1e screenShield: Wake up on deactivate()
Usually the screen is woken up before the shield is deactivated, but
it is also possible to unlock the session programmatically via the
org.gnome.ScreenSaver D-Bus API.

The intention is very likely not to unlock a turned off screen in
that case. Nor does it seem like a good idea to change the lock
state without any indication.

Waking up the screen is more likely to meet expectations and is
more reasonable too, so do that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1158


(cherry picked from commit fbe2e30f38)
2020-04-03 15:09:24 +00:00
8b80a4cf4d screenShield: Switch lightboxes off before unlock transition
There is no point in animating a transition with fullscreen black
rectangles stacked on top, so switch them off before rather than
after the transition.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1158


(cherry picked from commit fb6ead2881)
2020-04-03 15:08:58 +00:00
01e894c028 st/icon: Only load default fallback icon if an icon was set and failed to load
Commit c89d6a633 introduced a default fallback icon that would be displayed in
case the main gicon or the fallback gicon wasn't set or failed to load.

This broke the use case where a StIcon is created but no main icon or
fallback icon are set on purpose, for example the appindicator extension
which always creates a StIcon to represent icons in menu items but the
actual icons are only set if the application provides one, leaving the
menu showing the default fallback ("image-missing") icon for all menu
entries that don't actually have an icon provided by the application.

Fix that by only using the default fallback icon if the provided one
failed to load.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1173

(cherry picked from commit 7ff7fb5d3b)
2020-04-03 17:00:30 +02:00
856adfd1f1 extensionUtils: Add openPrefs() convenience method
Opening their own preferences is a reasonable desire for extensions,
so make up for breaking it by adding a convenience method for that
action.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1163

(cherry picked from commit 8030d9ad32)
2020-04-03 17:00:07 +02:00
efee3aa749 extensionSystem: Add method for opening extension prefs
Extension that want to expose their own preferences (for example as menu
items) do that by passing their UUID to gnome-shell-extension-prefs.

But since 3.36.1 the app is optional and no longer accepts arguments on
the command line. To adjust, extensions now need to make a D-Bus call
the extensions portal, just like the app and gnome-shell.

We will add a convenience method for that purpose, so it makes
sense to share the existing code. As it's extension-related, the
extension manager looks like the right place ...

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1163

(cherry picked from commit 45bc850715)
2020-04-03 16:58:15 +02:00
15e72da648 workspace: Fix chaining up
Gah, accidentally dropped the 'vfunc' prefix :-(

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1172
2020-04-03 15:47:01 +02:00
3f8bd1db25 extensions-app: Do not expand headerbar switch
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2563
2020-04-03 15:47:01 +02:00
3a863ee341 js: Account for promisified call() method
A promisified method expects the callback parameter to be either
a function (in which case the original method is called normally)
or omitted altogether (in which case a Promise is returned).

The call to open application details in Software does neither and
passes null instead, which will result in a warning (because no
function argument means a promise will be used, but not omitting
the parameter means we end up with too many arguments).

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2551
2020-04-03 02:03:18 +00:00
654a7af929 environment: Move g_dbus_connection_call() promisification
Commit 83c6b2ab promisified the method in endSessionDialog, which means
that after the module is imported, every caller will get the promisifed
version. That can be a bit surprising in completely unrelated modules,
so commit 764527c8 (on master) moved the promisification of more common
methods into environment, as that's initialized early and expected to be
shared between anything else.

Do the same for the call() method on the stable branch.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2551
2020-04-03 02:03:18 +00:00
8dd9cbac7f app-cache: Fix cache for folder translations
The app-cache code currently stores the folder translations in a hash
that can be accessed via shell_util_get_translated_folder_name().
This hash uses the filename (inc. extension) for the "desktop-directory"
as key which causes an issue when trying to find the translation
on AppDisplay._findBestFolderName() which gets categories (folder names)
from the app info which doesn't contain the ".directory" extension.

Fix that by storing the filename without extension as the hash key for
the cached folder translations.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1168


(cherry picked from commit 343b3351f1)
2020-04-03 00:40:34 +00:00
331db650dd appDisplay: Don't clear signal handler id before emitting
Otherwise we won't clear the 'view-loaded' handler after it was emitted.

Also move field initialization to the correct place, i.e. the init
function of the base class.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1169


(cherry picked from commit a9df4e7516)
2020-04-02 21:10:30 +00:00
428d38179d Update Serbian translation 2020-04-02 19:43:03 +00:00
fe9708ebd8 Update Basque translation 2020-04-02 16:15:32 +00:00
8398769321 Update Finnish translation 2020-04-02 09:44:36 +00:00
768c08ba9d main: Don't override DesktopAppInfo desktop if already GNOME
During the shell initialization we call the (deprecated) function to
override the Desktop environment in Gio DesktopAppInfo to make sure that
applications are correctly shown (as per commit b2fbf5a2), however this
might break the cases in which $XDG_CURRENT_DESKTOP is already set and
contains GNOME (given that is now a list).

In Ubuntu this is in fact set to: ubuntu:GNOME.
Now, if an application contains NotShowIn=ubuntu, the key will be ignored by
the shell, and the application is still listed everywhere.

So, override the DesktopAppInfo desktop environment only in the case that
the current desktop is not already GNOME.

At the current date I think we could just safely get rid of this override at
all, but there could be still cases where it still might be useful, like when
running as nested in some other environment, so keeping it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1156


(cherry picked from commit a0def23940)
2020-04-01 03:58:56 +00:00
69426cbfda Update Persian translation 2020-04-01 01:42:46 +00:00
9f968e7378 appDisplay: Clear animateLater callbacks when unmapping
In some situations we could end up not with lingering 'view-loaded'
handler. This could result in delayed spring animate-in being initiated,
e.g. after a minute after the activities overview was already closed.

Fix this by removing any lingering signal or later handlers when
unmapping.

Fixes: 5c33fe4a0a

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1155


(cherry picked from commit f49b58cf97)
2020-03-31 17:12:35 +00:00
1ab5e6973a Update Chinese (Taiwan) translation 2020-03-31 16:07:19 +00:00
1dea3341ec Update Friulian translation 2020-03-31 11:14:15 +00:00
8fda054dc5 Bump version to 3.36.1
Update NEWS.
2020-03-31 00:27:47 +02:00
e989684602 extensions-app/metainfo: Point screenshots to stable branch 2020-03-30 21:32:17 +02:00
166 changed files with 9083 additions and 13994 deletions

View File

@ -18,7 +18,7 @@ variables:
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
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:v2
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- find js -name '*.js' -exec js68 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- find js -name '*.js' -exec js60 -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:v2
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
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:v2
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- ./.gitlab-ci/check-potfiles.sh
<<: *only_default
no_template_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- ./.gitlab-ci/check-template-strings.sh
<<: *only_default
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: build
before_script:
- .gitlab-ci/checkout-mutter.sh
@ -83,7 +83,7 @@ build:
- build
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
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:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: test
before_script:
- ninja -C mutter/build install
@ -124,7 +124,11 @@ 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:

View File

@ -1,24 +0,0 @@
# 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

@ -0,0 +1,18 @@
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,11 +6,6 @@ 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,14 +18,12 @@ 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 --cache --cache-location $cache ${!extra_args} -o $output \
js subprojects/extensions-app/js
eslint -f unix ${!extra_args} -o $output js subprojects/extensions-app/js
}
list_commit_range_additions() {

149
NEWS
View File

@ -1,87 +1,122 @@
3.37.2
3.36.3
======
* Add support for "PrefersNonDefaultGPU" desktop key [Bastien; !1226]
* Add gnome-shell-extension-prefs wrapper for compatibility [Florian; !1220]
* Fix distorted fallback icons in top bar [Florian; #2578]
* Lower timeout for scrolling in overview [Alexander; #2602]
* Only start systemd units when running under systemd
[Carlos, Florian; #2755, !1242, !1252]
* Fix "ghost" media controls [Bryan; #2776]
* 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]
* Fix matching notifications by PID [Florian; #2592]
* Only allow updates for extensions that aren't cached [Florian; !1248]
* Fixed crashes [Jonas, Florian; #2709, #2757]
* Misc. bug fixes and cleanups [Michael, Piotr, Philip, Florian, Amr,
AsciiWolf; !1233, !1205, !1229, #2751, !1232, #2796, !1249, !1263,
!1277, #2286, !1288, !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
AsciiWolf, Michael Catanzaro, Philip Chimento, Jonas Dreßler, Bryan Dunsmore,
Carlos Garnacho, Amr Ibrahim, Michael Lass, Alexander Mikhaylenko,
Florian Müllner
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]
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Dušan Kazik [sk],
Piotr Drąg [pl], Daniel Mustieles [es], Nathan Follens [nl],
Bruce Cowan [en_GB], Florentina Mușat [ro], Yuri Chornoivan [uk],
Milo Casagrande [it], Anders Jonsson [sv], Charles Monzat [fr],
Daniel Șerbănescu [ro], sicklylife [ja], Kukuh Syafaat [id],
Emin Tufan Çetin [tr], Jiri Grönroos [fi], Марко Костић [sr],
Christian Kirbach [de], Changwoo Ryu [ko], Aurimas Černius [lt],
Matej Urbančič [sl]
3.37.1
3.36.2
======
* 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]
* Match ASCII alternatives of system actions [Will; #2688]
* Tone down weekend days with events in calendar [Jakub; #2588]
* Fix area screenshots on multi-monitor systems [Jonas Å; !1224]
* 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]
* Misc. bug fixes and cleanups [Jonas Å., Marco, Andre, Florian, Jonas D.;
!1155, !1156, !1169, !1168, #2551, #2563, !1172, !1179, !1160, #2562, #2578,
!1203, #2649, #2628, #2691, #1615, #2607, !1228]
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
Marco Trevisan (Treviño), Jonas Dreßler, Carlos Garnacho,
Andre Moreira Magalhaes, Florian Müllner, Georges Basile Stavracas Neto,
Jakub Steiner, Will Thompson, 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]
Rūdolfs Mazurs [lv], Rafael Fontenelle [pt_BR], Petr Kovář [cs],
Daniel Rusek [cs]
3.36.1
======
* Improve app folders [Jonas D.; !1011]
* Fix launching ibus daemon [Alynx; !1080]
* Do not shutdown ibus/xsettings on X11 compositor restart [Carlos; #2329]
* Hide hint text in entries when preedit is used [Carlos; !1084]
* Do not load app infos on main thread [Christian; #2282]
* Don't expose FDO Notifications interface on main bus name [Florian; !547]
* Fix icon of mobile broadband connections [Cosimo, Reik; !1097, !1105]
* Fix high-contrast/symbolic icon mix-up [Florian; #2414]
* Don't ellipsize times in world clock [Florian; !1090]
* Only check for extension updates if there are any extensions [Florian; !1100]
* Fix crash when trying to update removed extensions [Florian; #2343]
* Make Extensions app available as flatpak [Florian; !1081, !1106, !1087, !1133]
* Display fractional timezones as hours:minutes [Jonas D.; #2438]
* Fix assigning pad keybindings [Carlos; #2451]
* Handle embedded newlines in lock screen notifications [Florian; #2463]
* Fix OSK layout fallback for unsupported variants [Florian; #2471]
* Do not apply text color to color glyphs (emojis) [Carlos; #850]
* Check "Install pending software updates" by default [Michael; #2427]
* Do not warn about missing GDM on each login [Florian; #2432]
* Fix telepathy chat notifications [Marco; !1112]
* Fix offline updates support in end session dialog [Michael; #2276]
* Fix activating notifications by keyboard [Florian; #2319]
* Remove handling of 'blacklisted' extensions [Florian; !1132]
* Only update extensions if Extensions app is installed [Florian; #2346]
* Improve Norwegian on-screen-keyboard layout [Bjørn; !1073]
* Fix IM support for deleting surrounding text [Takao; !477]
* Fix blur effect with fractional scaling [Jonas D.; !1000]
* Use better location name in weather section [Florian; #2468]
* Fix glitch in sound feedback on volume changes [Florian; !1147]
* Fix on-screen keyboard regressions [Jonas D.; !1142]
* Improve screen-reader support [Luke; #2508, #2517]
* Fix password entry resize on login/lock screen [Florian; #2423]
* Fix crash when opening app picker [Jonas Å.; !1154]
* Misc. bug fixes and cleanups [Florian, Sebastian, Jan, Daniel, Philip, Mario,
Ray, Marco, Jonas D., Carlos, Georges; #2298, #2305, !1078, !1077, #2334,
#2381, !1093, !1098, #2386, !1108, !1109, !1114, !1076, !1072, !1115, !1088,
!1101, #2467, !1121, !1122, #2476, !1123, !1117, !1129, !1113, !1102, !1127,
#2238, !1131, !1135, !1136, !849, #2504, #2371, !1146, !1141, #2510, !1150]
Contributors:
Marco Trevisan (Treviño), Michael Catanzaro, Cosimo Cecchi, Jonas Dreßler,
Takao Fujiwara, Carlos Garnacho, Christian Hergert, Sebastian Keller,
Reik Keutterling, Bjørn Lie, Florian Müllner, Jwtiyar Nariman,
Georges Basile Stavracas Neto, Mario Sanchez Prada, Ray Strode, Jan Tojnar,
Daniel van Vugt, Philip Withnall, Luke Yelavich, Alynx Zhou, Jonas Ådahl
Translators:
Марко Костић [sr], Jordi Mas [ca], sicklylife [ja], Marek Černocký [cs],
Daniel Rusek [cs], Kjartan Maraas [nb], Tim Sabsch [de], Stas Solovey [ru],
Peter Mráz [sk], Rafael Fontenelle [pt_BR], Piotr Drąg [pl],
Milo Casagrande [it], Anders Jonsson [sv], Yuri Chornoivan [uk],
Kukuh Syafaat [id], Guillaume Bernard [fr], Daniel Mustieles [es],
Danial Behzadi [fa], Goran Vidović [hr], Yosef Or Boczko [he],
Emin Tufan Çetin [tr], Wolfgang Stöggl [de], Ibai Oihanguren Sala [eu],
Jwtiyar Nariman [ckb], Aurimas Černius [lt]
3.36.0
======

View File

@ -1,19 +1,12 @@
<node>
<interface name="org.gnome.Shell.CalendarServer">
<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 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>
<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,6 +2,7 @@
<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,7 +6,6 @@
<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>

View File

@ -1,94 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -14,6 +14,8 @@ $app_icon_padding: 24px;
}
}
//.app-display { spacing: 20px; }
/* App Icons */
$app_grid_fg_color: #fff;
@ -121,11 +123,15 @@ $app_grid_fg_color: #fff;
}
// Some hacks I don't even know
.all-apps {
.all-apps,
.frequent-apps > StBoxLayout {
// 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);
@ -133,3 +139,44 @@ $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

@ -204,7 +204,7 @@
.world-clocks-time {
font-weight: bold;
color: $fg_color;
font-feature-settings: "tnum";
font-feature-settings: "lnum";
@include fontsize($base_font_size);
text-align: right;
}

View File

@ -1,7 +1,5 @@
/* Looking Glass */
$text_fg_color: #ccc;
// Dialog
#LookingGlassDialog {
background-color: $osd_bg_color;
@ -54,11 +52,6 @@ $text_fg_color: #ccc;
&: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,10 +54,6 @@
@extend %status_text;
}
.grid-search-results {
spacing: $base_spacing * 6;
}
// Search results with icons
.grid-search-result {
@extend %app-well-app;

View File

@ -589,8 +589,8 @@ var LoginDialog = GObject.registerClass({
return actorBox;
}
vfunc_allocate(dialogBox) {
this.set_allocation(dialogBox);
vfunc_allocate(dialogBox, flags) {
this.set_allocation(dialogBox, flags);
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);
this._bannerView.allocate(bannerAllocation, flags);
if (authPromptAllocation)
this._authPrompt.allocate(authPromptAllocation);
this._authPrompt.allocate(authPromptAllocation, flags);
if (userSelectionAllocation)
this._userSelectionBox.allocate(userSelectionAllocation);
this._userSelectionBox.allocate(userSelectionAllocation, flags);
if (logoAllocation)
this._logoBin.allocate(logoAllocation);
this._logoBin.allocate(logoAllocation, flags);
if (sessionMenuButtonAllocation)
this._sessionMenuButton.allocate(sessionMenuButtonAllocation);
this._sessionMenuButton.allocate(sessionMenuButtonAllocation, flags);
}
_ensureUserListLoaded() {
@ -810,13 +810,12 @@ var LoginDialog = GObject.registerClass({
return;
this._logoBin.destroy_all_children();
const [valid, resourceScale] = this._logoBin.get_resource_scale();
if (this._logoFile && valid) {
if (this._logoFile && this._logoBin.resource_scale > 0) {
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,
resourceScale));
this._logoBin.resource_scale));
}
}

View File

@ -2,7 +2,7 @@
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
const { Clutter, Gdm, Gio, GLib } = imports.gi;
const { Clutter, Gio, GLib } = imports.gi;
const Signals = imports.signals;
const Batch = imports.gdm.batch;
@ -12,15 +12,6 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager;
Gio._promisify(Gdm.Client.prototype,
'open_reauthentication_channel', 'open_reauthentication_channel_finish');
Gio._promisify(Gdm.Client.prototype,
'get_user_verifier', 'get_user_verifier_finish');
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification_for_user', 'call_begin_verification_for_user_finish');
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification', 'call_begin_verification_finish');
var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
@ -177,12 +168,14 @@ var ShellUserVerifier = class {
this._checkForFingerprintReader();
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
if (userName)
this._openReauthenticationChannel(userName);
else
this._getUserVerifier();
if (userName) {
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
this._client.open_reauthentication_channel(userName, this._cancellable,
this._reauthenticationChannelOpened.bind(this));
} else {
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
}
}
cancel() {
@ -346,11 +339,10 @@ var ShellUserVerifier = class {
this._verificationFailed(false);
}
async _openReauthenticationChannel(userName) {
_reauthenticationChannelOpened(client, result) {
try {
this._clearUserVerifier();
this._userVerifier = await this._client.open_reauthentication_channel(
userName, this._cancellable);
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
@ -359,7 +351,8 @@ var ShellUserVerifier = class {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there
// is no session to reauthenticate. Fall back to performing
// verification from this login session
this._getUserVerifier();
client.get_user_verifier(this._cancellable,
this._userVerifierGot.bind(this));
return;
}
@ -373,11 +366,10 @@ var ShellUserVerifier = class {
this._hold.release();
}
async _getUserVerifier() {
_userVerifierGot(client, result) {
try {
this._clearUserVerifier();
this._userVerifier =
await this._client.get_user_verifier(this._cancellable);
this._userVerifier = client.get_user_verifier_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
@ -429,25 +421,35 @@ var ShellUserVerifier = class {
}
}
async _startService(serviceName) {
_startService(serviceName) {
this._hold.acquire();
try {
if (this._userName) {
await this._userVerifier.call_begin_verification_for_user(
serviceName, this._userName, this._cancellable);
} else {
await this._userVerifier.call_begin_verification(
serviceName, this._cancellable);
}
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError(this._userName
? 'Failed to start verification for user'
: 'Failed to start verification', e);
return;
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
});
} else {
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._hold.release();
});
}
this._hold.release();
}
_beginVerification() {

View File

@ -23,7 +23,6 @@
<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>
@ -102,6 +101,7 @@
<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

@ -6,15 +6,6 @@ const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
Gio._promisify(IBus.Bus.prototype,
'list_engines_async', 'list_engines_async_finish');
Gio._promisify(IBus.Bus.prototype,
'request_name_async', 'request_name_async_finish');
Gio._promisify(IBus.Bus.prototype,
'get_global_engine_async', 'get_global_engine_async_finish');
Gio._promisify(IBus.Bus.prototype,
'set_global_engine_async', 'set_global_engine_async_finish');
// Ensure runtime version matches
_checkIBusVersion(1, 5, 2);
@ -111,14 +102,16 @@ var IBusManager = class {
_onConnected() {
this._cancellable = new Gio.Cancellable();
this._initEngines();
this._initPanelService();
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
this._initPanelService.bind(this));
}
async _initEngines() {
_initEngines(ibus, result) {
try {
const enginesList =
await this._ibus.list_engines_async(-1, this._cancellable);
let enginesList = this._ibus.list_engines_async_finish(result);
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]);
@ -133,10 +126,9 @@ var IBusManager = class {
}
}
async _initPanelService() {
_initPanelService(ibus, result) {
try {
await this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable);
this._ibus.request_name_async_finish(result);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
@ -171,15 +163,19 @@ 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);
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(res);
if (!engine)
return;
} catch (e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
} catch (e) {
}
});
this._updateReadiness();
}
_updateReadiness() {
@ -227,7 +223,7 @@ var IBusManager = class {
return this._engines.get(id);
}
async setEngine(id, callback) {
setEngine(id, callback) {
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
@ -237,16 +233,18 @@ var IBusManager = class {
return;
}
try {
await this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
}
preloadEngines(ids) {

View File

@ -4,9 +4,6 @@ const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
Gio._promisify(IBus.Bus.prototype,
'create_input_context_async', 'create_input_context_async_finish');
var HIDE_PANEL_TIME = 50;
var InputMethod = GObject.registerClass(
@ -49,11 +46,15 @@ class InputMethod extends Clutter.InputMethod {
this._currentSource = this._inputSourceManager.currentSource;
}
async _onConnected() {
_onConnected() {
this._cancellable = new Gio.Cancellable();
this._ibus.create_input_context_async('gnome-shell', -1,
this._cancellable, this._setContext.bind(this));
}
_setContext(bus, res) {
try {
this._context = await this._ibus.create_input_context_async(
'gnome-shell', -1, this._cancellable);
this._context = this._ibus.create_input_context_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);

View File

@ -24,7 +24,8 @@ 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
@ -33,7 +34,8 @@ 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 } = imports.gi;
const { GLib, GnomeDesktop, Meta } = imports.gi;
const Main = imports.ui.main;
@ -62,11 +62,11 @@ var KeyboardManager = class {
return;
this._currentKeymap = { layouts, variants, options };
global.backend.set_keymap(layouts, variants, options);
Meta.get_backend().set_keymap(layouts, variants, options);
}
_applyLayoutGroupIndex(idx) {
global.backend.lock_layout_group(idx);
Meta.get_backend().lock_layout_group(idx);
}
apply(id) {

View File

@ -50,22 +50,25 @@ function canLock() {
}
async function registerSessionWithGDM() {
function registerSessionWithGDM() {
log("Registering session with GDM");
try {
await Gio.DBus.system.call(
'org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log('Not calling RegisterSession(): method not exported, GDM too old?');
}
Gio.DBus.system.call('org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null,
(source, result) => {
try {
source.call_finish(result);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log("Not calling RegisterSession(): method not exported, GDM too old?");
}
}
);
}
let _loginManager = null;
@ -171,19 +174,24 @@ var LoginManagerSystemd = class {
this._proxy.SuspendRemote(true);
}
async inhibit(reason, callback) {
try {
const inVariant = new GLib.Variant('(ssss)',
['sleep', 'GNOME Shell', reason, 'delay']);
const [outVariant_, fdList] =
await this._proxy.call_with_unix_fd_list('Inhibit',
inVariant, 0, -1, null, null);
const [fd] = fdList.steal_fds();
callback(new Gio.UnixInputStream({ fd }));
} catch (e) {
logError(e, 'Error getting systemd inhibitor');
callback(null);
}
inhibit(reason, callback) {
let inVariant = GLib.Variant.new('(ssss)',
['sleep',
'GNOME Shell',
reason,
'delay']);
this._proxy.call_with_unix_fd_list('Inhibit', inVariant, 0, -1, null, null,
(proxy, result) => {
let fd = -1;
try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd }));
} catch (e) {
logError(e, "Error getting systemd inhibitor");
callback(null);
}
});
}
_prepareForSleep(proxy, sender, [aboutToSuspend]) {

View File

@ -57,7 +57,9 @@ var ObjectManager = class {
// Start out inhibiting load until at least the proxy
// manager is loaded and the remote objects are fetched
this._numLoadInhibitors = 1;
this._initManagerProxy();
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
this._onManagerProxyLoaded.bind(this));
}
_tryToCompleteLoad() {
@ -71,7 +73,7 @@ var ObjectManager = class {
}
}
async _addInterface(objectPath, interfaceName, onFinished) {
_addInterface(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
if (!info) {
@ -87,38 +89,40 @@ var ObjectManager = class {
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
try {
await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => {
try {
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
});
}
_removeInterface(objectPath, interfaceName) {
@ -147,10 +151,9 @@ var ObjectManager = class {
}
}
async _initManagerProxy() {
_onManagerProxyLoaded(initable, result) {
try {
await this._managerProxy.init_async(
GLib.PRIORITY_DEFAULT, this._cancellable);
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize object manager for object ${this._serviceName}`);

View File

@ -1,146 +0,0 @@
// -*- 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

@ -7,8 +7,6 @@ const PermissionStore = imports.misc.permissionStore;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(Geoclue.Simple, 'new', 'new_finish');
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
const WEATHER_BUS_NAME = 'org.gnome.Weather';
@ -81,7 +79,16 @@ var WeatherClient = class {
this._weatherApp = null;
this._weatherProxy = null;
this._createWeatherProxy();
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null,
this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather',
@ -139,17 +146,9 @@ var WeatherClient = class {
(!this._needsAuth || this._weatherAuthorized);
}
async _createWeatherProxy() {
const nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
_onWeatherProxyReady(o, res) {
try {
this._weatherProxy = await Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null);
this._weatherProxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log(`Failed to create GNOME Weather proxy: ${e}`);
return;
@ -240,23 +239,25 @@ var WeatherClient = class {
}
}
async _startGClueService() {
_startGClueService() {
if (this._gclueStarting)
return;
this._gclueStarting = true;
try {
this._gclueService = await Geoclue.Simple.new(
'org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
this._setLocation(this._mostRecentLocation);
return;
}
this._gclueStarted = true;
this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring();
Geoclue.Simple.new('org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null,
(o, res) => {
try {
this._gclueService = Geoclue.Simple.new_finish(res);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
this._setLocation(this._mostRecentLocation);
return;
}
this._gclueStarted = true;
this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring();
});
}
_onGClueLocationChanged() {

View File

@ -68,8 +68,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._items = this._switcherList.icons;
}
vfunc_allocate(box) {
super.vfunc_allocate(box);
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
// 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);
this._thumbnails.allocate(childBox, flags);
}
}
@ -681,7 +681,8 @@ 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);
}
@ -749,9 +750,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
return super.vfunc_get_preferred_height(forWidth);
}
vfunc_allocate(box) {
vfunc_allocate(box, flags) {
// Allocate the main list items
super.vfunc_allocate(box);
super.vfunc_allocate(box, flags);
let contentBox = this.get_theme_node().get_content_box(box);
@ -766,7 +767,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);
this._arrows[i].allocate(childBox, flags);
}
}
@ -1056,7 +1057,7 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
return [minHeight, natHeight];
}
vfunc_allocate(box) {
vfunc_allocate(box, flags) {
let themeNode = this.get_theme_node();
let contentBox = themeNode.get_content_box(box);
const labelHeight = this._label.height;
@ -1064,20 +1065,20 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
labelHeight + themeNode.get_padding(St.Side.BOTTOM);
box.y2 -= totalLabelHeight;
super.vfunc_allocate(box);
super.vfunc_allocate(box, flags);
// 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.
box.y2 += totalLabelHeight;
this.set_allocation(box);
this.set_allocation(box, flags);
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);
this._label.allocate(childBox, flags);
}
highlight(index, justOutline) {

View File

@ -10,7 +10,6 @@ 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;
@ -18,6 +17,8 @@ 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;
@ -29,6 +30,8 @@ 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;
@ -43,6 +46,11 @@ 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) {
@ -138,7 +146,11 @@ var BaseAppView = GObject.registerClass({
padWithSpacing: true,
}, true);
this._grid = new IconGrid.IconGrid(gridParams);
if (this.use_pagination)
this._grid = new IconGrid.PaginatedIconGrid(gridParams);
else
this._grid = new IconGrid.IconGrid(gridParams);
this._grid.connect('child-focused', (grid, actor) => {
this._childFocused(actor);
});
@ -151,12 +163,6 @@ 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) {
@ -320,46 +326,24 @@ var BaseAppView = GObject.registerClass({
}
});
var AppDisplay = GObject.registerClass(
class AppDisplay extends BaseAppView {
var AllView = GObject.registerClass({
}, class AllView 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._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.add_actor(this._scrollView);
this._grid._delegate = this;
this._scrollView.set_policy(St.PolicyType.NEVER,
St.PolicyType.EXTERNAL);
@ -380,7 +364,24 @@ class AppDisplay extends BaseAppView {
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));
@ -433,29 +434,6 @@ class AppDisplay extends BaseAppView {
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() {
@ -538,7 +516,7 @@ class AppDisplay extends BaseAppView {
} catch (e) {
return false;
}
return this._parentalControlsManager.shouldShowApp(appInfo);
return appInfo.should_show();
});
let apps = this._appInfoList.map(app => app.get_id());
@ -648,7 +626,7 @@ class AppDisplay extends BaseAppView {
this._grid.currentPage = pageNumber;
// Animate the change between pages.
// Tween 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,
@ -679,7 +657,8 @@ class AppDisplay extends BaseAppView {
this._canScroll = true;
this._scrollTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
}
);
return Clutter.EVENT_STOP;
}
@ -970,6 +949,301 @@ class AppDisplay extends BaseAppView {
}
});
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();
@ -978,8 +1252,6 @@ var AppSearchProvider = class AppSearchProvider {
this.canLaunchSearch = false;
this._systemActions = new SystemActions.getDefault();
this._parentalControlsManager = ParentalControlsManager.getDefault();
}
getResultMetas(apps, callback) {
@ -1014,30 +1286,18 @@ 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 && this._parentalControlsManager.shouldShowApp(app.app_info);
return app && app.app_info.should_show();
});
results = results.concat(group.sort(
(a, b) => usage.compare(a, b)));
(a, b) => usage.compare(a, b)
));
});
results = results.concat(this._systemActions.getMatchingActions(terms));
@ -1172,7 +1432,7 @@ class FolderView extends BaseAppView {
if (!app)
return;
if (!this._parentalControlsManager.shouldShowApp(app.get_app_info()))
if (!app.get_app_info().should_show())
return;
if (apps.some(appIcon => appIcon.id == appId))
@ -1358,7 +1618,7 @@ var FolderIcon = GObject.registerClass({
return false;
let view = _getViewFromIcon(source);
if (!view || !(view instanceof AppDisplay))
if (!view || !(view instanceof AllView))
return false;
if (this._folder.get_strv('apps').includes(source.id))
@ -1680,7 +1940,7 @@ var AppFolderDialog = GObject.registerClass({
}
}
vfunc_allocate(box) {
vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box);
contentBox = this._viewBox.get_theme_node().get_content_box(contentBox);
@ -1693,7 +1953,7 @@ var AppFolderDialog = GObject.registerClass({
this._view._grid.topPadding = 0;
super.vfunc_allocate(box);
super.vfunc_allocate(box, flags);
// We can only start zooming after receiving an allocation
if (this._needsZoomAndFade)
@ -1918,7 +2178,7 @@ var AppIcon = GObject.registerClass({
}
vfunc_leave_event(crossingEvent) {
const ret = super.vfunc_leave_event(crossingEvent);
let ret = super.vfunc_leave_event(crossingEvent);
this.fake_release();
this._removeMenuTimeout();
@ -1926,22 +2186,22 @@ var AppIcon = GObject.registerClass({
}
vfunc_button_press_event(buttonEvent) {
const ret = super.vfunc_button_press_event(buttonEvent);
super.vfunc_button_press_event(buttonEvent);
if (buttonEvent.button == 1) {
this._setPopupTimeout();
} else if (buttonEvent.button == 3) {
this.popupMenu();
return Clutter.EVENT_STOP;
}
return ret;
return Clutter.EVENT_PROPAGATE;
}
vfunc_touch_event(touchEvent) {
const ret = super.vfunc_touch_event(touchEvent);
super.vfunc_touch_event(touchEvent);
if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN)
this._setPopupTimeout();
return ret;
return Clutter.EVENT_PROPAGATE;
}
vfunc_clicked(button) {
@ -2110,7 +2370,7 @@ var AppIcon = GObject.registerClass({
return source != this &&
(source instanceof this.constructor) &&
(view instanceof AppDisplay);
(view instanceof AllView);
}
_setHoveringByDnd(hovering) {
@ -2211,12 +2471,14 @@ 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 => {
@ -2246,16 +2508,10 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
if (discreteGpuAvailable &&
this._source.app.state == Shell.AppState.STOPPED) {
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._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card"));
this._onDiscreteGpuMenuItem.connect('activate', () => {
this._source.animateLaunch();
this._source.app.launch(0, -1, gpuPref);
this._source.app.launch(0, -1, true);
this.emit('activate-window', null);
});
}
@ -2297,18 +2553,19 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {
this._appendSeparator();
let item = this._appendMenuItem(_("Show Details"));
item.connect('activate', async () => {
item.connect('activate', () => {
let id = this._source.app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
bus.call(
'org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
new GLib.Variant.new(
'(sava{sv})', ['details', [args], null]),
null, 0, -1, null);
Main.overview.hide();
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
Main.overview.hide();
});
});
}
}

View File

@ -2,7 +2,6 @@
/* exported getAppFavorites */
const Shell = imports.gi.Shell;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const Signals = imports.signals;
const Main = imports.ui.main;
@ -66,13 +65,6 @@ 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));
@ -104,7 +96,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 && this._parentalControlsManager.shouldShowApp(app.app_info));
.filter(app => app != null);
this._favorites = {};
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
@ -143,9 +135,6 @@ 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,8 +147,9 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
_onDeviceSelected(dialog, device) {
let connection = this._dbusImpl.get_connection();
let info = this._dbusImpl.get_info();
const deviceName = Object.keys(AudioDevice)
.filter(dev => AudioDevice[dev] === device)[0].toLowerCase();
let 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('notify::allocation', () => {
this._barLevelWidth = this.allocation.get_width();
this.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width();
});
this._customAccessible = St.GenericAccessible.new_for_actor(this);

View File

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

View File

@ -199,52 +199,46 @@ class DBusEventSource extends EventSourceBase {
this._initialized = false;
this._dbusProxy = new CalendarServer();
this._initProxy();
}
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
let loaded = false;
async _initProxy() {
let loaded = false;
try {
await this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null);
loaded = true;
} catch (e) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
// NameOwnerChanged which will finish loading
//
// (But still _initialized to false, because the proxy does not know
// about the HasCalendars property and would cause an exception trying
// to read it)
if (!e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
log('Error loading calendars: %s'.format(e.message));
return;
try {
this._dbusProxy.init_finish(result);
loaded = true;
} catch (e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
// NameOwnerChanged which will finish loading
//
// (But still _initialized to false, because the proxy does not know
// about the HasCalendars property and would cause an exception trying
// to read it)
} else {
log('Error loading calendars: %s'.format(e.message));
return;
}
}
}
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.connectSignal('Changed', this._onChanged.bind(this));
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
});
this._dbusProxy.connect('g-properties-changed', () => {
this.notify('has-calendars');
});
this._initialized = loaded;
if (loaded) {
this.notify('has-calendars');
this._onNameAppeared();
else
this._onNameVanished();
}
});
this._dbusProxy.connect('g-properties-changed', () => {
this.notify('has-calendars');
});
this._initialized = loaded;
if (loaded) {
this.notify('has-calendars');
this._onNameAppeared();
}
}
destroy() {
@ -263,7 +257,7 @@ class DBusEventSource extends EventSourceBase {
}
_resetCache() {
this._events = new Map();
this._events = [];
this._lastRequestBegin = null;
this._lastRequestEnd = null;
}
@ -279,47 +273,28 @@ class DBusEventSource extends EventSourceBase {
this.emit('changed');
}
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
const [appointments = []] = argArray;
let changed = false;
_onChanged() {
this._loadEvents(false);
}
_onEventsReceived(results, _error) {
let newEvents = [];
let appointments = results[0] || [];
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 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);
this._events.set(event.id, event);
changed = true;
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
if (changed)
this.emit('changed');
}
_onEventsRemoved(dbusProxy, nameOwner, argArray) {
const [ids = []] = argArray;
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');
this._events = newEvents;
this._isLoading = false;
this.emit('changed');
}
_loadEvents(forceReload) {
@ -328,38 +303,33 @@ class DBusEventSource extends EventSourceBase {
return;
if (this._curRequestBegin && this._curRequestEnd) {
if (forceReload) {
this._events.clear();
this.emit('changed');
}
this._dbusProxy.SetTimeRangeRemote(
this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
Gio.DBusCallFlags.NONE);
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
this._onEventsReceived.bind(this),
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(true);
}
}
*_getFilteredEvents(begin, end) {
for (const event of this._events.values()) {
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
yield event;
this._loadEvents(false);
}
}
getEvents(begin, end) {
let result = [...this._getFilteredEvents(begin, end)];
let result = [];
for (let n = 0; n < this._events.length; n++) {
let event = this._events[n];
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;
@ -373,8 +343,12 @@ class DBusEventSource extends EventSourceBase {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
const { done } = this._getFilteredEvents(dayBegin, dayEnd).next();
return !done;
let events = this.getEvents(dayBegin, dayEnd);
if (events.length == 0)
return false;
return true;
}
});
@ -726,11 +700,12 @@ var Calendar = GObject.registerClass({
var EventMessage = GObject.registerClass(
class EventMessage extends MessageList.Message {
_init(event, date) {
super._init('', '');
super._init('', event.summary);
this._event = event;
this._date = date;
this.update(event);
this.setTitle(this._formatEventTime());
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
@ -742,13 +717,6 @@ 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);
@ -906,7 +874,7 @@ class EventsSection extends MessageList.MessageListSection {
}
_reloadEvents() {
if (this._eventSource.isLoading || this._reloading)
if (this._eventSource.isLoading)
return;
this._reloading = true;
@ -932,7 +900,6 @@ class EventsSection extends MessageList.MessageListSection {
this._messageById.set(event.id, message);
this.addMessage(message, false);
} else {
message.update(event);
this.moveMessage(message, i, false);
}
}

View File

@ -13,13 +13,17 @@ 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,7 +125,8 @@ 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

@ -10,7 +10,6 @@ const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype, 'init_async', 'init_finish');
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
@ -483,37 +482,39 @@ var VPNRequestHandler = class {
}
}
async _readStdoutOldStyle() {
const [line, len_] =
await this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null);
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let [line, len_] = this._dataStdout.read_line_finish_utf8(result);
if (line === null) {
// end of file
this._stdout.close(null);
return;
}
if (line == null) {
// end of file
this._stdout.close(null);
return;
}
this._vpnChildProcessLineOldStyle(line);
this._vpnChildProcessLineOldStyle(line);
// try to read more!
this._readStdoutOldStyle();
// try to read more!
this._readStdoutOldStyle();
});
}
async _readStdoutNewStyle() {
const cnt =
await this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null);
_readStdoutNewStyle() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let cnt = this._dataStdout.fill_finish(result);
if (cnt === 0) {
// end of file
this._showNewStyleDialog();
if (cnt == 0) {
// end of file
this._showNewStyleDialog();
this._stdout.close(null);
return;
}
this._stdout.close(null);
return;
}
// Try to read more
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
// Try to read more
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
});
}
_showNewStyleDialog() {
@ -620,17 +621,15 @@ var NetworkAgent = class {
this._native.connect('cancel-request', this._cancelRequest.bind(this));
this._initialized = false;
this._initNative();
}
async _initNative() {
try {
await this._native.init_async(GLib.PRIORITY_DEFAULT, null);
this._initialized = true;
} catch (e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
this._native.init_async(GLib.PRIORITY_DEFAULT, null, (o, res) => {
try {
this._native.init_finish(res);
this._initialized = true;
} catch (e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
});
}
enable() {

View File

@ -330,13 +330,11 @@ var AuthenticationDialog = GObject.registerClass({
this._sessionRequestTimeoutId = 0;
if (this.state != ModalDialog.State.OPENED)
return GLib.SOURCE_REMOVE;
return;
this._passwordEntry.hide();
this._cancelButton.grab_key_focus();
this._okButton.reactive = false;
return GLib.SOURCE_REMOVE;
};
if (delay) {

View File

@ -7,14 +7,6 @@ var Tpl = null;
var Tp = null;
try {
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
Gio._promisify(Tp.Channel.prototype, 'close_async', 'close_finish');
Gio._promisify(Tp.Channel.prototype,
'send_message_async', 'send_message_finish');
Gio._promisify(Tp.ChannelDispatchOperation.prototype,
'claim_with_async', 'claim_with_finish');
Gio._promisify(Tpl.LogManager.prototype,
'get_filtered_events_async', 'get_filtered_events_finish');
} catch (e) {
log('Telepathy is not available, chat integration will be disabled.');
}
@ -223,7 +215,7 @@ class TelepathyClient extends Tp.BaseClient {
// We can only handle text channel, so close any other channel
if (!(channel instanceof Tp.TextChannel)) {
channel.close_async();
channel.close_async(null);
continue;
}
@ -269,7 +261,7 @@ class TelepathyClient extends Tp.BaseClient {
}
}
async _approveTextChannel(account, conn, channel, dispatchOp, context) {
_approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle_, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
@ -278,15 +270,17 @@ class TelepathyClient extends Tp.BaseClient {
return;
}
context.accept();
// Approve private text channels right away as we are going to handle it
try {
await dispatchOp.claim_with_async(this);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: %s'.format(err.toString()));
}
dispatchOp.claim_with_async(this, (o, result) => {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: %s'.format(err.toString()));
}
});
context.accept();
}
_delegatedChannelsCb(_client, _channels) {
@ -447,14 +441,17 @@ class ChatSource extends MessageTray.Source {
}
}
async _getLogMessages() {
_getLogMessages() {
let logManager = Tpl.LogManager.dup_singleton();
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
const [events] = await logManager.get_filtered_events_async(
this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null);
logManager.get_filtered_events_async(this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, this._displayPendingMessages.bind(this));
}
_displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
this._ensureNotification();
@ -512,7 +509,9 @@ class ChatSource extends MessageTray.Source {
this._ackMessages();
// The chat box has been destroyed so it can't
// handle the channel any more.
this._channel.close_async();
this._channel.close_async((channel, result) => {
channel.close_finish(result);
});
} else {
// Don't indicate any unread messages when the notification
// that represents them has been destroyed.
@ -610,7 +609,9 @@ class ChatSource extends MessageTray.Source {
}
let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0);
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
});
}
setChatState(state) {

View File

@ -292,11 +292,11 @@ class DashActor extends St.Widget {
});
}
vfunc_allocate(box) {
vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box);
let availWidth = contentBox.x2 - contentBox.x1;
this.set_allocation(box);
this.set_allocation(box, flags);
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);
appIcons.allocate(childBox, flags);
childBox.y1 = contentBox.y2 - showAppsNatHeight;
childBox.y2 = contentBox.y2;
showAppsButton.allocate(childBox);
showAppsButton.allocate(childBox, flags);
}
vfunc_get_preferred_height(forWidth) {
@ -815,12 +815,7 @@ var Dash = GObject.registerClass({
else
pos = 0; // always insert at the top when dash is empty
// 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) {
if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
this._dragPlaceholderPos = pos;
// Don't allow positioning before or after self
@ -848,6 +843,11 @@ 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

@ -300,13 +300,13 @@ class WeatherSection extends St.Button {
this.child = box;
let titleBox = new St.BoxLayout({ style_class: 'weather-header-box' });
this._titleLabel = new St.Label({
titleBox.add_child(new St.Label({
style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_align: Clutter.ActorAlign.END,
});
titleBox.add_child(this._titleLabel);
text: _('Weather'),
}));
box.add_child(titleBox);
this._titleLocation = new St.Label({
@ -433,8 +433,10 @@ class WeatherSection extends St.Button {
_updateForecasts() {
this._forecastGrid.destroy_all_children();
if (!this._weatherClient.hasLocation)
if (!this._weatherClient.hasLocation) {
this._setStatusLabel(_("Select a location…"));
return;
}
const { info } = this._weatherClient;
this._titleLocation.text = this._findBestLocationName(info.location);
@ -461,12 +463,6 @@ 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();
@ -565,8 +561,8 @@ class FreezableBinLayout extends Clutter.BinLayout {
return this._savedHeight;
}
vfunc_allocate(container, allocation) {
super.vfunc_allocate(container, allocation);
vfunc_allocate(container, allocation, flags) {
super.vfunc_allocate(container, allocation, flags);
let [width, height] = allocation.get_size();
this._savedWidth = [width, width];

View File

@ -278,7 +278,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
}
async _onPkOfflineProxyCreated(proxy, error) {
_onPkOfflineProxyCreated(proxy, error) {
if (error) {
log(error.message);
return;
@ -293,12 +293,15 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
// It only makes sense to check for this permission if PackageKit is available.
try {
this._updatesPermission = await Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null,
(source, res) => {
try {
this._updatesPermission = Polkit.Permission.new_finish(res);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
});
}
_onDestroy() {
@ -677,7 +680,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
this._checkBox.visible = dialogContent.checkBoxText && updatePrepared && updatesAllowed;
this._checkBox.checked = this._checkBox.visible;
this._checkBox.checked = updatePrepared && updateTriggered;
// We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have

View File

@ -10,20 +10,11 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, Gio, GLib, GObject, Meta, Polkit, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const System = imports.system;
Gio._promisify(Gio.DataInputStream.prototype, 'fill_async', 'fill_finish');
Gio._promisify(Gio.DataInputStream.prototype,
'read_line_async', 'read_line_finish');
Gio._promisify(Gio.DBus, 'get', 'get_finish');
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
Gio._promisify(Gio.DBusProxy, 'new', 'new_finish');
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
Gio._promisify(Gio.DBusProxy.prototype,
'call_with_unix_fd_list', 'call_with_unix_fd_list_finish');
Gio._promisify(Polkit.Permission, 'new', 'new_finish');
let _localTimeZone = null;
@ -245,15 +236,16 @@ function _loggingFunc(...args) {
}
function init() {
// Add some bindings to the global JS namespace
globalThis.global = Shell.Global.get();
// 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();
globalThis.log = _loggingFunc;
window.log = _loggingFunc;
globalThis._ = Gettext.gettext;
globalThis.C_ = Gettext.pgettext;
globalThis.ngettext = Gettext.ngettext;
globalThis.N_ = s => s;
window._ = Gettext.gettext;
window.C_ = Gettext.pgettext;
window.ngettext = Gettext.ngettext;
window.N_ = s => s;
GObject.gtypeNameBasedOnJSPath = true;
@ -285,11 +277,6 @@ 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);
};
@ -360,7 +347,9 @@ 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

@ -230,7 +230,8 @@ var ExtensionManager = class {
null,
Gio.DBusCallFlags.NONE,
-1,
null);
null,
(conn, res) => conn.call_finish(res));
return true;
}
@ -260,8 +261,7 @@ var ExtensionManager = class {
if (!extension)
return;
const message = error instanceof Error
? error.message : error.toString();
let message = error.toString();
extension.error = message;
extension.state = ExtensionState.ERROR;
@ -486,15 +486,19 @@ 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

@ -114,11 +114,8 @@ class BaseIcon extends St.Bin {
if (this._setSizeManually) {
size = this.iconSize;
} else {
const { scaleFactor } =
St.ThemeContext.get_for_stage(global.stage);
let [found, len] = node.lookup_length('icon-size', false);
size = found ? len / scaleFactor : ICON_SIZE;
size = found ? len : ICON_SIZE;
}
if (this.iconSize == size && this._iconBin.child)
@ -197,9 +194,9 @@ function zoomOutActorAtPos(actor, x, y) {
});
}
function animateIconPosition(icon, box, nChangedIcons) {
function animateIconPosition(icon, box, flags, nChangedIcons) {
if (!icon.has_allocation() || icon.allocation.equal(box) || icon.opacity === 0) {
icon.allocate(box);
icon.allocate(box, flags);
return false;
}
@ -207,7 +204,7 @@ function animateIconPosition(icon, box, nChangedIcons) {
icon.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
icon.set_easing_delay(nChangedIcons * ICON_POSITION_DELAY);
icon.allocate(box);
icon.allocate(box, flags);
icon.restore_easing_state();
@ -226,6 +223,7 @@ var IconGrid = GObject.registerClass({
columnLimit: null,
minRows: 1,
minColumns: 1,
fillParent: false,
xAlign: St.Align.MIDDLE,
padWithSpacing: false });
this._rowLimit = params.rowLimit;
@ -233,6 +231,7 @@ 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;
@ -240,12 +239,6 @@ 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 = [];
@ -301,6 +294,11 @@ 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)
@ -319,23 +317,52 @@ var IconGrid = GObject.registerClass({
return this.get_children().filter(actor => actor.visible);
}
_availableHeightPerPageForItems() {
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
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);
}
vfunc_get_preferred_height() {
const height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
vfunc_allocate(box) {
if (this._childrenPerPage === 0)
log('computePages() must be called before allocate(); pagination will not work.');
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
this.set_allocation(box);
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);
}
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);
@ -351,27 +378,34 @@ 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 (animateIconPosition(children[i], childBox, nChangedIcons))
nChangedIcons++;
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
children[i].opacity = 0;
} else {
if (!animating)
children[i].opacity = 255;
children[i].show();
if (animateIconPosition(children[i], childBox, flags, nChangedIcons))
nChangedIcons++;
}
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;
@ -423,11 +457,7 @@ var IconGrid = GObject.registerClass({
* set of items to be animated.
*/
_getChildrenToAnimate() {
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);
return this._getVisibleChildren().filter(child => child.opacity > 0);
}
_resetAnimationActors() {
@ -703,6 +733,16 @@ 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');
@ -718,6 +758,14 @@ 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;
}
@ -767,24 +815,6 @@ 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
@ -810,7 +840,6 @@ 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
@ -823,6 +852,116 @@ 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) {
vfunc_allocate(box, flags) {
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);
super.vfunc_allocate(box, flags);
}
});
@ -722,7 +722,7 @@ var EmojiPager = GObject.registerClass({
_onPan(action) {
let [dist_, dx, dy_] = action.get_motion_delta(0);
this.delta += dx;
this.delta = this.delta + dx;
if (this._currentKey != null) {
this._currentKey.cancel();
@ -935,7 +935,8 @@ 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);
@ -1118,7 +1119,7 @@ var KeyboardManager = class KeyBoardManager {
this._seat.connect('notify::touch-mode', this._syncEnabled.bind(this));
this._lastDevice = null;
global.backend.connect('last-device-changed', (backend, device) => {
Meta.get_backend().connect('last-device-changed', (backend, device) => {
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE)
return;

View File

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

View File

@ -27,11 +27,13 @@ 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,9 +37,10 @@ const LG_ANIMATION_TIME = 500;
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of globalThis (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(globalThis).filter(
a => a.charAt(0) !== '_');
// Don't add the private properties of window (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(window).filter(
a => a.charAt(0) != '_'
);
const headerProperties = JsParse.getDeclaredConstants(commandHeader);
return keywords.concat(windowProperties).concat(headerProperties);
@ -554,8 +555,8 @@ var Inspector = GObject.registerClass({
this._lookingGlass = lookingGlass;
}
vfunc_allocate(box) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
if (!this._eventHandler)
return;
@ -570,7 +571,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);
this._eventHandler.allocate(childBox, flags);
}
_close() {
@ -802,191 +803,6 @@ 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() {
@ -1018,9 +834,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('notify::allocation',
Main.layoutManager.panelBox.connect('allocation-changed',
this._queueResize.bind(this));
Main.layoutManager.keyboardBox.connect('notify::allocation',
Main.layoutManager.keyboardBox.connect('allocation-changed',
this._queueResize.bind(this));
this._objInspector = new ObjInspector(this);
@ -1102,9 +918,6 @@ 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,7 +643,8 @@ 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)
);
}
}
@ -651,7 +652,8 @@ 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)
);
}
}
@ -659,7 +661,8 @@ 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)
);
}
}
@ -667,7 +670,8 @@ 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)
);
}
}
@ -675,7 +679,8 @@ 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)
);
}
}
@ -683,7 +688,8 @@ 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)
);
}
}
@ -1935,8 +1941,9 @@ 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
);
}
/**
@ -1963,7 +1970,8 @@ 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,7 +46,6 @@ 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';
@ -97,8 +96,6 @@ 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();
@ -123,23 +120,12 @@ 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 = globalThis.log;
global.log = globalThis.log;
global.logError = window.log;
global.log = window.log;
// Chain up async errors reported from C
global.connect('notify-error', (global, msg, detail) => {
@ -154,10 +140,6 @@ 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();
@ -817,7 +799,7 @@ function showRestartMessage(message) {
var AnimationsSettings = class {
constructor() {
let backend = global.backend;
let backend = Meta.get_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) {
vfunc_allocate(container, box, flags) {
for (let i = 0; i < container.get_n_children(); i++) {
let child = container.get_child_at_index(i);
if (child.visible)
child.allocate(box);
child.allocate(box, flags);
}
}

View File

@ -686,8 +686,8 @@ class SourceActorWithLabel extends SourceActor {
});
}
vfunc_allocate(box) {
super.vfunc_allocate(box);
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
let childBox = new Clutter.ActorBox();
@ -707,7 +707,7 @@ class SourceActorWithLabel extends SourceActor {
childBox.y1 = box.y2 - naturalHeight;
childBox.y2 = box.y2;
this._counterBin.allocate(childBox);
this._counterBin.allocate(childBox, flags);
}
_updateCount() {
@ -1164,7 +1164,8 @@ 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

@ -400,7 +400,8 @@ 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) {
vfunc_allocate(container, box, flags) {
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);
child.allocate(actorBox, flags);
}
// eslint-disable-next-line camelcase
@ -394,10 +394,10 @@ class DashSpacer extends St.Widget {
});
var ControlsLayout = GObject.registerClass({
Signals: { 'allocation-changed': {} },
Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
}, class ControlsLayout extends Clutter.BinLayout {
vfunc_allocate(container, box) {
super.vfunc_allocate(container, box);
vfunc_allocate(container, box, flags) {
super.vfunc_allocate(container, box, flags);
this.emit('allocation-changed');
}
});

View File

@ -436,11 +436,11 @@ var PadDiagram = GObject.registerClass({
childBox.y1 = y - natHeight / 2;
childBox.y2 = y + natHeight / 2;
child.allocate(childBox);
child.allocate(childBox, 0);
}
vfunc_allocate(box) {
super.vfunc_allocate(box);
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
if (this._handle === null)
return;

View File

@ -90,16 +90,18 @@ class AppMenu extends PopupMenu.PopupMenu {
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._detailsItem = this.addAction(_('Show Details'), async () => {
this._detailsItem = this.addAction(_("Show Details"), () => {
let id = this._app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
bus.call(
'org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
new GLib.Variant('(sava{sv})', ['details', [args], null]),
null, 0, -1, null);
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
});
});
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@ -284,7 +286,7 @@ var AppMenuButton = GObject.registerClass({
this.remove_all_transitions();
this.ease({
opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.Animation.EASE_OUT_QUAD,
duration: Overview.ANIMATION_TIME,
onComplete: () => this.hide(),
});
@ -842,8 +844,8 @@ class Panel extends St.Widget {
return [0, 0];
}
vfunc_allocate(box) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
@ -879,13 +881,13 @@ class Panel extends St.Widget {
childBox.x2 = Math.min(Math.floor(sideWidth),
leftNaturalWidth);
}
this._leftBox.allocate(childBox);
this._leftBox.allocate(childBox, flags);
childBox.x1 = Math.ceil(sideWidth);
childBox.y1 = 0;
childBox.x2 = childBox.x1 + centerWidth;
childBox.y2 = allocHeight;
this._centerBox.allocate(childBox);
this._centerBox.allocate(childBox, flags);
childBox.y1 = 0;
childBox.y2 = allocHeight;
@ -899,7 +901,7 @@ class Panel extends St.Widget {
0);
childBox.x2 = allocWidth;
}
this._rightBox.allocate(childBox);
this._rightBox.allocate(childBox, flags);
let cornerWidth, cornerHeight;
@ -909,7 +911,7 @@ class Panel extends St.Widget {
childBox.x2 = cornerWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._leftCorner.allocate(childBox);
this._leftCorner.allocate(childBox, flags);
[, cornerWidth] = this._rightCorner.get_preferred_width(-1);
[, cornerHeight] = this._rightCorner.get_preferred_height(-1);
@ -917,7 +919,7 @@ class Panel extends St.Widget {
childBox.x2 = allocWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._rightCorner.allocate(childBox);
this._rightCorner.allocate(childBox, flags);
}
_tryDragWindow(event) {
@ -1156,9 +1158,10 @@ class Panel extends St.Widget {
_getDraggableWindowForPosition(stageX) {
let workspaceManager = global.workspace_manager;
const windows = workspaceManager.get_active_workspace().list_windows();
const allWindowsByStacking =
global.display.sort_windows_by_stacking(windows).reverse();
let workspace = workspaceManager.get_active_workspace();
let allWindowsByStacking = global.display.sort_windows_by_stacking(
workspace.list_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) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
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);
child.allocate(childBox, flags);
}
_onDestroy() {

View File

@ -204,7 +204,7 @@ var RemoteSearchProvider = class {
g_interface_info: proxyInfo,
g_interface_name: proxyInfo.name,
gFlags });
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null);
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
this.appInfo = appInfo;
this.id = appInfo.get_id();

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 && Main.sessionMode.unlockDialog;
!this._isActive && lockEnabled && !lockLocked;
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) {
// Animate the lock screen out of screen
// Tween 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,8 +561,7 @@ var ScreenShield = class {
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
if (!this._ensureUnlockDialog(true))
return;
this._ensureUnlockDialog(true);
this.actor.show();

View File

@ -1,19 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ScreenshotService */
const { Clutter, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
Gio._promisify(Shell.Screenshot.prototype, 'pick_color', 'pick_color_finish');
Gio._promisify(Shell.Screenshot.prototype, 'screenshot', 'screenshot_finish');
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_window', 'screenshot_window_finish');
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_area', 'screenshot_area_finish');
const { loadInterfaceXML } = imports.misc.fileUtils;
const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
@ -165,7 +158,7 @@ var ScreenshotService = class {
return [x, y, width, height];
}
async ScreenshotAreaAsync(params, invocation) {
ScreenshotAreaAsync(params, invocation) {
let [x, y, width, height, flash, filename] = params;
[x, y, width, height] = this._scaleArea(x, y, width, height);
if (!this._checkArea(x, y, width, height)) {
@ -182,17 +175,21 @@ var ScreenshotService = class {
if (!stream)
return;
try {
let [area] =
await screenshot.screenshot_area(x, y, width, height, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
screenshot.screenshot_area(x, y, width, height, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async ScreenshotWindowAsync(params, invocation) {
ScreenshotWindowAsync(params, invocation) {
let [includeFrame, includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
@ -202,17 +199,21 @@ var ScreenshotService = class {
if (!stream)
return;
try {
let [area] =
await screenshot.screenshot_window(includeFrame, includeCursor, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
screenshot.screenshot_window(includeFrame, includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async ScreenshotAsync(params, invocation) {
ScreenshotAsync(params, invocation) {
let [includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
@ -222,13 +223,18 @@ var ScreenshotService = class {
if (!stream)
return;
try {
let [area] = await screenshot.screenshot(includeCursor, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
screenshot.screenshot(includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async SelectAreaAsync(params, invocation) {
@ -261,22 +267,27 @@ var ScreenshotService = class {
}
async PickColorAsync(params, invocation) {
const screenshot = this._createScreenshot(invocation, false);
if (!screenshot)
return;
const pickPixel = new PickPixel(screenshot);
let pickPixel = new PickPixel();
try {
const color = await pickPixel.pickAsync();
const { red, green, blue } = color;
const retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
blue / 255.0,
]),
}]);
invocation.return_value(retval);
const coords = await pickPixel.pickAsync();
let screenshot = this._createScreenshot(invocation, false);
if (!screenshot)
return;
screenshot.pick_color(coords.x, coords.y, (_o, res) => {
let [success_, color] = screenshot.pick_color_finish(res);
let { red, green, blue } = color;
let retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
blue / 255.0,
]),
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
});
} catch (e) {
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
@ -380,145 +391,12 @@ 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(screenshot) {
_init() {
super._init({ visible: false, reactive: true });
this._screenshot = screenshot;
this._result = null;
this._color = null;
this._inPick = false;
Main.uiGroup.add_actor(this);
@ -527,44 +405,16 @@ 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.BLANK);
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
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();
@ -574,25 +424,10 @@ class PickPixel extends St.Widget {
return this._result;
}
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);
vfunc_button_release_event(buttonEvent) {
let { x, y } = buttonEvent;
this._result = new Graphene.Point({ x, y });
this._grabHelper.ungrab();
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) {
vfunc_allocate(box, flags) {
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);
super.vfunc_allocate(adjustedBox, flags);
}
});
@ -219,7 +219,8 @@ 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);
@ -348,140 +349,18 @@ 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 St.Widget({ style_class: 'grid-search-results' });
this._grid.layout_manager = new GridSearchResultsLayout();
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._grid.connect('style-changed', () => {
const node = this._grid.get_theme_node();
this._grid.layout_manager.spacing = node.get_length('spacing');
});
this._bin = new St.Bin({ x_align: Clutter.ActorAlign.CENTER });
this._bin.set_child(this._grid);
this._resultDisplayBin.set_child(new St.Bin({
child: this._grid,
x_align: Clutter.ActorAlign.CENTER,
}));
this._resultDisplayBin.set_child(this._bin);
}
_onDestroy() {
@ -521,11 +400,12 @@ class GridSearchResults extends SearchResultsBase {
if (width == 0)
return -1;
return this._grid.layout_manager.columnsForWidth(width);
let nCols = this._grid.columnsForWidth(width);
return nCols * this._grid.getRowLimit();
}
_clearResultDisplay() {
this._grid.remove_all_children();
this._grid.removeAll();
}
_createResultDisplay(meta) {
@ -534,15 +414,14 @@ class GridSearchResults extends SearchResultsBase {
}
_addItem(display) {
this._grid.add_child(display);
this._grid.addItem(display);
}
getFirstResult() {
for (let child of this._grid) {
if (child.visible)
return child;
}
return null;
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0);
else
return null;
}
});
@ -552,9 +431,6 @@ 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,
@ -629,11 +505,6 @@ 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,7 +464,8 @@ 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, GLib, GnomeBluetooth, GObject } = imports.gi;
const { Gio, 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._queueSync.bind(this));
this._proxy.connect('g-properties-changed', this._sync.bind(this));
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
this._item.icon.icon_name = 'bluetooth-active-symbolic';
@ -49,27 +49,15 @@ 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-deleted', this._queueSync.bind(this));
this._model.connect('row-changed', this._queueSync.bind(this));
this._model.connect('row-changed', this._sync.bind(this));
this._model.connect('row-deleted', this._sync.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) {
@ -84,53 +72,46 @@ class Indicator extends PanelMenu.SystemIndicator {
return null;
}
_getDeviceInfos(adapter) {
// nDevices is the number of devices setup for the current default
// adapter if one exists and is powered. If unpowered or unavailable,
// nDevice is "1" if it had setup devices associated to it the last
// time it was seen, and "-1" if not.
//
// nConnectedDevices is the number of devices connected to the default
// adapter if one exists and is powered, or -1 if it's not available.
_getNDevices() {
let adapter = this._getDefaultAdapter();
if (!adapter)
return [];
return [this._hadSetupDevices ? 1 : -1, -1];
let deviceInfos = [];
let nConnectedDevices = 0;
let nDevices = 0;
let [ret, iter] = this._model.iter_children(adapter);
while (ret) {
const isPaired = this._model.get_value(iter,
GnomeBluetooth.Column.PAIRED);
const isTrusted = this._model.get_value(iter,
GnomeBluetooth.Column.TRUSTED);
if (isPaired || isTrusted) {
deviceInfos.push({
connected: this._model.get_value(iter,
GnomeBluetooth.Column.CONNECTED),
name: this._model.get_value(iter,
GnomeBluetooth.Column.ALIAS),
});
}
let isConnected = this._model.get_value(iter,
GnomeBluetooth.Column.CONNECTED);
if (isConnected)
nConnectedDevices++;
let isPaired = this._model.get_value(iter,
GnomeBluetooth.Column.PAIRED);
let isTrusted = this._model.get_value(iter,
GnomeBluetooth.Column.TRUSTED);
if (isPaired || isTrusted)
nDevices++;
ret = this._model.iter_next(iter);
}
return deviceInfos;
}
if (this._hadSetupDevices != (nDevices > 0)) {
this._hadSetupDevices = !this._hadSetupDevices;
global.settings.set_boolean(HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
}
_queueSync() {
if (this._syncId)
return;
this._syncId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._syncId = 0;
this._sync();
return GLib.SOURCE_REMOVE;
});
return [nDevices, nConnectedDevices];
}
_sync() {
let adapter = this._getDefaultAdapter();
let devices = this._getDeviceInfos(adapter);
const connectedDevices = devices.filter(dev => dev.connected);
const nConnectedDevices = connectedDevices.length;
if (adapter && this._adapter)
this._setHadSetupDevices(devices.length > 0);
this._adapter = adapter;
let [nDevices, nConnectedDevices] = this._getNDevices();
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
this.menu.setSensitive(sensitive);
@ -138,21 +119,19 @@ 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 (this._hadSetupDevices)
if (nDevices > 0)
this._item.visible = !this._proxy.BluetoothHardwareAirplaneMode;
else
this._item.visible = this._proxy.BluetoothHasAirplaneMode && !this._proxy.BluetoothAirplaneMode;
if (nConnectedDevices > 1)
if (nConnectedDevices > 0)
/* Translators: this is the number of connected bluetooth devices */
this._item.label.text = ngettext('%d Connected", "%d Connected', nConnectedDevices).format(nConnectedDevices);
else if (nConnectedDevices === 1)
this._item.label.text = connectedDevices[0].name;
else if (adapter === null)
this._item.label.text = _('Bluetooth Off');
this._item.label.text = ngettext("%d Connected", "%d Connected", nConnectedDevices).format(nConnectedDevices);
else if (nConnectedDevices == -1)
this._item.label.text = _("Off");
else
this._item.label.text = _('Bluetooth On');
this._item.label.text = _("On");
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _('Turn On') : _('Turn Off');
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off");
}
});

View File

@ -48,9 +48,7 @@ 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

@ -199,36 +199,36 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
this._reload.bind(this));
}
async _reload() {
let props;
try {
const result = await Gio.DBus.system.call(
this._BUS_NAME,
this._BUS_PATH,
this._BUS_PROPS_IFACE,
'GetAll',
new GLib.Variant('(s)', [this._BUS_IFACE]),
null, Gio.DBusCallFlags.NONE, -1, null);
[props] = result.deep_unpack();
} catch (e) {
log('Could not get properties from %s'.format(this._BUS_NAME));
return;
}
_reload() {
Gio.DBus.system.call(this._BUS_NAME,
this._BUS_PATH,
this._BUS_PROPS_IFACE,
'GetAll',
new GLib.Variant('(s)', [this._BUS_IFACE]),
null, Gio.DBusCallFlags.NONE, -1, null,
(conn, result) => {
let props;
try {
props = conn.call_finish(result).deep_unpack()[0];
} catch (e) {
log('Could not get properties from %s'.format(this._BUS_NAME));
return;
}
let layouts = props['X11Layout'].unpack();
let variants = props['X11Variant'].unpack();
let options = props['X11Options'].unpack();
const layouts = props['X11Layout'].unpack();
const variants = props['X11Variant'].unpack();
const options = props['X11Options'].unpack();
if (layouts !== this._layouts ||
variants !== this._variants) {
this._layouts = layouts;
this._variants = variants;
this._emitInputSourcesChanged();
}
if (options !== this._options) {
this._options = options;
this._emitKeyboardOptionsChanged();
}
if (layouts != this._layouts ||
variants != this._variants) {
this._layouts = layouts;
this._variants = variants;
this._emitInputSourcesChanged();
}
if (options != this._options) {
this._options = options;
this._emitKeyboardOptionsChanged();
}
});
}
get inputSources() {
@ -805,8 +805,8 @@ class InputSourceIndicatorContainer extends St.Widget {
}, [0, 0]);
}
vfunc_allocate(box) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
// 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);
c.allocate_align_fill(box, 0.5, 0.5, false, false, flags);
});
}
});

View File

@ -15,10 +15,6 @@ const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(NM.Client, 'new_async', 'new_finish');
Gio._promisify(NM.Client.prototype,
'check_connectivity_async', 'check_connectivity_finish');
const NMConnectionCategory = {
INVALID: 'invalid',
WIRED: 'wired',
@ -716,7 +712,8 @@ 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));
@ -1630,11 +1627,11 @@ class Indicator extends PanelMenu.SystemIndicator {
this._ctypes[NM.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NM.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
this._getClient();
NM.Client.new_async(null, this._clientGot.bind(this));
}
async _getClient() {
this._client = await NM.Client.new_async(null);
_clientGot(obj, result) {
this._client = NM.Client.new_finish(result);
this._activeConnections = [];
this._connections = [];
@ -1862,7 +1859,8 @@ 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);
});
@ -1984,7 +1982,7 @@ class Indicator extends PanelMenu.SystemIndicator {
}
}
async _portalHelperDone(proxy, emitter, parameters) {
_portalHelperDone(proxy, emitter, parameters) {
let [path, result] = parameters;
if (result == PortalHelperResult.CANCELLED) {
@ -1995,11 +1993,13 @@ class Indicator extends PanelMenu.SystemIndicator {
} else if (result == PortalHelperResult.COMPLETED) {
this._closeConnectivityCheck(path);
} else if (result == PortalHelperResult.RECHECK) {
try {
const state = await this._client.check_connectivity_async(null);
if (state >= NM.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch (e) { }
this._client.check_connectivity_async(null, (client, res) => {
try {
let state = client.check_connectivity_finish(res);
if (state >= NM.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch (e) { }
});
} else {
log('Invalid result from portal helper: %s'.format(result));
}

View File

@ -139,7 +139,7 @@ class Indicator extends PanelMenu.SystemIndicator {
label = _("%d\u2009%%").format(100);
else
label = _("%d\u2009%%").format(this._proxy.Percentage);
this._percentageLabel.text = label;
this._percentageLabel.clutter_text.set_markup('<span size="smaller">' + label + '</span>');
// The status label
this._item.label.text = this._getStatus();

View File

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

View File

@ -82,7 +82,8 @@ 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

@ -52,21 +52,22 @@ const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
var Client = class {
constructor() {
this._proxy = null;
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
Gio.DBusProxy.new(Gio.DBus.system,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
BOLT_DBUS_CLIENT_IFACE,
null,
this._onProxyReady.bind(this));
this.probing = false;
this._getProxy();
}
async _getProxy() {
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
_onProxyReady(o, res) {
try {
this._proxy = await Gio.DBusProxy.new(
Gio.DBus.system,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
BOLT_DBUS_CLIENT_IFACE,
null);
this._proxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log('error creating bolt proxy: %s'.format(e.message));
return;
@ -242,15 +243,14 @@ class Indicator extends PanelMenu.SystemIndicator {
this._source = null;
this._perm = null;
this._createPermission();
}
async _createPermission() {
try {
this._perm = await Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null);
} catch (e) {
log('Failed to get PolKit permission: %s'.format(e.toString()));
}
Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null, (source, res) => {
try {
this._perm = Polkit.Permission.new_finish(res);
} catch (e) {
log('Failed to get PolKit permission: %s'.format(e.toString()));
}
});
}
_onDestroy() {

View File

@ -56,9 +56,6 @@ 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) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
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);
this._switcherList.allocate(childBox, flags);
}
_initialSelection(backward, _binding) {
@ -317,7 +317,7 @@ var SwitcherPopup = GObject.registerClass({
this.ease({
opacity: 0,
duration: POPUP_FADE_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.Animation.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) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
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);
this._scrollView.allocate(contentBox, flags);
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);
this._leftArrow.allocate(childBox, flags);
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);
this._rightArrow.allocate(childBox, flags);
this._rightArrow.opacity = this._scrollableRight && scrollable ? 255 : 0;
}
});

228
js/ui/tweener.js Normal file
View File

@ -0,0 +1,228 @@
// -*- 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) {
vfunc_allocate(container, box, flags) {
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);
this._notifications.allocate(actorBox, flags);
// 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);
this._stack.allocate(actorBox, flags);
// 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);
this._switchUserButton.allocate(actorBox, flags);
}
}
});

View File

@ -144,8 +144,8 @@ class UserWidgetLabel extends St.Widget {
}
}
vfunc_allocate(box) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
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);
this._currentLabel.allocate(childBox, flags);
}
vfunc_paint(paintContext) {

View File

@ -51,22 +51,35 @@ 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 [0, this._boundingBox.height];
return [this._boundingBox.height, this._boundingBox.height];
}
vfunc_get_preferred_width(_container, _forHeight) {
return [0, this._boundingBox.width];
return [this._boundingBox.width, this._boundingBox.width];
}
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();
vfunc_allocate(container, box, flags) {
container.get_children().forEach(child => {
let realWindow;
if (child == container._windowClone)
@ -74,20 +87,8 @@ class WindowCloneLayout extends Clutter.LayoutManager {
else
realWindow = child.source;
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);
child.allocate(this._makeBoxForWindow(realWindow.meta_window),
flags);
});
}
});
@ -154,8 +155,7 @@ var WindowClone = GObject.registerClass({
this._updateAttachedDialogs();
this._computeBoundingBox();
this.x = this._boundingBox.x;
this.y = this._boundingBox.y;
this.set_translation(this._boundingBox.x, this._boundingBox.y, 0);
this._computeWindowCenter();
@ -240,9 +240,6 @@ var WindowClone = GObject.registerClass({
this._onMetaWindowSizeChanged();
});
Shell.util_set_hidden_from_pick(clone, true);
this.add_child(clone);
}
@ -266,6 +263,18 @@ 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();
@ -859,7 +868,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.boundingBox.height / this._monitor.height;
let ratio = window.height / this._monitor.height;
// The purpose of this manipulation here is to prevent windows
// from getting too small. For something like a calculator window,
@ -979,12 +988,11 @@ var LayoutStrategy = class {
let window = row.windows[j];
let s = scale * this._computeWindowScale(window) * row.additionalScale;
let cellWidth = window.boundingBox.width * s;
let cellHeight = window.boundingBox.height * s;
let cellWidth = window.width * s;
let cellHeight = window.height * s;
s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE);
let cloneWidth = window.boundingBox.width * s;
const cloneHeight = window.boundingBox.height * s;
let cloneWidth = window.width * s;
let cloneX = x + (cellWidth - cloneWidth) / 2;
let cloneY = row.y + row.height * row.additionalScale - cellHeight + compensation;
@ -993,7 +1001,7 @@ var LayoutStrategy = class {
cloneX = Math.floor(cloneX);
cloneY = Math.floor(cloneY);
slots.push([cloneX, cloneY, cloneWidth, cloneHeight, window]);
slots.push([cloneX, cloneY, s, window]);
x += cellWidth + this._columnSpacing;
}
}
@ -1038,7 +1046,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.boundingBox.width * s;
totalWidth += window.width * s;
}
let idealRowWidth = totalWidth / numRows;
@ -1056,8 +1064,8 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
for (; windowIdx < sortedWindows.length; windowIdx++) {
let window = sortedWindows[windowIdx];
let s = this._computeWindowScale(window);
let width = window.boundingBox.width * s;
let height = window.boundingBox.height * s;
let width = window.width * s;
let height = window.height * s;
row.fullHeight = Math.max(row.fullHeight, height);
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
@ -1332,7 +1340,7 @@ class Workspace extends St.Widget {
for (let i = 0; i < slots.length; i++) {
let slot = slots[i];
const [x, y, cellWidth, cellHeight, clone] = slot;
let [x, y, scale, clone] = slot;
clone.slotId = i;
@ -1341,8 +1349,8 @@ class Workspace extends St.Widget {
if (clone.inDrag)
continue;
const cloneWidth = cellWidth;
const cloneHeight = cellHeight;
let cloneWidth = clone.width * scale;
let cloneHeight = clone.height * scale;
clone.slot = [x, y, cloneWidth, cloneHeight];
let cloneCenter = x + cloneWidth / 2;
@ -1357,10 +1365,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.x = x + cloneWidth / 2;
clone.y = y + cloneHeight / 2;
clone.width = 0;
clone.height = 0;
clone.translation_x = x + cloneWidth / 2;
clone.translation_y = y + cloneHeight / 2;
clone.scale_x = 0;
clone.scale_y = 0;
clone.positioned = true;
}
@ -1371,10 +1379,10 @@ class Workspace extends St.Widget {
* can be scaled up later */
if (initialPositioning) {
clone.opacity = 0;
clone.x = x;
clone.y = y;
clone.width = cloneWidth;
clone.height = cloneHeight;
clone.scale_x = 0;
clone.scale_y = 0;
clone.translation_x = x;
clone.translation_y = y;
}
clone.ease({
@ -1384,12 +1392,12 @@ class Workspace extends St.Widget {
});
}
this._animateClone(clone, clone.overlay, x, y, cloneWidth, cloneHeight);
this._animateClone(clone, clone.overlay, x, y, scale);
} else {
// cancel any active tweens (otherwise they might override our changes)
clone.remove_all_transitions();
clone.set_position(x, y);
clone.set_size(cloneWidth, cloneHeight);
clone.set_translation(x, y, 0);
clone.set_scale(scale, scale);
clone.set_opacity(255);
clone.overlay.relayout(false);
this._showWindowOverlay(clone, clone.overlay);
@ -1416,10 +1424,12 @@ class Workspace extends St.Widget {
}
}
_animateClone(clone, overlay, x, y, width, height) {
_animateClone(clone, overlay, x, y, scale) {
clone.ease({
x, y,
width, height,
translation_x: x,
translation_y: y,
scale_x: scale,
scale_y: scale,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
@ -1476,14 +1486,11 @@ class Workspace extends St.Widget {
// this point.)
if (win) {
let [stageX, stageY] = clone.get_transformed_position();
const [transformedWidth, transformedHeight] =
clone.get_transformed_size();
let [stageWidth] = clone.get_transformed_size();
win._overviewHint = {
x: stageX,
y: stageY,
width: transformedWidth,
height: transformedHeight,
scale: stageWidth / clone.width,
};
}
clone.destroy();
@ -1559,15 +1566,14 @@ class Workspace extends St.Widget {
if (win._overviewHint) {
let x = win._overviewHint.x - this.x;
let y = win._overviewHint.y - this.y;
const width = win._overviewHint.width;
const height = win._overviewHint.height;
let scale = win._overviewHint.scale;
delete win._overviewHint;
clone.slot = [x, y, width, height];
clone.slot = [x, y, clone.width * scale, clone.height * scale];
clone.positioned = true;
clone.set_position(x, y);
clone.set_size(width, height);
clone.set_translation(x, y, 0);
clone.set_scale(scale, scale);
clone.overlay.relayout(false);
}
@ -1718,10 +1724,11 @@ class Workspace extends St.Widget {
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
clone.x = clone.boundingBox.x;
clone.y = clone.boundingBox.y;
clone.width = clone.boundingBox.width;
clone.height = clone.boundingBox.height;
let [origX, origY] = clone.getOriginalPosition();
clone.scale_x = 1;
clone.scale_y = 1;
clone.translation_x = origX;
clone.translation_y = origY;
clone.ease({
opacity,
duration,
@ -1769,11 +1776,12 @@ class Workspace extends St.Widget {
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
clone.ease({
x: clone.boundingBox.x,
y: clone.boundingBox.y,
width: clone.boundingBox.width,
height: clone.boundingBox.height,
translation_x: origX,
translation_y: origY,
scale_x: 1,
scale_y: 1,
opacity: 255,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -1781,8 +1789,8 @@ class Workspace extends St.Widget {
} else {
// The window is hidden, make it shrink and fade it out
clone.ease({
width: 0,
height: 0,
scale_x: 0,
scale_y: 0,
opacity: 0,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -2027,8 +2035,7 @@ class Workspace extends St.Widget {
win._overviewHint = {
x: actor.x,
y: actor.y,
width: actor.width,
heigth: actor.height,
scale: actor.scale_x,
};
let metaWindow = win.get_meta_window();

View File

@ -86,8 +86,8 @@ class WorkspaceSwitcherPopupList extends St.Widget {
return this._getSizeForOppositeOrientation();
}
vfunc_allocate(box) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
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);
child.allocate(childBox, flags);
}
}
});

View File

@ -1204,8 +1204,8 @@ var ThumbnailsBox = GObject.registerClass({
this.queue_relayout();
}
vfunc_allocate(box) {
this.set_allocation(box);
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
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);
this._dropPlaceholder.allocate(childBox, flags);
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);
thumbnail.allocate(childBox, flags);
// 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);
this._indicator.allocate(childBox, flags);
}
});

View File

@ -820,7 +820,8 @@ class WorkspacesDisplay extends St.Widget {
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 } = imports.gi;
const { Clutter, Meta } = 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 = global.backend.get_dnd();
var dnd = Meta.get_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.2',
meson_version: '>= 0.53.0',
version: '3.36.3',
meson_version: '>= 0.47.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.33.1'
eds_req = '>= 3.17.2'
gcr_req = '>= 3.7.5'
gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1'
gjs_req = '>= 1.65.1'
gjs_req = '>= 1.63.2'
gtk_req = '>= 3.15.0'
mutter_req = '>= 3.37.2'
mutter_req = '>= 3.36.0'
polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1'
startup_req = '>= 0.11'
@ -63,9 +63,16 @@ 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', define_variable: ['datadir', datadir])
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir')
else
keysdir = join_paths(datadir, 'gnome-control-center', 'keybindings')
endif
@ -115,9 +122,8 @@ endif
if get_option('systemd')
libsystemd_dep = dependency('libsystemd')
systemd_dep = dependency('systemd')
systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
define_variable: ['prefix', prefix])
# XXX: see systemduserunitdir
# systemd_dep = dependency('systemd')
have_systemd = true
else
libsystemd_dep = []
@ -315,6 +321,8 @@ if get_option('man')
summary_dirs += { 'mandir': get_option('mandir') }
endif
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
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

View File

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

View File

@ -94,7 +94,5 @@ 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

View File

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

1313
po/ca.po

File diff suppressed because it is too large Load Diff

558
po/cs.po

File diff suppressed because it is too large Load Diff

1262
po/eo.po

File diff suppressed because it is too large Load Diff

595
po/es.po

File diff suppressed because it is too large Load Diff

790
po/eu.po

File diff suppressed because it is too large Load Diff

708
po/fa.po

File diff suppressed because it is too large Load Diff

605
po/fur.po

File diff suppressed because it is too large Load Diff

590
po/ja.po

File diff suppressed because it is too large Load Diff

187
po/lt.po
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-03-28 16:33+0000\n"
"PO-Revision-Date: 2020-03-29 22:27+0300\n"
"POT-Creation-Date: 2020-05-26 21:26+0000\n"
"PO-Revision-Date: 2020-05-31 22:49+0300\n"
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
@ -20,7 +20,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
"%100<10 || n%100>=20) ? 1 : 2)\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
@ -389,7 +389,7 @@ msgid "Network Login"
msgstr "Tinklo prisijungimas"
#: 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 "Atsitiko kažkas negero"
@ -416,7 +416,7 @@ msgstr "Aplankyti plėtinio namų tinklalapį"
#: 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"
@ -472,71 +472,71 @@ msgid "(or swipe finger)"
msgstr "(arba perbraukite pirštu)"
#. 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 "Išjungti"
#. 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 "išjungti;perleisti;perkrauti;sustabdyti"
#. 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 "Užrakinti ekraną"
#. 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 "užrakinti ekraną"
#. 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 "Atsijungti"
#. 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 "atsijungti;išeiti;"
#. 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 "Pristabdyti"
#. 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 "pristabdyti;užmigdyti"
#. 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 "Keisti naudotoją"
#. 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 "keisti naudotoją"
#. 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 "orientacijos užrakinimas;orientacijos atrakinimas;ekranas;pasukimas"
#: js/misc/systemActions.js:251
#: js/misc/systemActions.js:255
msgctxt "search-result"
msgid "Unlock Screen Rotation"
msgstr "Atrakinti ekrano orientaciją"
#: js/misc/systemActions.js:252
#: js/misc/systemActions.js:256
msgctxt "search-result"
msgid "Lock Screen Rotation"
msgstr "Užrakinti ekrano orientaciją"
@ -707,53 +707,53 @@ msgstr "Atmesti prieigą"
msgid "Grant Access"
msgstr "Suteikti prieigą"
#: js/ui/appDisplay.js:898
#: js/ui/appDisplay.js:939
msgid "Unnamed Folder"
msgstr "Nepavadintas aplankas"
#: js/ui/appDisplay.js:921
#: js/ui/appDisplay.js:962
msgid "Frequently used applications will appear here"
msgstr "Čia bus matomos dažnai naudojamos programos"
#: js/ui/appDisplay.js:1056
#: js/ui/appDisplay.js:1097
msgid "Frequent"
msgstr "Dažnai naudojamos"
#: js/ui/appDisplay.js:1063
#: js/ui/appDisplay.js:1104
msgid "All"
msgstr "Visos"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2439 js/ui/panel.js:75
#: js/ui/appDisplay.js:2480 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Atverti langai"
#: js/ui/appDisplay.js:2459 js/ui/panel.js:82
#: js/ui/appDisplay.js:2500 js/ui/panel.js:82
msgid "New Window"
msgstr "Naujas langas"
#: js/ui/appDisplay.js:2470
#: js/ui/appDisplay.js:2511
msgid "Launch using Dedicated Graphics Card"
msgstr "Paleisti naudojant dedikuotą grafikos kortą"
#: js/ui/appDisplay.js:2498 js/ui/dash.js:239
#: js/ui/appDisplay.js:2539 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Pašalinti iš mėgstamų"
#: js/ui/appDisplay.js:2504
#: js/ui/appDisplay.js:2545
msgid "Add to Favorites"
msgstr "Pridėti prie mėgstamų"
#: js/ui/appDisplay.js:2514 js/ui/panel.js:93
#: js/ui/appDisplay.js:2555 js/ui/panel.js:93
msgid "Show Details"
msgstr "Rodyti detalią informaciją"
#: js/ui/appFavorites.js:152
#: js/ui/appFavorites.js:153
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s pridėta prie jūsų mėgstamų."
#: js/ui/appFavorites.js:185
#: js/ui/appFavorites.js:186
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s pašalinta iš jūsų mėgstamų."
@ -774,7 +774,7 @@ msgstr "Ausinės"
msgid "Headset"
msgstr "Ausinės su mikrofonu"
#: 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 "Mikrofonas"
@ -915,7 +915,7 @@ msgstr "Nėra įvykių"
msgid "Do Not Disturb"
msgstr "Netrukdyti"
#: js/ui/calendar.js:1171
#: js/ui/calendar.js:1176
msgid "Clear"
msgstr "Išvalyti"
@ -1100,46 +1100,46 @@ msgstr "%Y %B %-d."
msgid "%A %B %e %Y"
msgstr "%A, %Y m. %B %d d."
#: js/ui/dateMenu.js:161
#: js/ui/dateMenu.js:162
msgid "Add world clocks…"
msgstr "Pridėti pasaulio laikrodžius…"
#: js/ui/dateMenu.js:162
#: js/ui/dateMenu.js:163
msgid "World Clocks"
msgstr "Pasaulio laikrodžiai"
#: js/ui/dateMenu.js:289
#: js/ui/dateMenu.js:308
msgid "Weather"
msgstr "Orai"
#: js/ui/dateMenu.js:418
#: js/ui/dateMenu.js:437
msgid "Select a location…"
msgstr "Pasirinkite vietą…"
#: js/ui/dateMenu.js:426
#: js/ui/dateMenu.js:445
msgid "Loading…"
msgstr "Įkeliama…"
#: js/ui/dateMenu.js:436
#: js/ui/dateMenu.js:455
msgid "Go online for weather information"
msgstr "Prisijunkite prie tinklo orų informacijai gauti"
#: js/ui/dateMenu.js:438
#: js/ui/dateMenu.js:457
msgid "Weather information is currently unavailable"
msgstr "Orų informacija šiuo metu yra neprieinama"
#: js/ui/endSessionDialog.js:39
#: js/ui/endSessionDialog.js:37
#, javascript-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Atjungti naudotoją %s"
#: js/ui/endSessionDialog.js:40
#: js/ui/endSessionDialog.js:38
msgctxt "title"
msgid "Log Out"
msgstr "Atsijungti"
#: 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."
@ -1147,7 +1147,7 @@ msgstr[0] "%s bus automatiškai atjungta (-s) už %d sekundės."
msgstr[1] "%s bus automatiškai atjungta (-s) už %d sekundžių."
msgstr[2] "%s bus automatiškai atjungta (-s) už %d sekundžių."
#: 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."
@ -1155,22 +1155,22 @@ msgstr[0] "Jūs būsite automatiškai atjungti už %d sekundės."
msgstr[1] "Jūs būsite automatiškai atjungti už %d sekundžių."
msgstr[2] "Jūs būsite automatiškai atjungti už %d sekundžių."
#: js/ui/endSessionDialog.js:53
#: js/ui/endSessionDialog.js:51
msgctxt "button"
msgid "Log Out"
msgstr "Atsijungti"
#: js/ui/endSessionDialog.js:58
#: js/ui/endSessionDialog.js:56
msgctxt "title"
msgid "Power Off"
msgstr "Išjungti"
#: js/ui/endSessionDialog.js:59
#: js/ui/endSessionDialog.js:57
msgctxt "title"
msgid "Install Updates & Power Off"
msgstr "Įdiegti atnaujinimus ir išjungti"
#: 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."
@ -1178,27 +1178,27 @@ msgstr[0] "Sistema automatiškai išsijungs po %d sekundės."
msgstr[1] "Sistema automatiškai išsijungs po %d sekundžių."
msgstr[2] "Sistema automatiškai išsijungs po %d sekundžių."
#: js/ui/endSessionDialog.js:65
#: js/ui/endSessionDialog.js:63
msgctxt "checkbox"
msgid "Install pending software updates"
msgstr "Įdiegti programinės įrangos atnaujinimus"
#: 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 "Paleisti iš naujo"
#: js/ui/endSessionDialog.js:70
#: js/ui/endSessionDialog.js:68
msgctxt "button"
msgid "Power Off"
msgstr "Išjungti"
#: js/ui/endSessionDialog.js:76
#: js/ui/endSessionDialog.js:74
msgctxt "title"
msgid "Restart"
msgstr "Paleisti iš naujo"
#: 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."
@ -1206,12 +1206,12 @@ msgstr[0] "Sistema bus paleista iš naujo po %d sekundės."
msgstr[1] "Sistema bus paleista iš naujo po %d sekundžių."
msgstr[2] "Sistema bus paleista iš naujo po %d sekundžių."
#: js/ui/endSessionDialog.js:91
#: js/ui/endSessionDialog.js:89
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Perleisti ir įdiegti atnaujinimus"
#: 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 ""
@ -1223,22 +1223,22 @@ msgstr[1] ""
msgstr[2] ""
"Sistema bus paleista iš naujo ir įdiegs atnaujinimus po %d sekundžių."
#: 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 "Perleisti ir įdiegti"
#: js/ui/endSessionDialog.js:100
#: js/ui/endSessionDialog.js:98
msgctxt "button"
msgid "Install &amp; Power Off"
msgstr "Įdiegti ir išjungti"
#: js/ui/endSessionDialog.js:101
#: js/ui/endSessionDialog.js:99
msgctxt "checkbox"
msgid "Power off after updates are installed"
msgstr "Išjungti baigus diegti atnaujinimus"
#: js/ui/endSessionDialog.js:108
#: js/ui/endSessionDialog.js:106
msgctxt "title"
msgid "Restart & Install Upgrade"
msgstr "Perleisti ir įdiegti atnaujinimą"
@ -1246,7 +1246,7 @@ msgstr "Perleisti ir įdiegti atnaujinimą"
#. 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 "
@ -1256,28 +1256,28 @@ msgstr ""
"įsitikinkite, kad pasidarėte atsarginę duomenų kopiją, ir kad kompiuteris "
"yra įjungtas į elektros tinklą."
#: js/ui/endSessionDialog.js:261
#: js/ui/endSessionDialog.js:259
msgid "Running on battery power: Please plug in before installing updates."
msgstr ""
"Veikia naudojant baterijos energiją: įjunkite į elektros tinklą prieš "
"įdiegdami atnaujinimus."
#: js/ui/endSessionDialog.js:270
#: js/ui/endSessionDialog.js:268
msgid "Some applications are busy or have unsaved work"
msgstr "Kai kurios programos dirba arba turi neįrašyto darbo."
#: js/ui/endSessionDialog.js:275
#: js/ui/endSessionDialog.js:273
msgid "Other users are logged in"
msgstr "Yra prisijungusių kitų naudotojų"
#. 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 (nutolęs)"
#. 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 (komandų eilutė)"
@ -1295,11 +1295,11 @@ msgstr "Išdiegti plėtinį"
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Parsiųsti ir įdiegti „%s“ iš extensions.gnome.org?"
#: js/ui/extensionSystem.js:233
#: js/ui/extensionSystem.js:252
msgid "Extension Updates Available"
msgstr "Yra plėtinių atnaujinimų"
#: js/ui/extensionSystem.js:234
#: js/ui/extensionSystem.js:253
msgid "Extension updates are ready to be installed."
msgstr "Plėtinių atnaujinimai paruošti diegimui."
@ -1446,11 +1446,11 @@ msgstr "Žiūrėti šaltinį"
msgid "Web Page"
msgstr "Tinklalapis"
#: js/ui/main.js:277
#: js/ui/main.js:279
msgid "Logged in as a privileged user"
msgstr "Prisijungta privilegijuotu naudotoju"
#: 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."
@ -1458,23 +1458,23 @@ msgstr ""
"Saugumo sumetimais turėtų būti vengiama vykdyti seansus privilegijuotais "
"naudotojais. Jei įmanoma, turėtumėt visada prisjungti normaliu naudotoju."
#: js/ui/main.js:317
#: js/ui/main.js:319
msgid "Screen Lock disabled"
msgstr "Ekrano užraktas išjungtas"
#: js/ui/main.js:318
#: js/ui/main.js:320
msgid "Screen Locking requires the GNOME display manager."
msgstr "Ekrano užrakinimas reikalaujas GNOME vaizduoklio valdyklės."
#: js/ui/messageTray.js:1551
#: js/ui/messageTray.js:1548
msgid "System Information"
msgstr "Sistemos informacija"
#: js/ui/mpris.js:199
#: js/ui/mpris.js:204
msgid "Unknown artist"
msgstr "Nežinomas atlikėjas"
#: js/ui/mpris.js:209
#: js/ui/mpris.js:214
msgid "Unknown title"
msgstr "Nežinomas pavadinimas"
@ -1546,16 +1546,16 @@ msgstr "Užverti"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:434
#: js/ui/panel.js:437
msgid "Activities"
msgstr "Apžvalga"
#: js/ui/panel.js:713
#: js/ui/panel.js:716
msgctxt "System menu in the top bar"
msgid "System"
msgstr "Sistema"
#: js/ui/panel.js:826
#: js/ui/panel.js:829
msgid "Top Bar"
msgstr "Viršutinė juosta"
@ -1586,11 +1586,11 @@ msgstr "GNOME aplinkai reikia užrakinti ekraną"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: js/ui/screenShield.js:244 js/ui/screenShield.js:598
#: js/ui/screenShield.js:244 js/ui/screenShield.js:601
msgid "Unable to lock"
msgstr "Nepavyksta užrakinti"
#: 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 "Programa užblokavo užrakinimą"
@ -1674,13 +1674,13 @@ msgid "The PIM must be a number or empty."
msgstr "PIM turi būti numeris arba tuščias."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:469
#: js/ui/shellMountOperation.js:465
#, javascript-format
msgid "Unable to start %s"
msgstr "Nepavyksta paleisti %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 "Nepavyksta rasti programos %s"
@ -2156,11 +2156,11 @@ msgstr "Thunderbolt autorizacijos klaida"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Nepavyko autorizuoti Thunderbolt įrenginio: %s"
#: js/ui/status/volume.js:150
#: js/ui/status/volume.js:151
msgid "Volume changed"
msgstr "Garsumas pakeistas"
#: js/ui/status/volume.js:221
#: js/ui/status/volume.js:222
msgid "Volume"
msgstr "Garsumas"
@ -2243,7 +2243,7 @@ msgstr "Grąžinti nustatymus"
msgid "Keep Changes"
msgstr "Įrašyti pakeitimus"
#: 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"
@ -2253,7 +2253,7 @@ msgstr[2] "Pakeitimai bus grąžinti po %d sekundžių"
#. 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"
@ -2346,12 +2346,12 @@ msgstr "Naudoti konkrečią veikseną, pvz., „gdm“ prisijungimo ekranui"
msgid "List possible modes"
msgstr "Išvardinti galimas veiksenas"
#: src/shell-app.c:279
#: src/shell-app.c:286
msgctxt "program"
msgid "Unknown"
msgstr "Nežinoma"
#: src/shell-app.c:530
#: src/shell-app.c:537
#, c-format
msgid "Failed to launch “%s”"
msgstr "Nepavyko paleisti „%s“"
@ -2475,19 +2475,19 @@ msgstr ""
"Plėtiniai gali sukelti sistemai problemų, įskaitant našumo problemas. Jei su "
"tokiomis susidursite, rekomenduojama išjungti visus plėtinius."
#: subprojects/extensions-app/data/ui/extensions-window.ui:134
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
msgid "Manually Installed"
msgstr "Įdiegtas rankomis"
#: subprojects/extensions-app/data/ui/extensions-window.ui:158
#: subprojects/extensions-app/data/ui/extensions-window.ui:159
msgid "Built-In"
msgstr "Vidinis"
#: subprojects/extensions-app/data/ui/extensions-window.ui:199
#: subprojects/extensions-app/data/ui/extensions-window.ui:200
msgid "No Installed Extensions"
msgstr "Nėra įdiegtų plėtinių"
#: 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."
@ -2495,7 +2495,12 @@ msgstr ""
"Atsiprašome, bet nepavyko gauti įdiegtų plėtinių sąrašo. Įsitikinkite, kad "
"esate prisijungęs prie GNOME ir bandykite vėl."
#: subprojects/extensions-app/data/ui/extensions-window.ui:288
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
#| msgid "Extension Updates Available"
msgid "Extension Updates Ready"
msgstr "Plėtinių atnaujinimai paruošti"
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
msgid "Log Out…"
msgstr "Atsijungti…"

2803
po/os.po

File diff suppressed because it is too large Load Diff

727
po/ro.po

File diff suppressed because it is too large Load Diff

1937
po/sl.po

File diff suppressed because it is too large Load Diff

638
po/tr.po

File diff suppressed because it is too large Load Diff

641
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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