Compare commits

..

71 Commits

Author SHA1 Message Date
7031449f01 Bump version to 3.37.3
Update NEWS.
2020-07-07 19:01:21 +02:00
06df79286d windowPreview: Adapt to ClutterActor API changes
The API of clutter_actor_allocate_preferred_size() changed with
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1310, so adapt to
this change and pass the origin to the function.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1322
2020-07-07 16:51:33 +00:00
9297d87775 workspacesView: Do not animate primary view geometry when fading
When going straight to the app picker, we fade in the overview instead
of doing the full-blown zoom transition. In order to keep windows at
their floating position, we must apply the same to the view itself
and not transition to the overview geometry when fading.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1353
2020-07-07 13:41:54 +02:00
ef56b14553 workspacesView: Always sync geometry after showing overview
We don't always want to sync the geometry when entering the overview,
namely when the fade transition is used.

However we do want the correct geometry once we have entered the overview,
so that workspaces are at their place when switching from the app picker.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1353
2020-07-07 13:41:54 +02:00
30ff76272e workspacesView: Decouple syncing geometry from updating views
This gives us more control over when the geometry is synced. We
will soon use that to keep the primary view at the work area
geometry while fading to the overview.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1353
2020-07-07 13:41:54 +02:00
52a7481ba6 workspacesView: Only animate primary view
Non-primary views always use their monitor's work area for their
geometry, so there's nothing to animate when leaving the overview.

The animation is already limited to the primary view when entering
the overview, so this is also more consistent.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1353
2020-07-07 13:41:54 +02:00
14cfd74f08 workspace: Always start in FLOATING state
It doesn't matter which animation we use to enter the overview,
we always want to start and end with the floating layout.

The simplest way to achieve that is by creating the state adjustment
with the correct value in the first place.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1353
2020-07-07 13:41:54 +02:00
fa97f7141b workspace: Remove reserved slots
This is a pre-3.0 feature that was dropped before
the 3.0 release, but managed to find its way until
now, 11 years later.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1352
2020-07-07 12:26:59 +02:00
03bcd4c05b unlockDialog: Small cleanup
It's silly to initialize a variable to 0 right before setting it
to its actual value.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1352
2020-07-07 12:26:58 +02:00
89574abc83 windowPreview: Remove slotId property
We're no longer using that property, so clean up a bit and remove the
last occurences of it.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1351
2020-07-07 11:22:20 +02:00
602078cbde workspacesView: Add back overview transition
The transition was temporarily removed when switching to the new
workspace layout manager. Now everything is in place to reimplement
it with a combination of the layout manager's state adjustment and
the view's allocation.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:09:29 +02:00
96f63b08c2 workspacesView: Properly allocate workspaces
So far we've been allocating workspaces in a stack, and relied on
translation to move them to the right position. And as the position
depends on both the workspace's index and the view's viewport, some
care is needed to prevent gestures/scrolling from interfering with
layout updates.

Clean that up by properly allocating workspaces in a row or column,
and use a translation to reflect the current scroll position.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
d66cd0d206 workspacesView: Don't set full geometry
It's not used anymore.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
ff13ad9e71 workspacesView: Stop using full geometry
Since the workspaces themselves stopped using it, there is little
reason for upholding the difference between "full" and "actual"
geometry.

Just base positioning/swiping on the view's allocation.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
5e4b65d37e workspacesView: Use work area for default geometry
The workspace's layout manager keeps the workspace at the same ratio as
the work area, so it makes more sense to base the views' default geometry
on that as well than the monitor area we are using right now.

(It shouldn't matter much in practice, as this only affects views on
non-primary monitors where the work area usually matches the monitor area)

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
51fd0875d1 workspacesView: Simplify syncing actual geometry
We adjust the size and position of the primary view to match the workspaces
display, but views on other monitors are always set to fill their monitor.

Take that into account and create views with a fixed size and position, then
only sync the primary view to the new geometry.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
75f8903c7e workspace: Use actual container allocation
We currently assume that the passed in Clutter.ActorBox matches
the container allocation, but in reality it is the container's
content area.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
124eb1ca18 workspace: Account for window picker padding
Workspaces are supposed to request the work area as their preferred
size, however the widget will adjust the sizes returned by the
layout manager to account for borders and padding.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
b5d925817f workspace: Disable preview overlays unless fully zoomed out
The overlays are only meant to be shown when the workspace is fully
zoomed out, not when using the floating layout or some in-between state.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:53 +02:00
c134091268 windowPreview: Allow to disable overlay
WindowPreviews now contain and manage overlaid elements like close
button or title label themselves. That's generally better, but right now
the only way to disable those overlays (for example during transitions)
is to prevent any hover or focus events from getting to the preview.

Instead, add some explicit API for enabling or disabling overlay support.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:06:49 +02:00
ff89693998 workspace: Handle minimized windows in layout
The new layout manager always uses the window's regular size and position
for the floating state, but the preview of minimized windows should be
hidden instead.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1345
2020-07-07 00:05:36 +02:00
c26860dcb7 windowPreview: Ensure style as soon as preview is realized
For the windowPreview we need to ensure the style information of the
border and title is up-to-date when chromeWidths() or chromeHeights() is
called. Since the introduction of the WorkspaceLayout those functions
may be called during an allocation cycle, which means we should avoid
calling queuing relayouts inside them. Calling StWidgets ensure_style()
method will queue a relayout though in case the newly generated theme
node has a different geometry.

So avoid queueing a relayout during allocation cycles (and the warning
Clutter logs because of that) by ensuring the style of the border and
title earlier, as soon as the WindowPreview is attached to a stage.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1305
2020-07-06 23:16:15 +02:00
6757c7d20a workspace: Animate opening new windows while in overview
Use the pivot point and scale to animate in new windows which are opened
while the overview is shown.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1305
2020-07-06 23:16:15 +02:00
751189253a workspace: Use the new WorkspaceLayout for allocating window clones
Switch to the new WorkspaceLayout layout manager to allocate the window
clones of the overview properly using Clutters layouting mechanisms.

Since we now no longer make use of the fullGeometry, we can remove the
setFullGeometry() function from the Workspace class. Also we can stop
setting the actualGeometry on the Workspaces and WorkspaceViews and
instead just set the fixed position and size of the views to their
full or actual geometry. This also has the benefit that we no longer
have to set a custom clip, but can simply enable clip_to_allocation.

The geometry needs to be set inside a BEFORE_REDRAW later because
_updateWorkspacesActualGeometry() is called from a notify::allocation
handler.

This isn't doing any animations when showing/hiding the overview yet,
we'll add that in the next commit.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1305
2020-07-06 23:16:15 +02:00
21187a4cec workspace: Introduce layout manager for allocating the Workspace
Add a new ClutterLayoutManager for layouting the workspaces of the
overview, WorkspaceLayout.

This layout manager integrates the existing LayoutStrategies used to
layout the window clones of the overview and supports freezing the
layout, animating between layout changes and adjusting the spacing for
the width and height of the window chrome. It also adds support for a
layout of the windows that looks the same as the actual workspace,
transitioning between that layout and the LayoutStrategy can be done by
setting the value of an StAdjustment, available using the
stateAdjustment getter function.

This will replace the current static-positioning based layouting of the
window clones in the next commit.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1305
2020-07-06 23:16:15 +02:00
b7db56ca9b workspacesViews: Use translation for showing Workspaces
We're going to use fixed position for positioning workspaces when
they're allocated by their own layout manager, using those positions to
scroll between different workspaces interferes with that, so do that
using translations instead.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1305
2020-07-06 23:16:15 +02:00
261d36ba72 keyboard: Request a bigger size in portrait orientation
In portrait orientation, we set the height to the preferred height
for the monitor width (or, if smaller, a third o the screen height).

However as the forWidth currently doesn't make a difference, the height
is effectively controlled by the natural height of the keys - which is
rather small.

Address this by making AspectContainer request an appropriate preferred
size based on the fixed ratio.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2349
2020-07-06 15:16:35 +00:00
1e72874192 keyboard: Fix setting height in portrait orientation
get_preferred_height() returns both the minimum and natural height,
not a single size. Math.min() doesn't handle that and returns NaN,
whoops.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2349
2020-07-06 15:16:35 +00:00
f29dbd1f18 shell/window-tracker: Match on WM_CLASS first
Currently our heuristics for matching a window to its app check
for the application ID before the WM_CLASS, as the ID is more
reliable in so far that it is outside the application's control
and so it cannot use it to spoof a different application.

However this also prevents applications with multiple .desktop
files like LibreOffice from matching any .desktop files other
than the one under the main ID.

Since we now no longer allow the WM_CLASS to match a .desktop
file that doesn't belong to the sandboxed application, we can
fix that issue by checking the WM_CLASS first, without opening
the door to spoofing.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/219
2020-07-06 14:59:51 +00:00
b60836932a shell/window-tracker: Enforce prefix for sandboxed applications
At least flatpak (no idea about snap, sorry) enforces that all .desktop
files exported by a sandboxed app use the application ID as prefix.

Add the same check when trying to find a match based on the WM_CLASS,
to prevent sandboxed apps from matching a .desktop file they do not
own.

At the moment this is unlikely as we check for a match on the
sandboxed app ID first, but we are about to change that.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/219
2020-07-06 14:59:51 +00:00
bf47d1b22d shell/window-tracker: Minor simplification
Switching to autocleanup gives us a better separation between the
app/no-app cases.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/219
2020-07-06 14:59:51 +00:00
4ea0fca4fc gdm: Introduce vmware credential manager for pre-authenticated logins
The previous commit implemented a new CredentialManager interface to
    facilitate adding additional providers for pre-authenticating the user
    at the login screen.

    This commit implements a new credential manager using that interface
    for vmware deployments.

    Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1983
2020-07-04 08:11:49 +08:00
809f820cd4 gdm: Refactor oVirt to a generic CredentialManager interface
Commit 4cda61a1 added support for pre-authenticated logins in
    oVirt environments. This feature prevents a user from having
    to type their password twice (once to the oVirt management machine,
    and then immediately again in the provisioned guest running gnome-shell).
    That feature is currently oVirt specific, but a similar feature would
    be useful in non-oVirt based virt farm environments.

    Toward that end, this commit generalizes the various aspects of the
    oVirt integration code, so that it can be reused in a subsequent
    commit for adding single sign on support in vmware deployments, too.

    Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1983
2020-07-04 08:11:49 +08:00
75235624b2 background: Use actor.content.background
Because actor.background no longer exists and emitted errors when
referenced.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2949

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1343
2020-07-03 14:41:48 +08:00
5ea54426b9 st/adjustment: Add ::actor property
Will be used by transitions to set the timeline actor.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1299
2020-07-02 20:50:03 +00:00
4aabcd9e7d shell/global: Adapt to after-paint signal type signature
A stage view parameter was added.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1299
2020-07-02 20:50:03 +00:00
918b3eeb42 st/theme-node-transition: Pass actor when constructing timeline
Timelines now take an actor, to be able to derive an appropriate frame
clock, so pass the one of the actor we're transitioning on.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1299
2020-07-02 20:50:03 +00:00
482c655590 messageTray: Remove SourceActorWithLabel class
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1346
2020-07-01 20:20:26 -03:00
86b5a43008 shell/app: Add new get_icon() method
Now that we can always associate a GIcon with the app, add a method
to access it. While create_icon_texture() is still likely to be more
convenient in most cases, exposing the icon can still be useful, for
example to add it to a different kind of actor or to compare it with
other GIcons.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1342
2020-07-01 12:42:57 +02:00
d7cb2eeebc st/texture-cache: Return a GIcon from bind_cairo_surface_property()
We still load the surface into an StImageContent, but instead of
adding the content to an actor we hand out, return the content
itself (as GIcon).

That means we lose the ability to specify an icon size, but as we
get the pixel data from a fixed-size surface anyway, that shouldn't
matter much in practice.

Not to mention that the function is only used for fallback X11 icons,
which are already shit more often than not.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1342
2020-07-01 12:42:57 +02:00
770231c2d7 st/image-content: Implement GIcon interface
On the one hand, this is a bit of a stretch: StImageContent is what
we create from GIcons.

But on the other hand, there's some justification: StImageContent does
represent an image (and likely icon) after all, and there's some
precedent with GdkPixbuf.

In the end as we don't care about serialization or loading from other
API, we can go with a very crude implementation that allows us to
pass out a content as GIcon and use it directly when "loading" it.

We will use that soon to represent X11 window icons as GIcons, which
in turn will allow us to unify app icon handling.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1342
2020-07-01 12:42:57 +02:00
ecdf62d63e st/viewport: Invalidate transform when it changes
Since ClutterActor now caches the whole transformation matrix for an
actor, we need to invalidate the cached transform if the matrix returned
by apply_transform() implementations changes.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1308
2020-06-30 19:17:58 +02:00
d885486397 st/widget: Remove get_resource_scale function
ClutterActor provides the same function, but with a different return
value. So since we already switched to the ClutterActor implementation
in our C code, we can now safely remove st_widget_get_resource_scale()
and update the JS code that's still using the old API.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1287
2020-06-30 13:42:18 +00:00
1524abc947 Switch to ClutterActors resource-scale-changed signal
Instead of using the "notify::resource-scale" signal and StWidgets
"resource-scale-changed" signal, use the new "resource-scale-changed"
signal of ClutterActor, which replaces its "resource-scale" property.

Since we'd now have two "resource-scale-changed" signals, one on
ClutterActor and one on StWidget, remove the StWidget one in favour of
the new one.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1287
2020-06-30 13:42:18 +00:00
cb9842e4a4 Use new clutter_actor_get_resource_scale() API
Update the existing users of clutter_actor_get_resource_scale() to the
new API which doesn't return a boolean value.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1287
2020-06-30 13:42:18 +00:00
140ab4dec1 unlockDialog: Fix scale-factor handling on multihead
The blur effect needs to take the scale-factor into account, so we
listen for scale changes. However we set up the signal handler when
creating a background, which is repeated for each monitor, and every
time the monitor configuration changes. But we only disconnect the
last handler that was connected, and only when we are destroyed,
not when recreating backgrounds.

Fix this by splitting out updating the effect parameters to a separate
method that iterates over all backgrounds, so we can simply set up the
handler from the constructor.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1341
2020-06-30 13:12:08 +00:00
845122497b altTab: Remove down arrow when removing an app from switcher
The arrow of the removed app was still left in the list with the
visibility of the arrow still depending on the original list order. This
could either lead to apps with just one window now suddenly having a
down arrow or apps with multiple windows not having one. If the last
window in the list had a down arrow, it would have been displayed
outside the window switcher.

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

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1340
2020-06-29 22:51:41 +02:00
d51a622fc0 Update Latvian translation 2020-06-29 18:12:25 +00:00
e90466347a cleanup: Use Meta.Workspace.active property
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1337
2020-06-29 17:09:38 +02:00
73f8c1c482 inhibitShortcutsDialog: Enable line wrapping for additional label
The inhibitShortcutsDialog can show an additional label which explains
how to restore shortcuts. This label is not managed by the
MessageDialogContent, so we need to enable line wrapping and disable
ellipsization ourselves.

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

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1336
2020-06-29 10:17:07 +00:00
0ff75941ea dialog: Return GLib.SOURCE_REMOVE instead of false
This is more readable than just returning false.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1336
2020-06-29 10:17:07 +00:00
e4bb2037ca dialog: Check whether text changed when setting title or description
As usually with GObject setters, we should check whether the property
actually changed before setting the value and notifying the property. So
check whether the title or description text actually changed before
setting it.

This fixes a bug which makes the title flicker and change its size,
because when updating the title we remove the "leightweight" css class
and reapply it inside a later, which makes the title appear larger for
one frame.

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

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1336
2020-06-29 10:17:07 +00:00
481014ac9e st/viewport: Only extend child allocation when scrolled
When scrolled, the container's allocation is smaller than the allocation
of the content. To account for that, commit 2717ca9d08 added the
additional size reported by the layout manager to the content allocation.

However as it did so unconditionally, we now allow children to extend
outside the parent even when *not* scrolled, which breaks any constraints
set on the container (like "width" or "max-height").

Fix this by only extending the child allocation in scrollable dimensions.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2491
2020-06-29 00:42:03 +02:00
6dbcb5f9da Update Kazakh translation 2020-06-27 18:29:23 +00:00
c1f06daf88 st/tests: Replace ClutterGroup by ClutterActor
ClutterGroup is deprecated and can be 1:1 replaced by ClutterActor,
so let's do it.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1334
2020-06-26 21:03:57 +00:00
0717f76362 Replace anchor point by translation and pivot point
Anchor point is deprecated and will eventually be removed from
Mutter's Clutter. Replace them by a combination of pivot point
and translation.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1334
2020-06-26 21:03:57 +00:00
da738988cd workspacesView: Small cleanup
scrollToActive() and friends are only used for handling the 'switch-workspace'
animation.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1333
2020-06-26 16:19:57 +02:00
e86e88ea47 workspacesView: Don't make reactive
Since commit a11f417cd0, scroll events are handled by the SwipeTracker.
There's no other reason for the view to be reactive, so don't make it so.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1333
2020-06-26 16:19:57 +02:00
ae338af1e8 st-label: Keep labels fully pre-rendered on the GPU
The performance of the icon grid was being hindered by a large number
of primitives (a few hundred) being copied from the CPU to the GPU on
each frame. This was first noticed in mutter#971 but we failed to
investigate all the issues at the time.

You can also see the high number using `COGL_DEBUG=batching` or
`COGL_DEBUG=disable-texturing`. So now it's obvious that high number is
every letter of every label being uploaded as a separate quad. Let's not
do that and instead treat the whole label as a single quad/texture.

Measured performance on an i7-7700 at UHD 3840x2160:

Journal entries per frame on the icon grid:
 * Before: 288 (18 KB copied from CPU to GPU)
 * After:   73 ( 4 KB copied from CPU to GPU)

Spring animation:
 * Before: 20-30 FPS, avg 22/peak 45 milliseconds per frame
 * After:  30-40 FPS, avg 14/peak 28 milliseconds per frame

Scrolling the icon grid:
 * Before: 15 FPS, 50 milliseconds per frame
 * After:  30 FPS, 28 milliseconds per frame

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1329
2020-06-25 09:09:36 +00:00
3f9cc0ed37 Update Kazakh translation
(cherry picked from commit d3384d29e4)
2020-06-25 04:34:40 +00:00
8f8ecdb983 appDisplay: Update folder dialog field before ungrabbing
Noticed while working on customizable folders. Calling GrabHelper.ungrab()
ends up calling FolderDialog.popdown(), but at this point the '_isOpen'
field isn't updated yet, so we end up calling popdown() twice.

Update the '_isOpen' field before ungrabbing.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1332
2020-06-24 18:06:21 -03:00
8f547c9d5d iconGrid: Adjust animation delay
As per design feedback, adjust the animation delay to be shorter.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1332
2020-06-24 18:06:21 -03:00
821f3e8ddf overview: Pass drag source on item-drag-* signals
Overview has signals to notify about starting, cancelling, and
finishing icon drags, but none of these signals pass the dragged
item to the callbacks.

Pass the dragged items to the 'item-drag-*' overview signals.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1332
2020-06-24 18:06:21 -03:00
81be25bbd6 Update Kazakh translation 2020-06-24 16:17:48 +00:00
26d27fdbf8 overview: Define ANIMATION_TIME earlier
Commit c7e597cf72 tried to improve the slide animations when entering
the overview by using the same time as the overall overview animation,
but in fact broke the animation most of the times.

That is because the Overview imports OverviewControls before defining
the ANIMATION_TIME variable, so any javascript code that is evaluated
during that import will see the value as "undefined" (which is converted
to 0 for the animation).

Fix this by moving the ANIMATION_TIME variable before the imports instead
of the usual placement.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1331
2020-06-24 15:41:12 +02:00
c7e597cf72 overviewControls: Animate sidebars the same duration as windows
When you tap Super and see the sidebars and windows slide, it looks more
cohesive if those animations complete at the same time.

Previously there were 0.09 seconds difference between the two animations
which was enough to make it look slightly buggy. Now it doesn't.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1289
2020-06-23 19:07:30 +00:00
e4db68a1da Revert "workspacesView: Work around spurious allocation changes"
We now found the underlying bug: The ControlsManager (which causes the
bad call to `_updateWorkspacesFullGeometry()`) is getting (re-)allocated
while we add the view to the overviewGroup actor because the
overviewGroup is already visible and the view is immediately getting
mapped by `clutter_actor_add_child_internal()`. That causes a
resource-scale calculation and that indirectly causes a call to
`_clutter_stage_maybe_relayout()` (explained more detailed in the last
commit).

So now that we got rid of the immediate relayout happening when mapping
the view, we can revert this fix.

This reverts commit 6cc19ee6f0.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1315
2020-06-23 19:05:05 +00:00
980a90f8fb dateMenu: Do not ellipsize clock
This addresses the issue with ellipsized clock that occurs when using
extensions that move the clock from the middle to the side of the top
bar.

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

Signed-off-by: MOZGIII <mike-n@narod.ru>
2020-06-23 16:14:24 +00:00
87e4bf52b7 windowPreview: Fix a division by zero
When the bounding box size is 0 during allocation (which happens right
after creating a window for example), we're doing a division by zero and
end up with a NaN scale. This ends up making the childBox NaN, which
triggers an error in Clutters allocation machinery.

So fix that and fall back to a scale of 1 in case the bounding box is
empty.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1320
2020-06-23 15:50:03 +00:00
a368df61ac volume: Update indicator when microphone volume changes
The current microphone indicator only indicates if the microphone is in
use. Users might be also interested if their microphone is recording
or is muted, this commit enables that without opening the pop-up
menu. The microphone icon changes itself, depending on the sensitivity
of the microphone. It behaves similar to the already existing volume
indicator.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2902
2020-06-23 11:34:16 +02:00
5e66b104dc Updated Lithuanian translation 2020-06-21 22:18:03 +03:00
63 changed files with 2696 additions and 2254 deletions

35
NEWS
View File

@ -1,3 +1,38 @@
3.37.3
======
* Refactor and clean up window picker
[Jonas D., Florian; !1297, !1298, !1305, !1345, !1353]
* Move calendar events out of notifications list [Florian; !1282]
* Refine app folder dialogs [Georges; !1301]
* Hide switch-user button on lock screen if unsupported [Chingkai; #2687]
* Refactor and clean up app picker pagination [Georges; !1271]
* Add API to retrieve specified mimetypes from clipboards [Carlos; !1321]
* Support prepending workspace with horizontal layouts [Florian; #2916]
* Update microphone icon on input volume changes [fludixx; #2902]
* Cache labels on GPU [Daniel; !1329]
* Fix regressions in redesigned modal dialogs [Florian, Jonas D.; #2491, !1336]
* Use GIcon for all application icons [Florian; !1342]
* Support pre-authenticated logins in vmware environments [yun341; #1983]
* Better support sandboxed apps with multiple .desktop files [Florian; #219]
* Fix on-screen keyboard size in portrait orientation [Florian; #2349]
* Plugged leaks [Sebastian, Daniel, Florian; !1306, !1319, !1341]
* Misc. bug fixes and cleanups [Jonas D., Georges, Marco, Florian, Sebastian,
MOZGIII, Daniel, Mariana, Jonas Å.; !1296, !1295, #2643, !1300, !1309,
!1119, #2901, !1313, !1251, !1285, !1307, !1318, !1310, !1320, !1327, !1315,
!1289, !1331, !1332, !1333, !1334, !1340, !1287, !1308, !1346, !1299, !1343,
!1351, !1352, !1322]
Contributors:
Marco Trevisan (Treviño), Chingkai, Jonas Dreßler, Carlos Garnacho,
Sebastian Keller, MOZGIII, Florian Müllner, Georges Basile Stavracas Neto,
Mariana Picolo, Daniel van Vugt, fludixx, yun341, Jonas Ådahl
Translators:
Daniel Mustieles [es], Boyuan Yang [zh_CN], Yuri Chornoivan [uk],
Jordi Mas [ca], sicklylife [ja], Emin Tufan Çetin [tr],
Baurzhan Muftakhidinov [kk], Florentina Mușat [ro], Aurimas Černius [lt],
Rūdolfs Mazurs [lv]
3.37.2
======
* Add support for "PrefersNonDefaultGPU" desktop key [Bastien; !1226]

View File

@ -1,7 +1,7 @@
/* Window Picker */
$window_picker_spacing: $base_spacing * 2; // 16px
$window_picker_padding: $base_padding * 2; // 16px
$window_picker_spacing: $base_spacing; // 6px
$window_picker_padding: $base_padding * 2; // 12px
$window_thumbnail_border_color:transparentize($selected_fg_color, 0.65);
@ -13,8 +13,8 @@ $window_clone_border_size: 6px;
// Window picker
.window-picker {
// Space between window thumbnails
-horizontal-spacing: $window_picker_spacing;
-vertical-spacing: $window_picker_spacing;
spacing: $window_picker_spacing;
// Padding for container around window thumbnails
padding: $window_picker_padding;

View File

@ -71,7 +71,7 @@ var AuthPrompt = GObject.registerClass({
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
this._userVerifier.connect('reset', this._onReset.bind(this));
this._userVerifier.connect('smartcard-status-changed', this._onSmartcardStatusChanged.bind(this));
this._userVerifier.connect('ovirt-user-authenticated', this._onOVirtUserAuthenticated.bind(this));
this._userVerifier.connect('credential-manager-authenticated', this._onCredentialManagerAuthenticated.bind(this));
this.smartcardDetected = this._userVerifier.smartcardDetected;
this.connect('destroy', this._onDestroy.bind(this));
@ -242,7 +242,7 @@ var AuthPrompt = GObject.registerClass({
this.emit('prompted');
}
_onOVirtUserAuthenticated() {
_onCredentialManagerAuthenticated() {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
}

View File

@ -0,0 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CredentialManager */
class CredentialManager {
constructor(service) {
this._token = null;
this._service = service;
this._authenticatedSignalId = null;
}
get token() {
return this._token;
}
set token(t) {
this._token = t;
if (this._token)
this.emit('user-authenticated', this._token);
}
get service() {
return this._service;
}
}

View File

@ -810,8 +810,8 @@ var LoginDialog = GObject.registerClass({
return;
this._logoBin.destroy_all_children();
const [valid, resourceScale] = this._logoBin.get_resource_scale();
if (this._logoFile && valid) {
const resourceScale = this._logoBin.get_resource_scale();
if (this._logoFile) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, -1,

View File

@ -3,6 +3,9 @@
const Gio = imports.gi.Gio;
const Signals = imports.signals;
const Credential = imports.gdm.credentialManager;
var SERVICE_NAME = 'gdm-ovirtcred';
const OVirtCredentialsIface = `
<node>
@ -28,30 +31,14 @@ function OVirtCredentials() {
return self;
}
var OVirtCredentialsManager = class {
var OVirtCredentialsManager = class OVirtCredentialsManager extends Credential.CredentialManager {
constructor() {
this._token = null;
super(SERVICE_NAME);
this._credentials = new OVirtCredentials();
this._credentials.connectSignal('UserAuthenticated',
this._onUserAuthenticated.bind(this));
}
_onUserAuthenticated(proxy, sender, [token]) {
this._token = token;
this.emit('user-authenticated', token);
}
hasToken() {
return this._token != null;
}
getToken() {
return this._token;
}
resetToken() {
this._token = null;
(proxy, sender, [token]) => {
this.token = token;
});
}
};
Signals.addSignalMethods(OVirtCredentialsManager.prototype);

View File

@ -8,6 +8,7 @@ const Signals = imports.signals;
const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint;
const OVirt = imports.gdm.oVirt;
const Vmware = imports.gdm.vmware;
const Main = imports.ui.main;
const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager;
@ -24,7 +25,6 @@ Gio._promisify(Gdm.UserVerifierProxy.prototype,
var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
var OVIRT_SERVICE_NAME = 'gdm-ovirtcred';
var FADE_ANIMATION_TIME = 160;
var CLONE_FADE_ANIMATION_TIME = 250;
@ -160,13 +160,20 @@ var ShellUserVerifier = class {
this._failCounter = 0;
this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager();
this._credentialManagers = {};
this._credentialManagers[OVirt.SERVICE_NAME] = OVirt.getOVirtCredentialsManager();
this._credentialManagers[Vmware.SERVICE_NAME] = Vmware.getVmwareCredentialsManager();
if (this._oVirtCredentialsManager.hasToken())
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
for (let service in this._credentialManagers) {
if (this._credentialManagers[service].token) {
this._onCredentialManagerAuthenticated(this._credentialManagers[service],
this._credentialManagers[service].token);
}
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
this._oVirtUserAuthenticated.bind(this));
this._credentialManagers[service]._authenticatedSignalId =
this._credentialManagers[service].connect('user-authenticated',
this._onCredentialManagerAuthenticated.bind(this));
}
}
begin(userName, hold) {
@ -222,8 +229,11 @@ var ShellUserVerifier = class {
this._smartcardManager.disconnect(this._smartcardRemovedId);
this._smartcardManager = null;
this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId);
this._oVirtCredentialsManager = null;
for (let service in this._credentialManagers) {
let credentialManager = this._credentialManagers[service];
credentialManager.disconnect(credentialManager._authenticatedSignalId);
credentialManager = null;
}
}
answerQuery(serviceName, answer) {
@ -311,9 +321,9 @@ var ShellUserVerifier = class {
});
}
_oVirtUserAuthenticated(_token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
_onCredentialManagerAuthenticated(credentialManager, _token) {
this._preemptingService = credentialManager.service;
this.emit('credential-manager-authenticated');
}
_checkForSmartcard() {
@ -490,9 +500,12 @@ var ShellUserVerifier = class {
if (!this.serviceIsForeground(serviceName))
return;
if (serviceName == OVIRT_SERVICE_NAME) {
// The only question asked by this service is "Token?"
this.answerQuery(serviceName, this._oVirtCredentialsManager.getToken());
let token = null;
if (this._credentialManagers[serviceName])
token = this._credentialManagers[serviceName].token;
if (token) {
this.answerQuery(serviceName, token);
return;
}
@ -560,8 +573,10 @@ var ShellUserVerifier = class {
// If the login failed with the preauthenticated oVirt credentials
// then discard the credentials and revert to default authentication
// mechanism.
if (this.serviceIsForeground(OVIRT_SERVICE_NAME)) {
this._oVirtCredentialsManager.resetToken();
let foregroundService = Object.keys(this._credentialManagers).find(service =>
this.serviceIsForeground(service));
if (foregroundService) {
this._credentialManagers[foregroundService].token = null;
this._preemptingService = null;
this._verificationFailed(false);
return;

54
js/gdm/vmware.js Normal file
View File

@ -0,0 +1,54 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getVmwareCredentialsManager */
const Gio = imports.gi.Gio;
const Signals = imports.signals;
const Credential = imports.gdm.credentialManager;
const dbusPath = '/org/vmware/viewagent/Credentials';
const dbusInterface = 'org.vmware.viewagent.Credentials';
var SERVICE_NAME = 'gdm-vmwcred';
const VmwareCredentialsIface = '<node> \
<interface name="' + dbusInterface + '"> \
<signal name="UserAuthenticated"> \
<arg type="s" name="token"/> \
</signal> \
</interface> \
</node>';
const VmwareCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(VmwareCredentialsIface);
let _vmwareCredentialsManager = null;
function VmwareCredentials() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
g_interface_name: VmwareCredentialsInfo.name,
g_interface_info: VmwareCredentialsInfo,
g_name: dbusInterface,
g_object_path: dbusPath,
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
self.init(null);
return self;
}
var VmwareCredentialsManager = class VmwareCredentialsManager extends Credential.CredentialManager {
constructor() {
super(SERVICE_NAME);
this._credentials = new VmwareCredentials();
this._credentials.connectSignal('UserAuthenticated',
(proxy, sender, [token]) => {
this.token = token;
});
}
};
Signals.addSignalMethods(VmwareCredentialsManager.prototype);
function getVmwareCredentialsManager() {
if (!_vmwareCredentialsManager)
_vmwareCredentialsManager = new VmwareCredentialsManager();
return _vmwareCredentialsManager;
}

View File

@ -6,6 +6,8 @@
<file>gdm/fingerprint.js</file>
<file>gdm/loginDialog.js</file>
<file>gdm/oVirt.js</file>
<file>gdm/credentialManager.js</file>
<file>gdm/vmware.js</file>
<file>gdm/realmd.js</file>
<file>gdm/util.js</file>

View File

@ -852,6 +852,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
if (index === -1)
return;
this._arrows[index].destroy();
this._arrows.splice(index, 1);
this.icons.splice(index, 1);
this.removeItem(index);
}

View File

@ -60,7 +60,7 @@ class Animation extends St.Bin {
}
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.get_resource_scale();
const resourceScale = this.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
@ -69,12 +69,6 @@ class Animation extends St.Bin {
this._isLoaded = false;
this.destroy_all_children();
if (!validResourceScale) {
if (wasPlaying)
this.play();
return;
}
let textureCache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = textureCache.load_sliced_image(file, width, height,

View File

@ -1782,8 +1782,8 @@ var AppFolderDialog = GObject.registerClass({
this._zoomAndFadeOut();
this._showFolderLabel();
this._grabHelper.ungrab({ actor: this });
this._isOpen = false;
this._grabHelper.ungrab({ actor: this });
this.emit('open-state-changed', false);
}
});
@ -2185,17 +2185,20 @@ var AppIcon = GObject.registerClass({
}
});
var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
constructor(source, side) {
var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
constructor(source) {
let side = St.Side.LEFT;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
side = St.Side.RIGHT;
super(source, 0.5, side);
this._source = source;
this._appSystem = Shell.AppSystem.get_default();
// We want to keep the item hovered while the menu is up
this.blockSourceEvents = true;
this._appSystem.connect('installed-changed', () => {
this._updateDetailsVisibility();
});
this._updateDetailsVisibility();
this._source = source;
this.actor.add_style_class_name('app-well-menu');
// Chain our visibility and lifecycle to that of the source
this._sourceMappedId = source.connect('notify::mapped', () => {
@ -2206,50 +2209,14 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
source.disconnect(this._sourceMappedId);
this.destroy();
});
}
_updateDetailsVisibility() {
let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
this._detailsItem.visible = sw != null;
}
get app() {
return null;
}
isEmpty() {
const { app } = this;
if (!app)
return true;
return super.isEmpty();
}
_updateWindowsSection() {
this._windowSection.removeAll();
if (!this.app)
return;
let windows = this.app.get_windows().filter(
w => !w.skip_taskbar);
windows.forEach(window => {
let title = window.title || this.app.get_name();
let item = this._windowSection.addAction(title, event => {
Main.activateWindow(window, event.get_time());
});
let id = window.connect('notify::title', () => {
item.label.text = window.title || this.app.get_name();
});
item.connect('destroy', () => window.disconnect(id));
});
Main.uiGroup.add_actor(this.actor);
}
_rebuildMenu() {
this.removeAll();
let windows = this.app.get_windows().filter(
let windows = this._source.app.get_windows().filter(
w => !w.skip_taskbar);
if (windows.length > 0) {
@ -2258,29 +2225,33 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
new PopupMenu.PopupSeparatorMenuItem(_('Open Windows')));
}
this._windowSection = new PopupMenu.PopupMenuSection();
this.addMenuItem(this._windowSection);
windows.forEach(window => {
let title = window.title
? window.title : this._source.app.get_name();
let item = this._appendMenuItem(title);
item.connect('activate', () => {
this.emit('activate-window', window);
});
});
this._updateWindowsSection();
if (!this.app.is_window_backed()) {
if (!this._source.app.is_window_backed()) {
this._appendSeparator();
let appInfo = this.app.get_app_info();
let appInfo = this._source.app.get_app_info();
let actions = appInfo.list_actions();
if (this.app.can_open_new_window() &&
if (this._source.app.can_open_new_window() &&
!actions.includes('new-window')) {
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem.connect('activate', () => {
this._source.animateLaunch();
this.app.open_new_window(-1);
this._source.app.open_new_window(-1);
this.emit('activate-window', null);
});
this._appendSeparator();
}
if (discreteGpuAvailable &&
this.app.state == Shell.AppState.STOPPED) {
this._source.app.state == Shell.AppState.STOPPED) {
const appPrefersNonDefaultGPU = appInfo.get_boolean('PrefersNonDefaultGPU');
const gpuPref = appPrefersNonDefaultGPU
? Shell.AppLaunchGpu.DEFAULT
@ -2290,7 +2261,7 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
: _('Launch using Discrete Graphics Card'));
this._onGpuMenuItem.connect('activate', () => {
this._source.animateLaunch();
this.app.launch(0, -1, gpuPref);
this._source.app.launch(0, -1, gpuPref);
this.emit('activate-window', null);
});
}
@ -2302,7 +2273,7 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
if (action == 'new-window')
this._source.animateLaunch();
this.app.launch_action(action, event.get_time(), -1);
this._source.app.launch_action(action, event.get_time(), -1);
this.emit('activate-window', null);
});
}
@ -2312,19 +2283,19 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
if (canFavorite) {
this._appendSeparator();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._app.get_id());
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
if (isFavorite) {
let item = this._appendMenuItem(_("Remove from Favorites"));
item.connect('activate', () => {
let favs = AppFavorites.getAppFavorites();
favs.removeFavorite(this.app.get_id());
favs.removeFavorite(this._source.app.get_id());
});
} else {
let item = this._appendMenuItem(_("Add to Favorites"));
item.connect('activate', () => {
let favs = AppFavorites.getAppFavorites();
favs.addFavorite(this.app.get_id());
favs.addFavorite(this._source.app.get_id());
});
}
}
@ -2333,7 +2304,7 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
this._appendSeparator();
let item = this._appendMenuItem(_("Show Details"));
item.connect('activate', async () => {
let id = this.app.get_id();
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(
@ -2345,17 +2316,7 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
null, 0, -1, null);
Main.overview.hide();
});
this._detailsItem = item;
}
this._appendSeparator();
let item = this._appendMenuItem(_("Quit"));
item.connect('activate', () => {
this.app.request_quit();
});
}
}
@ -2378,27 +2339,6 @@ var BaseAppMenu = class BaseAppMenu extends PopupMenu.PopupMenu {
};
Signals.addSignalMethods(AppIconMenu.prototype);
var AppIconMenu = class AppIconMenu extends BaseAppMenu {
constructor(source) {
let side = St.Side.LEFT;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
side = St.Side.RIGHT;
super(source, side);
// We want to keep the item hovered while the menu is up
this.blockSourceEvents = true;
this.actor.add_style_class_name('app-well-menu');
Main.uiGroup.add_actor(this.actor);
}
get app() {
return this._source.app;
}
}
var SystemActionIcon = GObject.registerClass(
class SystemActionIcon extends Search.GridSearchResult {
activate() {

View File

@ -712,13 +712,18 @@ var BackgroundManager = class BackgroundManager {
}
let newBackgroundActor = this._createBackgroundActor();
newBackgroundActor.vignette_sharpness = this.backgroundActor.vignette_sharpness;
newBackgroundActor.brightness = this.backgroundActor.brightness;
const oldContent = this.backgroundActor.content;
const newContent = newBackgroundActor.content;
newContent.vignette_sharpness = oldContent.vignette_sharpness;
newContent.brightness = oldContent.brightness;
newBackgroundActor.visible = this.backgroundActor.visible;
this._newBackgroundActor = newBackgroundActor;
let background = newBackgroundActor.background;
const { background } = newBackgroundActor.content;
if (background.isLoaded) {
this._swapBackgroundActor();

View File

@ -784,6 +784,7 @@ class DateMenuButton extends PanelMenu.Button {
this._clockDisplay = new St.Label({ style_class: 'clock' });
this._clockDisplay.clutter_text.y_align = Clutter.ActorAlign.CENTER;
this._clockDisplay.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._indicator = new MessagesIndicator();

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dialog, MessageDialogContent, ListSection, ListSectionItem */
const { Clutter, GObject, Meta, Pango, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, Pango, St } = imports.gi;
function _setLabel(label, value) {
label.set({
@ -221,13 +221,16 @@ var MessageDialogContent = GObject.registerClass({
this._updateTitleStyleLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._updateTitleStyleLater = 0;
this._title.add_style_class_name('leightweight');
return false;
return GLib.SOURCE_REMOVE;
});
}
}
set title(title) {
if (this._title.text === title)
return;
_setLabel(this._title, title);
this._title.remove_style_class_name('leightweight');
@ -237,6 +240,9 @@ var MessageDialogContent = GObject.registerClass({
}
set description(description) {
if (this._description.text === description)
return;
_setLabel(this._description, description);
this.notify('description');
}

View File

@ -31,7 +31,7 @@ var IconSize = {
var APPICON_ANIMATION_OUT_SCALE = 3;
var APPICON_ANIMATION_OUT_TIME = 250;
const ICON_POSITION_DELAY = 25;
const ICON_POSITION_DELAY = 10;
const defaultGridModes = [
{

View File

@ -1,5 +1,5 @@
/* exported InhibitShortcutsDialog */
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Pango, Shell, St } = imports.gi;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
@ -90,6 +90,8 @@ var InhibitShortcutsDialog = GObject.registerClass({
text: _('You can restore shortcuts by pressing %s.').format(restoreAccel),
style_class: 'message-dialog-description',
});
restoreLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
restoreLabel.clutter_text.line_wrap = true;
content.add_child(restoreLabel);
}

View File

@ -61,6 +61,24 @@ class AspectContainer extends St.Widget {
this.queue_relayout();
}
vfunc_get_preferred_width(forHeight) {
let [min, nat] = super.vfunc_get_preferred_width(forHeight);
if (forHeight > 0)
nat = forHeight * this._ratio;
return [min, nat];
}
vfunc_get_preferred_height(forWidth) {
let [min, nat] = super.vfunc_get_preferred_height(forWidth);
if (forWidth > 0)
nat = forWidth / this._ratio;
return [min, nat];
}
vfunc_allocate(box) {
if (box.get_width() > 0 && box.get_height() > 0) {
let sizeRatio = box.get_width() / box.get_height();
@ -1608,7 +1626,9 @@ class Keyboard extends St.BoxLayout {
* we allow the OSK being smaller than 1/3rd of the monitor height
* there.
*/
this.height = Math.min(maxHeight, this.get_preferred_height(monitor.width));
const forWidth = this.get_theme_node().adjust_for_width(monitor.width);
const [, natHeight] = this.get_preferred_height(forWidth);
this.height = Math.min(maxHeight, natHeight);
}
}

View File

@ -1204,7 +1204,8 @@ class HotCorner extends Clutter.Actor {
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
this._corner.set_position(this.width - this._corner.width, 0);
this.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
this.set_pivot_point(1.0, 0.0);
this.translation_x = -this.width;
} else {
this._corner.set_position(0, 0);
}

View File

@ -489,7 +489,10 @@ var Magnifier = class Magnifier {
_updateMouseSprite() {
this._updateSpriteTexture();
let [xHot, yHot] = this._cursorTracker.get_hot();
this._mouseSprite.set_anchor_point(xHot, yHot);
this._mouseSprite.set({
translation_x: -xHot,
translation_y: -yHot,
});
}
_updateSpriteTexture() {

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationPolicy, NotificationGenericPolicy,
NotificationApplicationPolicy, Source, SourceActor, SourceActorWithLabel,
NotificationApplicationPolicy, Source, SourceActor,
SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
@ -655,77 +655,6 @@ class SourceActor extends St.Widget {
}
});
var SourceActorWithLabel = GObject.registerClass(
class SourceActorWithLabel extends SourceActor {
_init(source, size) {
super._init(source, size);
this._counterLabel = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this._counterBin = new St.Bin({ style_class: 'summary-source-counter',
child: this._counterLabel,
layout_manager: new Clutter.BinLayout() });
this._counterBin.hide();
this._counterBin.connect('style-changed', () => {
let themeNode = this._counterBin.get_theme_node();
this._counterBin.translation_x = themeNode.get_length('-shell-counter-overlap-x');
this._counterBin.translation_y = themeNode.get_length('-shell-counter-overlap-y');
});
this.add_actor(this._counterBin);
this._countUpdatedId = this._source.connect('notify::count', this._updateCount.bind(this));
this._updateCount();
this.connect('destroy', () => {
this._source.disconnect(this._countUpdatedId);
});
}
vfunc_allocate(box) {
super.vfunc_allocate(box);
let childBox = new Clutter.ActorBox();
let [, , naturalWidth, naturalHeight] = this._counterBin.get_preferred_size();
let direction = this.get_text_direction();
if (direction == Clutter.TextDirection.LTR) {
// allocate on the right in LTR
childBox.x1 = box.x2 - naturalWidth;
childBox.x2 = box.x2;
} else {
// allocate on the left in RTL
childBox.x1 = 0;
childBox.x2 = naturalWidth;
}
childBox.y1 = box.y2 - naturalHeight;
childBox.y2 = box.y2;
this._counterBin.allocate(childBox);
}
_updateCount() {
if (this._actorDestroyed)
return;
this._counterBin.visible = this._source.countVisible;
let text;
if (this._source.count < 100)
text = this._source.count.toString();
else
text = String.fromCharCode(0x22EF); // midline horizontal ellipsis
this._counterLabel.set_text(text);
}
});
var Source = GObject.registerClass({
Properties: {
'count': GObject.ParamSpec.int(

View File

@ -4,6 +4,10 @@
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
// Time for initial animation going into Overview mode;
// this is defined here to make it available in imports.
var ANIMATION_TIME = 250;
const Background = imports.ui.background;
const DND = imports.ui.dnd;
const LayoutManager = imports.ui.layout;
@ -14,9 +18,6 @@ const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode
var ANIMATION_TIME = 250;
// Must be less than ANIMATION_TIME, since we switch to
// or from the overview completely after ANIMATION_TIME,
// and don't want the shading animation to get cut off
@ -439,19 +440,19 @@ var Overview = class {
this.emit('windows-restacked', stackIndices);
}
beginItemDrag(_source) {
this.emit('item-drag-begin');
beginItemDrag(source) {
this.emit('item-drag-begin', source);
this._inItemDrag = true;
}
cancelledItemDrag(_source) {
this.emit('item-drag-cancelled');
cancelledItemDrag(source) {
this.emit('item-drag-cancelled', source);
}
endItemDrag(_source) {
endItemDrag(source) {
if (!this._inItemDrag)
return;
this.emit('item-drag-end');
this.emit('item-drag-end', source);
this._inItemDrag = false;
}

View File

@ -8,8 +8,9 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const ViewSelector = imports.ui.viewSelector;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
const Overview = imports.ui.overview;
var SIDE_CONTROLS_ANIMATION_TIME = 160;
var SIDE_CONTROLS_ANIMATION_TIME = Overview.ANIMATION_TIME;
function getRtlSlideDirection(direction, actor) {
let rtl = actor.text_direction == Clutter.TextDirection.RTL;
@ -422,6 +423,7 @@ class ControlsManager extends St.Widget {
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
this._workspaceAdjustment = new St.Adjustment({
actor: this,
value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
@ -453,8 +455,6 @@ class ControlsManager extends St.Widget {
this._group.add_child(this.viewSelector);
this._group.add_actor(this._thumbnailsSlider);
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
Main.overview.connect('showing', this._updateSpacerVisibility.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
@ -477,26 +477,6 @@ class ControlsManager extends St.Widget {
this._workspaceAdjustment.value = activeIndex;
}
_updateWorkspacesGeometry() {
let [x, y] = this.get_transformed_position();
let [width, height] = this.get_transformed_size();
let geometry = { x, y, width, height };
let spacing = this.get_theme_node().get_length('spacing');
let dashWidth = this._dashSlider.getVisibleWidth() + spacing;
let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing;
geometry.width -= dashWidth;
geometry.width -= thumbnailsWidth;
if (this.get_text_direction() == Clutter.TextDirection.LTR)
geometry.x += dashWidth;
else
geometry.x += thumbnailsWidth;
this.viewSelector.setWorkspacesFullGeometry(geometry);
}
_setVisibility() {
// Ignore the case when we're leaving the overview, since
// actors will be made visible again when entering the overview

View File

@ -5,7 +5,6 @@ const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
const Animation = imports.ui.animation;
const AppDisplay = imports.ui.appDisplay;
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab;
const DND = imports.ui.dnd;
@ -61,20 +60,69 @@ function _unpremultiply(color) {
return new Clutter.Color({ red, green, blue, alpha: color.alpha });
}
class AppMenu extends AppDisplay.BaseAppMenu {
class AppMenu extends PopupMenu.PopupMenu {
constructor(sourceActor) {
super(sourceActor, St.Side.TOP);
super(sourceActor, 0.5, St.Side.TOP);
this.actor.add_style_class_name('app-menu');
this._app = null;
this._appSystem = Shell.AppSystem.get_default();
this._windowsChangedId = 0;
/* Translators: This is the heading of a list of open windows */
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem(_("Open Windows")));
this._windowSection = new PopupMenu.PopupMenuSection();
this.addMenuItem(this._windowSection);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._newWindowItem = this.addAction(_("New Window"), () => {
this._app.open_new_window(-1);
});
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._actionSection = new PopupMenu.PopupMenuSection();
this.addMenuItem(this._actionSection);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._detailsItem = this.addAction(_('Show Details'), async () => {
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);
});
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.addAction(_("Quit"), () => {
this._app.request_quit();
});
this._appSystem.connect('installed-changed', () => {
this._updateDetailsVisibility();
});
this._updateDetailsVisibility();
}
get app() {
return this._app;
_updateDetailsVisibility() {
let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
this._detailsItem.visible = sw != null;
}
isEmpty() {
if (!this._app)
return true;
return super.isEmpty();
}
setApp(app) {
@ -109,6 +157,25 @@ class AppMenu extends AppDisplay.BaseAppMenu {
this._newWindowItem.visible =
app && app.can_open_new_window() && !actions.includes('new-window');
}
_updateWindowsSection() {
this._windowSection.removeAll();
if (!this._app)
return;
let windows = this._app.get_windows();
windows.forEach(window => {
let title = window.title || this._app.get_name();
let item = this._windowSection.addAction(title, event => {
Main.activateWindow(window, event.get_time());
});
let id = window.connect('notify::title', () => {
item.label.text = window.title || this._app.get_name();
});
item.connect('destroy', () => window.disconnect(id));
});
}
}
/**
@ -608,7 +675,7 @@ class PanelCorner extends St.DrawingArea {
let borderWidth = node.get_length('-panel-corner-border-width');
this.set_size(cornerRadius, borderWidth + cornerRadius);
this.set_anchor_point(0, borderWidth);
this.translation_y = -borderWidth;
}
});

View File

@ -62,6 +62,7 @@ var StreamSlider = class {
this._stream = null;
this._volumeCancellable = null;
this._icons = [];
}
get stream() {
@ -182,24 +183,15 @@ var StreamSlider = class {
if (!this._stream)
return null;
let icons = ["audio-volume-muted-symbolic",
"audio-volume-low-symbolic",
"audio-volume-medium-symbolic",
"audio-volume-high-symbolic",
"audio-volume-overamplified-symbolic"];
let volume = this._stream.volume;
let n;
if (this._stream.is_muted || volume <= 0) {
n = 0;
} else {
n = Math.ceil(3 * volume / this._control.get_vol_max_norm());
if (n < 1)
n = 1;
else if (n > 3)
n = 4;
n = Math.clamp(n, 1, this._icons.length - 1);
}
return icons[n];
return this._icons[n];
}
getLevel() {
@ -223,6 +215,13 @@ var OutputStreamSlider = class extends StreamSlider {
constructor(control) {
super(control);
this._slider.accessible_name = _("Volume");
this._icons = [
'audio-volume-muted-symbolic',
'audio-volume-low-symbolic',
'audio-volume-medium-symbolic',
'audio-volume-high-symbolic',
'audio-volume-overamplified-symbolic',
];
}
_connectStream(stream) {
@ -274,6 +273,12 @@ var InputStreamSlider = class extends StreamSlider {
this._control.connect('stream-added', this._maybeShowInput.bind(this));
this._control.connect('stream-removed', this._maybeShowInput.bind(this));
this._icon.icon_name = 'audio-input-microphone-symbolic';
this._icons = [
'microphone-sensitivity-muted-symbolic',
'microphone-sensitivity-low-symbolic',
'microphone-sensitivity-medium-symbolic',
'microphone-sensitivity-high-symbolic',
];
}
_connectStream(stream) {
@ -319,7 +324,7 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
this._output = new OutputStreamSlider(this._control);
this._output.connect('stream-updated', () => {
this.emit('icon-changed');
this.emit('output-icon-changed');
});
this.addMenuItem(this._output.item);
@ -327,6 +332,9 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
this._input.item.connect('notify::visible', () => {
this.emit('input-visible-changed');
});
this._input.connect('stream-updated', () => {
this.emit('input-icon-changed');
});
this.addMenuItem(this._input.item);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@ -343,7 +351,7 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
this._readInput();
this._readOutput();
} else {
this.emit('icon-changed');
this.emit('output-icon-changed');
}
}
@ -355,10 +363,14 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
this._input.stream = this._control.get_default_source();
}
getIcon() {
getOutputIcon() {
return this._output.getIcon();
}
getInputIcon() {
return this._input.getIcon();
}
getLevel() {
return this._output.getLevel();
}
@ -382,21 +394,24 @@ class Indicator extends PanelMenu.SystemIndicator {
this._control = getMixerControl();
this._volumeMenu = new VolumeMenu(this._control);
this._volumeMenu.connect('icon-changed', () => {
let icon = this._volumeMenu.getIcon();
this._volumeMenu.connect('output-icon-changed', () => {
let icon = this._volumeMenu.getOutputIcon();
if (icon != null)
this._primaryIndicator.icon_name = icon;
this._primaryIndicator.visible = icon !== null;
});
this._inputIndicator.set({
icon_name: 'audio-input-microphone-symbolic',
visible: this._volumeMenu.getInputVisible(),
});
this._inputIndicator.visible = this._volumeMenu.getInputVisible();
this._volumeMenu.connect('input-visible-changed', () => {
this._inputIndicator.visible = this._volumeMenu.getInputVisible();
});
this._volumeMenu.connect('input-icon-changed', () => {
let icon = this._volumeMenu.getInputIcon();
if (icon !== null)
this._inputIndicator.icon_name = icon;
});
this.menu.addMenuItem(this._volumeMenu);
}
@ -406,7 +421,7 @@ class Indicator extends PanelMenu.SystemIndicator {
if (result == Clutter.EVENT_PROPAGATE || this.menu.actor.mapped)
return result;
let gicon = new Gio.ThemedIcon({ name: this._volumeMenu.getIcon() });
let gicon = new Gio.ThemedIcon({ name: this._volumeMenu.getOutputIcon() });
let level = this._volumeMenu.getLevel();
let maxLevel = this._volumeMenu.getMaxLevel();
Main.osdWindowManager.show(-1, gicon, null, level, maxLevel);

View File

@ -485,6 +485,7 @@ var UnlockDialog = GObject.registerClass({
this._gdmClient = new Gdm.Client();
this._adjustment = new St.Adjustment({
actor: this,
lower: 0,
upper: 2,
page_size: 1,
@ -524,6 +525,10 @@ var UnlockDialog = GObject.registerClass({
this._bgManagers = [];
const themeContext = St.ThemeContext.get_for_stage(global.stage);
this._scaleChangedId = themeContext.connect('notify::scale-factor',
() => this._updateBackgroundEffects());
this._updateBackgrounds();
this._monitorsChangedId =
Main.layoutManager.connect('monitors-changed', this._updateBackgrounds.bind(this));
@ -568,11 +573,9 @@ var UnlockDialog = GObject.registerClass({
this._screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' });
this._userSwitchEnabledId = 0;
this._userSwitchEnabledId = this._screenSaverSettings.connect('changed::user-switch-enabled',
this._updateUserSwitchVisibility.bind(this));
this._userLoadedId = 0;
this._userLoadedId = this._user.connect('notify::is-loaded',
this._updateUserSwitchVisibility.bind(this));
@ -626,6 +629,7 @@ var UnlockDialog = GObject.registerClass({
y: monitor.y,
width: monitor.width,
height: monitor.height,
effect: new Shell.BlurEffect({ name: 'blur' }),
});
let bgManager = new Background.BackgroundManager({
@ -637,19 +641,17 @@ var UnlockDialog = GObject.registerClass({
this._bgManagers.push(bgManager);
this._backgroundGroup.add_child(widget);
}
_updateBackgroundEffects() {
const themeContext = St.ThemeContext.get_for_stage(global.stage);
let effect = new Shell.BlurEffect({
brightness: BLUR_BRIGHTNESS,
sigma: BLUR_SIGMA * themeContext.scale_factor,
});
this._scaleChangedId = themeContext.connect('notify::scale-factor', () => {
effect.sigma = BLUR_SIGMA * themeContext.scale_factor;
});
widget.add_effect(effect);
for (const widget of this._backgroundGroup) {
widget.get_effect('blur').set({
brightness: BLUR_BRIGHTNESS,
sigma: BLUR_SIGMA * themeContext.scale_factor,
});
}
}
_updateBackgrounds() {
@ -661,6 +663,7 @@ var UnlockDialog = GObject.registerClass({
for (let i = 0; i < Main.layoutManager.monitors.length; i++)
this._createBackground(i);
this._updateBackgroundEffects();
}
_ensureAuthPrompt() {

View File

@ -299,10 +299,6 @@ var ViewSelector = GObject.registerClass({
Main.overview.fadeInDesktop();
}
setWorkspacesFullGeometry(geom) {
this._workspacesDisplay.setWorkspacesFullGeometry(geom);
}
vfunc_hide() {
this.reset();
this._workspacesDisplay.hide();

View File

@ -1800,8 +1800,7 @@ var WindowManager = class {
w.window.get_parent().remove_child(w.window);
w.parent.add_child(w.window);
if (w.window.get_meta_window().get_workspace() !=
global.workspace_manager.get_active_workspace())
if (!w.window.get_meta_window().get_workspace().active)
w.window.hide();
}
switchData.container.destroy();
@ -1985,7 +1984,7 @@ var WindowManager = class {
duration,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
onComplete: () => {
if (newWs !== activeWorkspace)
if (!newWs.active)
this.actionMoveWorkspace(newWs);
this._finishWorkspaceSwitch(switchData);
},
@ -2185,10 +2184,7 @@ var WindowManager = class {
if (!Main.sessionMode.hasWorkspaces)
return;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (activeWorkspace != workspace)
if (!workspace.active)
workspace.activate(global.get_current_time());
}
@ -2196,10 +2192,7 @@ var WindowManager = class {
if (!Main.sessionMode.hasWorkspaces)
return;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (activeWorkspace != workspace) {
if (!workspace.active) {
// This won't have any effect for "always sticky" windows
// (like desktop windows or docks)

View File

@ -67,8 +67,12 @@ var WindowPreviewLayout = GObject.registerClass({
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.get_width();
const scaleY = box.get_height() / this._boundingBox.get_height();
const scaleX = this._boundingBox.get_width() > 0
? box.get_width() / this._boundingBox.get_width()
: 1;
const scaleY = this._boundingBox.get_height() > 0
? box.get_height() / this._boundingBox.get_height()
: 1;
const childBox = new Clutter.ActorBox();
@ -93,7 +97,7 @@ var WindowPreviewLayout = GObject.registerClass({
child.allocate(childBox);
} else {
child.allocate_preferred_size();
child.allocate_preferred_size(0, 0);
}
}
}
@ -185,6 +189,12 @@ var WindowPreviewLayout = GObject.registerClass({
});
var WindowPreview = GObject.registerClass({
Properties: {
'overlay-enabled': GObject.ParamSpec.boolean(
'overlay-enabled', 'overlay-enabled', 'overlay-enabled',
GObject.ParamFlags.READWRITE,
true),
},
Signals: {
'drag-begin': {},
'drag-cancelled': {},
@ -219,7 +229,6 @@ var WindowPreview = GObject.registerClass({
this._delegate = this;
this.slotId = 0;
this._stackAbove = null;
this._windowContainer.layout_manager.connect(
@ -233,8 +242,6 @@ var WindowPreview = GObject.registerClass({
this._windowActor.connect('destroy', () => this.destroy());
this._updateAttachedDialogs();
this.x = this.boundingBox.x;
this.y = this.boundingBox.y;
let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', () => this._activate());
@ -253,6 +260,7 @@ var WindowPreview = GObject.registerClass({
this.inDrag = false;
this._selected = false;
this._overlayEnabled = true;
this._closeRequested = false;
this._idleHideOverlayId = 0;
@ -345,6 +353,14 @@ var WindowPreview = GObject.registerClass({
this.add_child(this._border);
this.add_child(this._title);
this.add_child(this._closeButton);
this.connect('notify::realized', () => {
if (!this.realized)
return;
this._border.ensure_style();
this._title.ensure_style();
});
}
vfunc_get_preferred_width(forHeight) {
@ -399,8 +415,6 @@ var WindowPreview = GObject.registerClass({
}
chromeHeights() {
this._border.ensure_style();
this._title.ensure_style();
const [, closeButtonHeight] = this._closeButton.get_preferred_height(-1);
const [, titleHeight] = this._title.get_preferred_height(-1);
@ -413,7 +427,6 @@ var WindowPreview = GObject.registerClass({
}
chromeWidths() {
this._border.ensure_style();
const [, closeButtonWidth] = this._closeButton.get_preferred_width(-1);
const leftOversize = this._closeButtonSide === St.Side.LEFT
@ -427,6 +440,9 @@ var WindowPreview = GObject.registerClass({
}
showOverlay(animate) {
if (!this._overlayEnabled)
return;
const ongoingTransition = this._border.get_transition('opacity');
// Don't do anything if we're fully visible already
@ -562,6 +578,25 @@ var WindowPreview = GObject.registerClass({
});
}
// eslint-disable-next-line camelcase
get overlay_enabled() {
return this._overlayEnabled;
}
// eslint-disable-next-line camelcase
set overlay_enabled(enabled) {
if (this._overlayEnabled === enabled)
return;
this._overlayEnabled = enabled;
this.notify('overlay-enabled');
if (!enabled)
this.hideOverlay(false);
else if (this['has-pointer'] || global.stage.key_focus === this)
this.showOverlay(true);
}
// Find the actor just below us, respecting reparenting done by DND code
_getActualStackAbove() {
if (this._stackAbove == null)

File diff suppressed because it is too large Load Diff

View File

@ -549,9 +549,7 @@ var WorkspaceThumbnail = GObject.registerClass({
return;
// a click on the already current workspace should go back to the main view
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (this.metaWorkspace == activeWorkspace)
if (this.metaWorkspace.active)
Main.overview.hide();
else
this.metaWorkspace.activate(time);

View File

@ -7,6 +7,7 @@ const Main = imports.ui.main;
const SwipeTracker = imports.ui.swipeTracker;
const Workspace = imports.ui.workspace;
var { ANIMATION_TIME } = imports.ui.overview;
var WORKSPACE_SWITCH_TIME = 250;
var SCROLL_TIMEOUT_TIME = 150;
@ -21,18 +22,18 @@ var WorkspacesViewBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
}, class WorkspacesViewBase extends St.Widget {
_init(monitorIndex) {
super._init({ style_class: 'workspaces-view', reactive: true });
const { x, y, width, height } =
Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
super._init({
style_class: 'workspaces-view',
x, y, width, height,
});
this.connect('destroy', this._onDestroy.bind(this));
global.focus_manager.add_group(this);
// The actor itself isn't a drop target, so we don't want to pick on its area
this.set_size(0, 0);
this._monitorIndex = monitorIndex;
this._fullGeometry = null;
this._actualGeometry = null;
this._inDrag = false;
this._windowDragBeginId = Main.overview.connect('window-drag-begin', this._dragBegin.bind(this));
this._windowDragEndId = Main.overview.connect('window-drag-end', this._dragEnd.bind(this));
@ -51,24 +52,19 @@ var WorkspacesViewBase = GObject.registerClass({
}
}
_dragBegin(overview, window) {
_dragBegin() {
this._inDrag = true;
this._setReservedSlot(window);
}
_dragEnd() {
this._inDrag = false;
this._setReservedSlot(null);
}
setFullGeometry(geom) {
this._fullGeometry = geom;
this._syncFullGeometry();
}
vfunc_allocate(box) {
this.set_allocation(box);
setActualGeometry(geom) {
this._actualGeometry = geom;
this._syncActualGeometry();
for (const child of this)
child.allocate_available_size(0, 0, box.get_width(), box.get_height());
}
});
@ -83,9 +79,8 @@ class WorkspacesView extends WorkspacesViewBase {
this._gestureActive = false; // touch(pad) gestures
this._scrollAdjustment = scrollAdjustment;
this._onScrollId =
this._scrollAdjustment.connect('notify::value',
this._onScroll.bind(this));
this._onScrollId = this._scrollAdjustment.connect('notify::value',
this._updateScrollPosition.bind(this));
this._workspaces = [];
this._updateWorkspaces();
@ -97,34 +92,42 @@ class WorkspacesView extends WorkspacesViewBase {
this._workspaces.sort((a, b) => {
return a.metaWorkspace.index() - b.metaWorkspace.index();
});
this._updateWorkspaceActors(false);
this._workspaces.forEach(
(ws, i) => this.set_child_at_index(ws, i));
});
this._overviewShownId =
Main.overview.connect('shown', () => {
this.set_clip(this._fullGeometry.x, this._fullGeometry.y,
this._fullGeometry.width, this._fullGeometry.height);
});
this._overviewShownId = Main.overview.connect('shown', () => {
this.clip_to_allocation = true;
});
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
this._activeWorkspaceChanged.bind(this));
}
_setReservedSlot(window) {
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(window);
}
vfunc_allocate(box) {
this.set_allocation(box);
_syncFullGeometry() {
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setFullGeometry(this._fullGeometry);
}
if (this.get_n_children() === 0)
return;
_syncActualGeometry() {
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setActualGeometry(this._actualGeometry);
const { workspaceManager } = global;
const { nWorkspaces } = workspaceManager;
const vertical = workspaceManager.layout_rows === -1;
const rtl = this.text_direction === Clutter.TextDirection.RTL;
this._workspaces.forEach((child, index) => {
if (rtl && !vertical)
index = nWorkspaces - index - 1;
const x = vertical ? 0 : index * this.width;
const y = vertical ? index * this.height : 0;
child.allocate_available_size(x, y, box.get_width(), box.get_height());
});
this._updateScrollPosition();
}
getActiveWorkspace() {
@ -140,11 +143,11 @@ class WorkspacesView extends WorkspacesViewBase {
else
this._workspaces[w].fadeToOverview();
}
this._updateWorkspaceActors(false);
this._updateScrollPosition();
}
animateFromOverview(animationType) {
this.remove_clip();
this.clip_to_allocation = false;
for (let w = 0; w < this._workspaces.length; w++) {
if (animationType == AnimationType.ZOOM)
@ -159,49 +162,22 @@ class WorkspacesView extends WorkspacesViewBase {
this._workspaces[i].syncStacking(stackIndices);
}
// Update workspace actors parameters
// @showAnimation: iff %true, transition between states
_updateWorkspaceActors(showAnimation) {
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
_scrollToActive() {
const { workspaceManager } = global;
const active = workspaceManager.get_active_workspace_index();
this._animating = showAnimation;
this._animating = true;
this._updateVisibility();
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
workspace.remove_all_transitions();
let params = {};
if (workspaceManager.layout_rows == -1)
params.y = (w - active) * this._fullGeometry.height;
else if (this.text_direction == Clutter.TextDirection.RTL)
params.x = (active - w) * this._fullGeometry.width;
else
params.x = (w - active) * this._fullGeometry.width;
if (showAnimation) {
let easeParams = Object.assign(params, {
duration: WORKSPACE_SWITCH_TIME,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
});
// we have to call _updateVisibility() once before the
// animation and once afterwards - it does not really
// matter which tween we use, so we pick the first one ...
if (w == 0) {
this._updateVisibility();
easeParams.onComplete = () => {
this._animating = false;
this._updateVisibility();
};
}
workspace.ease(easeParams);
} else {
workspace.set(params);
if (w == 0)
this._updateVisibility();
}
}
this._scrollAdjustment.remove_transition('value');
this._scrollAdjustment.ease(active, {
duration: WORKSPACE_SWITCH_TIME,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
onComplete: () => {
this._animating = false;
this._updateVisibility();
},
});
}
_updateVisibility() {
@ -242,19 +218,14 @@ class WorkspacesView extends WorkspacesViewBase {
}
}
if (this._fullGeometry) {
this._updateWorkspaceActors(false);
this._syncFullGeometry();
}
if (this._actualGeometry)
this._syncActualGeometry();
this._updateScrollPosition();
}
_activeWorkspaceChanged(_wm, _from, _to, _direction) {
if (this._scrolling)
return;
this._updateWorkspaceActors(true);
this._scrollToActive();
}
_onDestroy() {
@ -276,21 +247,25 @@ class WorkspacesView extends WorkspacesViewBase {
this._gestureActive = false;
// Make sure title captions etc are shown as necessary
this._updateWorkspaceActors(true);
this._scrollToActive();
this._updateVisibility();
}
// sync the workspaces' positions to the value of the scroll adjustment
// and change the active workspace if appropriate
_onScroll(adj) {
if (adj.get_transition('value') !== null && !this._gestureActive)
_updateScrollPosition() {
if (!this.has_allocation())
return;
const adj = this._scrollAdjustment;
const allowSwitch =
adj.get_transition('value') === null && !this._gestureActive;
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
let current = Math.round(adj.value);
if (active != current && !this._gestureActive) {
if (allowSwitch && active !== current) {
if (!this._workspaces[current]) {
// The current workspace was destroyed. This could happen
// when you are on the last empty workspace, and consolidate
@ -307,36 +282,16 @@ class WorkspacesView extends WorkspacesViewBase {
if (adj.upper == 1)
return;
let last = this._workspaces.length - 1;
const vertical = workspaceManager.layout_rows === -1;
const rtl = this.text_direction === Clutter.TextDirection.RTL;
const progress = vertical || !rtl
? adj.value : adj.upper - adj.value;
if (workspaceManager.layout_rows == -1) {
let firstWorkspaceY = this._workspaces[0].y;
let lastWorkspaceY = this._workspaces[last].y;
let workspacesHeight = lastWorkspaceY - firstWorkspaceY;
let currentY = firstWorkspaceY;
let newY = -Math.round(adj.value / (adj.upper - 1) * workspacesHeight);
let dy = newY - currentY;
for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].visible = Math.abs(i - adj.value) <= 1;
this._workspaces[i].y += dy;
}
} else {
let firstWorkspaceX = this._workspaces[0].x;
let lastWorkspaceX = this._workspaces[last].x;
let workspacesWidth = lastWorkspaceX - firstWorkspaceX;
let currentX = firstWorkspaceX;
let newX = -Math.round(adj.value / (adj.upper - 1) * workspacesWidth);
let dx = newX - currentX;
for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].visible = Math.abs(i - adj.value) <= 1;
this._workspaces[i].x += dx;
}
for (const ws of this._workspaces) {
if (vertical)
ws.translation_y = -progress * this.height;
else
ws.translation_x = -progress * this.width;
}
}
});
@ -349,18 +304,6 @@ class ExtraWorkspaceView extends WorkspacesViewBase {
this.add_actor(this._workspace);
}
_setReservedSlot(window) {
this._workspace.setReservedSlot(window);
}
_syncFullGeometry() {
this._workspace.setFullGeometry(this._fullGeometry);
}
_syncActualGeometry() {
this._workspace.setActualGeometry(this._actualGeometry);
}
getActiveWorkspace() {
return this._workspace;
}
@ -438,6 +381,8 @@ class WorkspacesDisplay extends St.Widget {
this._windowDragEndId =
Main.overview.connect('window-drag-begin',
this._windowDragEnd.bind(this));
this._overviewShownId = Main.overview.connect('shown',
this._syncWorkspacesActualGeometry.bind(this));
this._primaryIndex = Main.layoutManager.primaryIndex;
this._workspacesViews = [];
@ -452,9 +397,9 @@ class WorkspacesDisplay extends St.Widget {
this._scrollEventId = 0;
this._keyPressEventId = 0;
this._scrollTimeoutId = 0;
this._syncActualGeometryLater = 0;
this._actualGeometry = null;
this._fullGeometry = null;
this._inWindowDrag = false;
this._gestureActive = false; // touch(pad) gestures
@ -476,6 +421,11 @@ class WorkspacesDisplay extends St.Widget {
this._parentSetLater = 0;
}
if (this._syncActualGeometryLater) {
Meta.later_remove(this._syncActualGeometryLater);
this._syncActualGeometryLater = 0;
}
if (this._scrollTimeoutId !== 0) {
GLib.source_remove(this._scrollTimeoutId);
this._scrollTimeoutId = 0;
@ -485,6 +435,7 @@ class WorkspacesDisplay extends St.Widget {
global.workspace_manager.disconnect(this._reorderWorkspacesdId);
Main.overview.disconnect(this._windowDragBeginId);
Main.overview.disconnect(this._windowDragEndId);
Main.overview.disconnect(this._overviewShownId);
}
_windowDragBegin() {
@ -508,25 +459,11 @@ class WorkspacesDisplay extends St.Widget {
workspaceManager.get_active_workspace_index();
}
_activeWorkspaceChanged(_wm, _from, _to, _direction) {
_activeWorkspaceChanged(_wm, _from, to, _direction) {
if (this._gestureActive)
return;
this._scrollToActive();
}
_scrollToActive() {
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
this._updateScrollAdjustment(active);
}
_updateScrollAdjustment(index) {
if (this._gestureActive)
return;
this._scrollAdjustment.ease(index, {
this._scrollAdjustment.ease(to, {
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
duration: WORKSPACE_SWITCH_TIME,
});
@ -564,11 +501,8 @@ class WorkspacesDisplay extends St.Widget {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startTouchGesture();
let monitors = Main.layoutManager.monitors;
let geometry = monitor === this._primaryIndex
? this._fullGeometry : monitors[monitor];
let distance = global.workspace_manager.layout_rows === -1
? geometry.height : geometry.width;
? this.height : this.width;
let progress = adjustment.value / adjustment.page_size;
let points = Array.from(
@ -588,14 +522,13 @@ class WorkspacesDisplay extends St.Widget {
this._clickAction.release();
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = workspaceManager.get_workspace_by_index(endProgress);
this._scrollAdjustment.ease(endProgress, {
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
duration,
onComplete: () => {
if (newWs !== activeWorkspace)
if (!newWs.active)
newWs.activate(global.get_current_time());
this._endTouchGesture();
},
@ -616,7 +549,7 @@ class WorkspacesDisplay extends St.Widget {
this.show();
this._updateWorkspacesViews();
if (this._actualGeometry && this._fullGeometry) {
if (this._actualGeometry) {
for (let i = 0; i < this._workspacesViews.length; i++) {
let animationType;
if (fadeOnPrimary && i == this._primaryIndex)
@ -625,6 +558,9 @@ class WorkspacesDisplay extends St.Widget {
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateToOverview(animationType);
}
if (!fadeOnPrimary)
this._syncWorkspacesActualGeometry();
}
this._restackedNotifyId =
@ -646,6 +582,15 @@ class WorkspacesDisplay extends St.Widget {
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateFromOverview(animationType);
}
const { primaryIndex } = Main.layoutManager;
const { x, y, width, height } =
Main.layoutManager.getWorkAreaForMonitor(primaryIndex);
this._getPrimaryView().ease({
x, y, width, height,
duration: fadeOnPrimary ? 0 : ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
}
vfunc_hide() {
@ -675,6 +620,7 @@ class WorkspacesDisplay extends St.Widget {
return;
this._updateWorkspacesViews();
this._syncWorkspacesActualGeometry();
}
_updateWorkspacesViews() {
@ -691,19 +637,9 @@ class WorkspacesDisplay extends St.Widget {
else
view = new WorkspacesView(i, this._scrollAdjustment);
// HACK: Avoid spurious allocation changes while updating views
view.hide();
this._workspacesViews.push(view);
Main.layoutManager.overviewGroup.add_actor(view);
}
this._workspacesViews.forEach(v => v.show());
if (this._fullGeometry)
this._syncWorkspacesFullGeometry();
if (this._actualGeometry)
this._syncWorkspacesActualGeometry();
}
_getMonitorIndexForEvent(event) {
@ -750,43 +686,35 @@ class WorkspacesDisplay extends St.Widget {
});
}
// This geometry should always be the fullest geometry
// the workspaces switcher can ever be allocated, as if
// the sliding controls were never slid in at all.
setWorkspacesFullGeometry(geom) {
this._fullGeometry = geom;
this._syncWorkspacesFullGeometry();
}
_syncWorkspacesFullGeometry() {
if (!this._workspacesViews.length)
return;
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
let geometry = i == this._primaryIndex ? this._fullGeometry : monitors[i];
this._workspacesViews[i].setFullGeometry(geometry);
}
}
_updateWorkspacesActualGeometry() {
const [x, y] = this.get_transformed_position();
const width = this.allocation.get_width();
const height = this.allocation.get_height();
this._actualGeometry = { x, y, width, height };
this._syncWorkspacesActualGeometry();
if (this._syncActualGeometryLater > 0)
return;
this._syncActualGeometryLater =
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._syncWorkspacesActualGeometry();
this._syncActualGeometryLater = 0;
return GLib.SOURCE_REMOVE;
});
}
_syncWorkspacesActualGeometry() {
if (!this._workspacesViews.length)
const primaryView = this._getPrimaryView();
if (!primaryView)
return;
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
let geometry = i === this._primaryIndex ? this._actualGeometry : monitors[i];
this._workspacesViews[i].setActualGeometry(geometry);
}
primaryView.ease({
...this._actualGeometry,
duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
}
_onRestacked(overview, stackIndices) {

View File

@ -1,5 +1,5 @@
project('gnome-shell', 'c',
version: '3.37.2',
version: '3.37.3',
meson_version: '>= 0.53.0',
license: 'GPLv2+'
)
@ -25,7 +25,7 @@ gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1'
gjs_req = '>= 1.65.1'
gtk_req = '>= 3.15.0'
mutter_req = '>= 3.37.2'
mutter_req = '>= 3.37.3'
polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1'
startup_req = '>= 0.11'

1
mutter

Submodule mutter deleted from 1551b6d386

313
po/kk.po
View File

@ -1,14 +1,14 @@
# Kazakh translation for gnome-shell.
# Copyright (C) 2015 The gnome-shell authors.
# This file is distributed under the same license as the gnome-shell package.
# Baurzhan Muftakhidinov <baurthefirst@gmail.com>, 2012-2019.
# Baurzhan Muftakhidinov <baurthefirst@gmail.com>, 2012-2020.
#
msgid ""
msgstr ""
"Project-Id-Version: master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-06-05 23:11+0000\n"
"PO-Revision-Date: 2020-06-15 18:37+0500\n"
"POT-Creation-Date: 2020-06-25 04:35+0000\n"
"PO-Revision-Date: 2020-06-27 23:27+0500\n"
"Last-Translator: Baurzhan Muftakhidinov <baurthefirst@gmail.com>\n"
"Language-Team: Kazakh <kk_KZ@googlegroups.com>\n"
"Language: kk\n"
@ -81,16 +81,10 @@ msgstr ""
"DisableExtension DBus тәсілдерімен де өзгертуге болады."
#: data/org.gnome.shell.gschema.xml.in:26
#| msgid "UUIDs of extensions to enable"
msgid "UUIDs of extensions to force disabling"
msgstr ""
msgstr "Мәжбүрлі сөндіру үшін кеңейтулер UUID-лары"
#: data/org.gnome.shell.gschema.xml.in:27
#| msgid ""
#| "GNOME Shell extensions have a UUID property; this key lists extensions "
#| "which should be loaded. Any extension that wants to be loaded needs to be "
#| "in this list. You can also manipulate this list with the EnableExtension "
#| "and DisableExtension D-Bus methods on org.gnome.Shell."
msgid ""
"GNOME Shell extensions have a UUID property; this key lists extensions which "
"should be disabled, even if loaded as part of the current mode. You can also "
@ -98,6 +92,11 @@ msgid ""
"methods on org.gnome.Shell. This key takes precedence over the “enabled-"
"extensions” setting."
msgstr ""
"GNOME Shell кеңейтулерінде UUID қасиеті бар; бұл кілт сөндіру үшін "
"кеңейтулер тізімін сақтайды, олар қазіргі режимде іске қосылған болса да. "
"Сонымен қатар, бұл тізімді org.gnome.Shell EnableExtension және "
"DisableExtension D-Bus тәсілдері арқылы түзетуге болады. Бұл кілт \"enabled-"
"extensions\" баптауын үстінен басады."
#: data/org.gnome.shell.gschema.xml.in:37
msgid "Disable user extensions"
@ -333,19 +332,19 @@ msgstr ""
#: data/org.gnome.shell.gschema.xml.in:234
msgid "Locations"
msgstr "Орналасу"
msgstr "Орналасулар"
#: data/org.gnome.shell.gschema.xml.in:235
msgid "The locations to show in world clocks"
msgstr ""
msgstr "Дүниежүзілік сағаттарда көрсетілетін орналасулар"
#: data/org.gnome.shell.gschema.xml.in:245
msgid "Automatic location"
msgstr ""
msgstr "Автоматты орналасу"
#: data/org.gnome.shell.gschema.xml.in:246
msgid "Whether to fetch the current location or not"
msgstr ""
msgstr "Ағымдағы орналасуды алу керек пе, жоқ па"
#: data/org.gnome.shell.gschema.xml.in:253
msgid "Location"
@ -353,7 +352,7 @@ msgstr "Орналасу"
#: data/org.gnome.shell.gschema.xml.in:254
msgid "The location for which to show a forecast"
msgstr ""
msgstr "Ауа райы болжамын көрсету үшін орналасу"
#: data/org.gnome.shell.gschema.xml.in:266
msgid "Attach modal dialog to the parent window"
@ -532,23 +531,20 @@ msgstr "пайдаланушыны ауыстыру"
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
#: js/misc/systemActions.js:135
#| msgid "lock orientation;screen;rotation"
msgid "lock orientation;unlock orientation;screen;rotation"
msgstr ""
"lock orientation;unlock orientation;screen;rotation;бұрылуды құлыптау;экран "
"бұрылуы"
#: js/misc/systemActions.js:255
#| msgctxt "search-result"
#| msgid "Lock Orientation"
msgctxt "search-result"
msgid "Unlock Screen Rotation"
msgstr ""
msgstr "Экранды бұруды құлыптан босату"
#: js/misc/systemActions.js:256
#| msgctxt "search-result"
#| msgid "Lock Orientation"
msgctxt "search-result"
msgid "Lock Screen Rotation"
msgstr ""
msgstr "Экранды бұруды құлыптау"
#: js/misc/util.js:120
msgid "Command not found"
@ -705,38 +701,36 @@ msgstr "Тыйым салу"
msgid "Grant Access"
msgstr "Рұқсат ету"
#: js/ui/appDisplay.js:956
#: js/ui/appDisplay.js:903
msgid "Unnamed Folder"
msgstr "Атаусыз бума"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2215 js/ui/panel.js:75
#: js/ui/appDisplay.js:2225 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Ашық терезелер"
#: js/ui/appDisplay.js:2234 js/ui/panel.js:82
#: js/ui/appDisplay.js:2244 js/ui/panel.js:82
msgid "New Window"
msgstr "Жаңа терезе"
#: js/ui/appDisplay.js:2250
#| msgid "Launch using Dedicated Graphics Card"
#: js/ui/appDisplay.js:2260
msgid "Launch using Integrated Graphics Card"
msgstr ""
msgstr "Құрамындағы графикалық картаны пайдаланып жөнелту"
#: js/ui/appDisplay.js:2251
#| msgid "Launch using Dedicated Graphics Card"
#: js/ui/appDisplay.js:2261
msgid "Launch using Discrete Graphics Card"
msgstr ""
msgstr "Бөлек графикалық картаны пайдаланып жөнелту"
#: js/ui/appDisplay.js:2279 js/ui/dash.js:239
#: js/ui/appDisplay.js:2289 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Таңдамалылардан өшіру"
#: js/ui/appDisplay.js:2285
#: js/ui/appDisplay.js:2295
msgid "Add to Favorites"
msgstr "Таңдамалыларға қосу"
#: js/ui/appDisplay.js:2295 js/ui/panel.js:93
#: js/ui/appDisplay.js:2305 js/ui/panel.js:93
msgid "Show Details"
msgstr "Деректерді көрсету"
@ -766,7 +760,7 @@ msgstr "Құлаққап"
msgid "Headset"
msgstr "Микрофонды құлаққап"
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:273
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:272
msgid "Microphone"
msgstr "Микрофон"
@ -918,9 +912,8 @@ msgid "External drive disconnected"
msgstr "Сыртқы диск алынды"
#: js/ui/components/automountManager.js:208
#| msgid "Unable to lock"
msgid "Unable to unlock volume"
msgstr ""
msgstr "Томды босату мүмкін емес"
#: js/ui/components/automountManager.js:209
msgid "The installed udisks version does not support the PIM setting"
@ -993,7 +986,6 @@ msgid "PIN code is needed for the mobile broadband device"
msgstr "Сымсыз кеңжолақты құрылғы үшін PIN коды керек"
#: js/ui/components/networkAgent.js:334
#| msgid "PIN: "
msgid "PIN"
msgstr "PIN"
@ -1129,9 +1121,8 @@ msgid "Weather"
msgstr "Ауа райы"
#: js/ui/dateMenu.js:653
#| msgid "Select a location…"
msgid "Select weather location…"
msgstr ""
msgstr "Ауа райы орнын таңдау…"
#: js/ui/endSessionDialog.js:37
#, javascript-format
@ -1251,9 +1242,10 @@ msgstr ""
"эл. желісіне жалғанып тұрғанына көз жеткізіңіз."
#: js/ui/endSessionDialog.js:259
#| msgid "Running on battery power: please plug in before installing updates."
msgid "Running on battery power: Please plug in before installing updates."
msgstr ""
"Батарея қорегінен жұмыс істеуде. Жаңартуларды орнату алдында эл. қорегі "
"желісіне жалғаңыз."
#: js/ui/endSessionDialog.js:268
msgid "Some applications are busy or have unsaved work"
@ -1289,30 +1281,26 @@ msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "extensions.gnome.org адресінен \"%s\" жүктеп алып, орнату керек пе?"
#: js/ui/extensionSystem.js:252
#| msgid "No Extensions Installed"
msgid "Extension Updates Available"
msgstr ""
msgstr "Кеңейту жаңартулары дайын"
#: js/ui/extensionSystem.js:253
msgid "Extension updates are ready to be installed."
msgstr ""
msgstr "Кеңейту жаңартулары орнатылуға дайын."
#: js/ui/inhibitShortcutsDialog.js:79
#| msgid "%s wants to inhibit shortcuts"
msgid "Allow inhibiting shortcuts"
msgstr ""
msgstr "Пернелер жарлығын алмастыруды рұқсат ету"
#. Translators: %s is an application name like "Settings"
#: js/ui/inhibitShortcutsDialog.js:82
#, javascript-format
#| msgid "Application wants to inhibit shortcuts"
msgid "The application %s wants to inhibit shortcuts"
msgstr ""
msgstr "%s қолданбасы пернелер жарлығын алмастырғысы келеді"
#: js/ui/inhibitShortcutsDialog.js:83
#| msgid "Application wants to inhibit shortcuts"
msgid "An application wants to inhibit shortcuts"
msgstr ""
msgstr "Қолданба пернелер жарлығын алмастырғысы келеді"
#. Translators: %s is a keyboard shortcut like "Super+x"
#: js/ui/inhibitShortcutsDialog.js:90
@ -1445,23 +1433,25 @@ msgid "Web Page"
msgstr "Веб парағы"
#: js/ui/main.js:297
#| msgid "Log in as another user"
msgid "Logged in as a privileged user"
msgstr ""
msgstr "Привилегияланған пайдаланушы ретінде жүйеге кірген"
#: js/ui/main.js:298
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
msgstr ""
"Привилегияланған пайдаланушы ретінде сессияны орындаудан қауіпсіздік "
"салдарынан аулақ болу керек. Мүмкін болса, қалыпты пайдаланушы ретінде "
"жүйеге кіріңіз."
#: js/ui/main.js:337
msgid "Screen Lock disabled"
msgstr ""
msgstr "Экранды блоктау сөндірілген"
#: js/ui/main.js:338
msgid "Screen Locking requires the GNOME display manager."
msgstr ""
msgstr "Экранды блоктау GNOME дисплейлер басқарушысын талап етеді."
#: js/ui/messageTray.js:1547
msgid "System Information"
@ -1475,13 +1465,13 @@ msgstr "Белгісіз әртіс"
msgid "Unknown title"
msgstr "Белгісіз атауы"
#: js/ui/overview.js:73
#: js/ui/overview.js:74
msgid "Undo"
msgstr "Болдырмау"
#. Translators: This is the main view to select
#. activities. See also note for "Activities" string.
#: js/ui/overview.js:86
#: js/ui/overview.js:87
msgid "Overview"
msgstr "Шолу"
@ -1489,7 +1479,7 @@ msgstr "Шолу"
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: js/ui/overview.js:107
#: js/ui/overview.js:108
msgid "Type to search"
msgstr "Іздеу үшін теріңіз"
@ -1626,18 +1616,16 @@ msgid "Caps lock is on."
msgstr "Caps lock іске қосылған."
#: js/ui/shellMountOperation.js:285
#| msgid "Volume"
msgid "Hidden Volume"
msgstr ""
msgstr "Жасырын том"
#: js/ui/shellMountOperation.js:288
msgid "Windows System Volume"
msgstr ""
msgstr "Windows жүйелік томы"
#: js/ui/shellMountOperation.js:291
#| msgid "Mouse Keys"
msgid "Uses Keyfiles"
msgstr ""
msgstr "Кілт файлдарды қолданады"
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:298
@ -1645,6 +1633,7 @@ msgstr ""
msgid ""
"To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead."
msgstr ""
"Кілт файлдарын қолданатын томды босату үшін, <i>%s</i> утилитасын қолданыңыз."
#: js/ui/shellMountOperation.js:306
msgid "PIM Number"
@ -1666,7 +1655,7 @@ msgstr "%s ашу"
#: js/ui/shellMountOperation.js:423
msgid "The PIM must be a number or empty."
msgstr ""
msgstr "PIM тек сандардан тұруы, немесе бос болуы тиіс."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:465
@ -1678,7 +1667,7 @@ msgstr "%s іске қосу мүмкін емес"
#: js/ui/shellMountOperation.js:467
#, javascript-format
msgid "Couldnt find the %s application"
msgstr ""
msgstr "%s қолданбасы табылмады"
#: js/ui/status/accessibility.js:35
msgid "Accessibility"
@ -1733,14 +1722,12 @@ msgid "Bluetooth Settings"
msgstr "Bluetooth баптаулары"
#: js/ui/status/bluetooth.js:152
#| msgid "Bluetooth"
msgid "Bluetooth Off"
msgstr ""
msgstr "Bluetooth сөндірілген"
#: js/ui/status/bluetooth.js:154
#| msgid "Bluetooth"
msgid "Bluetooth On"
msgstr ""
msgstr "Bluetooth іске қосылған"
#: js/ui/status/brightness.js:39
msgid "Brightness"
@ -1748,7 +1735,7 @@ msgstr "Жарықтылығы"
#: js/ui/status/dwellClick.js:13
msgid "Single Click"
msgstr ""
msgstr "Дара шерту"
#: js/ui/status/dwellClick.js:18
msgid "Double Click"
@ -1760,11 +1747,11 @@ msgstr "Тартып апару"
#: js/ui/status/dwellClick.js:28
msgid "Secondary Click"
msgstr ""
msgstr "Екінші шерту"
#: js/ui/status/dwellClick.js:37
msgid "Dwell Click"
msgstr ""
msgstr "Пернеде кідіртуден кейінгі сол жақпен шерту"
#: js/ui/status/keyboard.js:826
msgid "Keyboard"
@ -1800,7 +1787,7 @@ msgstr "Іске қосу"
#: js/ui/status/location.js:350
msgid "Allow location access"
msgstr ""
msgstr "Орналасуға қатынауды рұқсат ету"
#. Translators: %s is an application name
#: js/ui/status/location.js:352
@ -2140,11 +2127,11 @@ msgstr "Thunderbolt авторизация қатесі"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Thunderbolt құралғысын авторизациялау мүмкін емес: %s"
#: js/ui/status/volume.js:154
#: js/ui/status/volume.js:155
msgid "Volume changed"
msgstr "Дыбыс өзгертілді"
#: js/ui/status/volume.js:225
#: js/ui/status/volume.js:217
msgid "Volume"
msgstr "Дыбыс деңгейі"
@ -2179,18 +2166,16 @@ msgstr "Тек құрамындағы"
#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:371
#| msgctxt "calendar heading"
#| msgid "%A, %B %-d"
msgid "%A %B %-d"
msgstr "%A %B %-d"
#: js/ui/unlockDialog.js:377
msgid "Swipe up to unlock"
msgstr ""
msgstr "Босату үшін жоғары өткізіңіз"
#: js/ui/unlockDialog.js:378
msgid "Click or press a key to unlock"
msgstr ""
msgstr "Босату үшін шертіңіз немесе пернені басыңыз"
#: js/ui/unlockDialog.js:550
msgid "Unlock Window"
@ -2373,6 +2358,8 @@ msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"GNOME кеңейтулері көмегімен кеңейтулерді жаңарту, баптау және оларды өшіру "
"немесе сөндіруге болады."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
@ -2388,6 +2375,7 @@ msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Кеңейтуді өшірсеңіз, оны қайта іске қосу үшін қайта жүктеп алу керек болады"
#: subprojects/extensions-app/js/main.js:150
msgid "Remove"
@ -2401,15 +2389,15 @@ msgstr "Baurzhan Muftakhidinov <baurthefirst@gmail.com>"
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] ""
msgstr[0] "%d кеңейту жүйеге келесі рет кірген кезде жаңартылатын болады."
#: subprojects/extensions-app/js/main.js:461
msgid "The extension is incompatible with the current GNOME version"
msgstr ""
msgstr "Бұл кеңейту ағымдағы GNOME нұсқасымен үйлеспейді"
#: subprojects/extensions-app/js/main.js:464
msgid "The extension had an error"
msgstr ""
msgstr "Кеңейтуде қате болды"
#: subprojects/extensions-app/data/ui/extension-row.ui:109
#: subprojects/extensions-tool/src/command-create.c:325
@ -2428,7 +2416,7 @@ msgstr "Авторы"
#: subprojects/extensions-app/data/ui/extension-row.ui:216
msgid "Website"
msgstr "Веб-сайт"
msgstr "Веб сайт"
#: subprojects/extensions-app/data/ui/extension-row.ui:233
msgid "Remove…"
@ -2460,6 +2448,9 @@ msgid ""
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Кеңейтулер жүйелік мәселелерді, соның ішінде өнімділік мәселелерін туғызуы "
"мүмкін. Жүйелік мәселелерге тап болсаңыз, барлық кеңейтулерді сөндіру "
"ұсынылады."
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
msgid "Manually Installed"
@ -2478,10 +2469,12 @@ msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Кешірім өтінеміз, барлық орнатылған кеңейтулер тізімін алу мүмкін болмады. "
"GNOME ішіне кіргеніңізді тексеріп, қайталап көріңіз."
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
msgid "Extension Updates Ready"
msgstr ""
msgstr "Кеңейту жаңартулары дайын"
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
msgid "Log Out…"
@ -2491,7 +2484,7 @@ msgstr "Жүйеден шығу…"
#: subprojects/extensions-tool/src/command-create.c:226
#, c-format
msgid "The new extension was successfully created in %s.\n"
msgstr ""
msgstr "Жаңа кеңейту %s ішінде сәтті жасалды.\n"
#: subprojects/extensions-tool/src/command-create.c:299
#, c-format
@ -2499,11 +2492,13 @@ msgid ""
"Name should be a very short (ideally descriptive) string.\n"
"Examples are: %s"
msgstr ""
"Атауы қысқа мәтіндік жол (сипаттайтын) болуы тиіс.\n"
"Мысалы: %s"
#: subprojects/extensions-tool/src/command-create.c:305
#: subprojects/extensions-tool/src/main.c:238
msgid "Name"
msgstr "Атауы"
msgstr "Аты"
#: subprojects/extensions-tool/src/command-create.c:319
#, c-format
@ -2511,6 +2506,9 @@ msgid ""
"Description is a single-sentence explanation of what your extension does.\n"
"Examples are: %s"
msgstr ""
"Сипаттамасы - бұл сіздің кеңейтуіңіз жасайтын әрекеттің бір сөйлемді "
"анықтамасы.\n"
"Мысалы: %s"
#: subprojects/extensions-tool/src/command-create.c:339
msgid ""
@ -2518,10 +2516,12 @@ msgid ""
"This should be in the format of an email address (clicktofocus@janedoe."
"example.com)\n"
msgstr ""
"UUID - бұл кеңейтуңіздің глобалды деңгейдегі бірегей идентификаторы.\n"
"Ол эл. пошта адресі пішімінде болуы тиіс (clicktofocus@janedoe.example.com)\n"
#: subprojects/extensions-tool/src/command-create.c:366
msgid "Choose one of the available templates:\n"
msgstr ""
msgstr "Қол жетімді үлгілердің бірін таңдаңыз:\n"
#: subprojects/extensions-tool/src/command-create.c:380
msgid "Template"
@ -2529,7 +2529,7 @@ msgstr "Үлгі"
#: subprojects/extensions-tool/src/command-create.c:435
msgid "The unique identifier of the new extension"
msgstr ""
msgstr "Жаңа кеңейтудің бірегей идентификаторы"
#: subprojects/extensions-tool/src/command-create.c:438
msgid "NAME"
@ -2537,7 +2537,7 @@ msgstr "АТАУЫ"
#: subprojects/extensions-tool/src/command-create.c:439
msgid "The user-visible name of the new extension"
msgstr ""
msgstr "Жаңа кеңейтудің пайдаланушыға көрінетін атауы"
#: subprojects/extensions-tool/src/command-create.c:441
msgid "DESCRIPTION"
@ -2545,7 +2545,7 @@ msgstr "СИПАТТАМАСЫ"
#: subprojects/extensions-tool/src/command-create.c:443
msgid "A short description of what the extension does"
msgstr ""
msgstr "Кеңейтудің қысқаша сипаттамасы"
#: subprojects/extensions-tool/src/command-create.c:446
msgid "TEMPLATE"
@ -2553,11 +2553,11 @@ msgstr "ҮЛГІ"
#: subprojects/extensions-tool/src/command-create.c:447
msgid "The template to use for the new extension"
msgstr ""
msgstr "Жаңа кеңейту үшін қолданылатын үлгі"
#: subprojects/extensions-tool/src/command-create.c:453
msgid "Enter extension information interactively"
msgstr ""
msgstr "Кеңейту ақпаратын интерактивті түрде енгізу"
#: subprojects/extensions-tool/src/command-create.c:461
msgid "Create a new extension"
@ -2570,20 +2570,20 @@ msgstr "Белгісіз аргументтер"
#: subprojects/extensions-tool/src/command-create.c:504
msgid "UUID, name and description are required"
msgstr ""
msgstr "UUID, аты және сипаттамасы керек"
#: subprojects/extensions-tool/src/command-disable.c:46
#: subprojects/extensions-tool/src/command-enable.c:46
#: subprojects/extensions-tool/src/command-info.c:50
#: subprojects/extensions-tool/src/command-list.c:64
msgid "Failed to connect to GNOME Shell\n"
msgstr "GNOME Shell-ға байланысты орнату мүмкін емес\n"
msgstr "GNOME Shell-ға байланысты орнату сәтсіз аяқталды\n"
#: subprojects/extensions-tool/src/command-disable.c:53
#: subprojects/extensions-tool/src/command-enable.c:53
#, c-format
msgid "Extension “%s” does not exist\n"
msgstr ""
msgstr "\"%s\" кеңейтуі жоқ\n"
#: subprojects/extensions-tool/src/command-disable.c:101
msgid "Disable an extension"
@ -2605,7 +2605,7 @@ msgstr "UUID көрсетілмеген"
#: subprojects/extensions-tool/src/command-reset.c:81
#: subprojects/extensions-tool/src/command-uninstall.c:109
msgid "More than one UUID given"
msgstr ""
msgstr "Бірден көп UUID көрсетілген"
#: subprojects/extensions-tool/src/command-enable.c:101
msgid "Enable an extension"
@ -2615,7 +2615,7 @@ msgstr "Кеңейтуді іске қосу"
#: subprojects/extensions-tool/src/main.c:155
#, c-format
msgid "Extension “%s” doesn't exist\n"
msgstr ""
msgstr "\"%s\" кеңейтуі жоқ\n"
#: subprojects/extensions-tool/src/command-info.c:85
msgid "Show extensions info"
@ -2623,60 +2623,51 @@ msgstr "Кеңейтулер ақпаратын көрсету"
#: subprojects/extensions-tool/src/command-install.c:173
msgid "Overwrite an existing extension"
msgstr ""
msgstr "Бар болып тұрған кеңейтуді үстінен жазу"
#: subprojects/extensions-tool/src/command-install.c:175
msgid "EXTENSION_BUNDLE"
msgstr ""
msgstr "КЕҢЕЙТУЕСТЕСІ"
#: subprojects/extensions-tool/src/command-install.c:184
#| msgid "UUIDs of extensions to enable"
msgid "Install an extension bundle"
msgstr ""
msgstr "Кеңейту дестесін орнату"
#: subprojects/extensions-tool/src/command-install.c:202
#| msgid "No extensions installed"
msgid "No extension bundle specified"
msgstr ""
msgstr "Кеңейту дестесі көрсетілмеген"
#: subprojects/extensions-tool/src/command-install.c:208
msgid "More than one extension bundle specified"
msgstr ""
msgstr "Бірден көп кеңейту дестесі көрсетілген"
#: subprojects/extensions-tool/src/command-list.c:128
#| msgid "Shell Extensions"
msgid "Show user-installed extensions"
msgstr ""
msgstr "Пайдаланушы орнатқан кеңейтулерді көрсету"
#: subprojects/extensions-tool/src/command-list.c:131
#| msgid "Shell Extensions"
msgid "Show system-installed extensions"
msgstr ""
msgstr "Жүйелік деңгейде орнатылған кеңейтулерді көрсету"
#: subprojects/extensions-tool/src/command-list.c:134
#| msgid "Shell Extensions"
msgid "Show enabled extensions"
msgstr ""
msgstr "Іске қосылған кеңейтулерді көрсету"
#: subprojects/extensions-tool/src/command-list.c:137
#| msgid "Disable user extensions"
msgid "Show disabled extensions"
msgstr ""
msgstr "Сөндірілген кеңейтулерді көрсету"
#: subprojects/extensions-tool/src/command-list.c:140
#| msgid "GNOME Shell Extension Preferences"
msgid "Show extensions with preferences"
msgstr ""
msgstr "Баптаулары бар кеңейтулерді көрсету"
#: subprojects/extensions-tool/src/command-list.c:143
#| msgid "No extensions installed"
msgid "Show extensions with updates"
msgstr ""
msgstr "Жаңартулары бар кеңейтулерді көрсету"
#: subprojects/extensions-tool/src/command-list.c:146
#| msgid "Visit extension homepage"
msgid "Print extension details"
msgstr ""
msgstr "Кеңейту ақпаратын басып шығару"
#: subprojects/extensions-tool/src/command-list.c:154
msgid "List installed extensions"
@ -2688,7 +2679,7 @@ msgstr "ФАЙЛ"
#: subprojects/extensions-tool/src/command-pack.c:451
msgid "Additional source to include in the bundle"
msgstr ""
msgstr "Дестеге қосылатын қосымша қайнар көз"
#: subprojects/extensions-tool/src/command-pack.c:454
msgid "SCHEMA"
@ -2696,7 +2687,7 @@ msgstr "СҰЛБА"
#: subprojects/extensions-tool/src/command-pack.c:455
msgid "A GSettings schema that should be included"
msgstr ""
msgstr "Құрамына енуі тиіс GSettings сұлбасы"
#: subprojects/extensions-tool/src/command-pack.c:457
#: subprojects/extensions-tool/src/command-pack.c:468
@ -2705,7 +2696,7 @@ msgstr "БУМА"
#: subprojects/extensions-tool/src/command-pack.c:459
msgid "The directory where translations are found"
msgstr ""
msgstr "Аудармалар орналасқан бума"
#: subprojects/extensions-tool/src/command-pack.c:461
msgid "DOMAIN"
@ -2713,37 +2704,37 @@ msgstr "ДОМЕН"
#: subprojects/extensions-tool/src/command-pack.c:463
msgid "The gettext domain to use for translations"
msgstr ""
msgstr "Аудармалар үшін қолданылуы тиіс gettext домені"
#: subprojects/extensions-tool/src/command-pack.c:466
msgid "Overwrite an existing pack"
msgstr ""
msgstr "Бар болып тұрған пакетті үстінен жазу"
#: subprojects/extensions-tool/src/command-pack.c:470
msgid "The directory where the pack should be created"
msgstr ""
msgstr "Десте жасалуы тиіс бума"
#: subprojects/extensions-tool/src/command-pack.c:472
msgid "SOURCE_DIRECTORY"
msgstr ""
msgstr "ҚАЙНАР_КӨЗУМАСЫ"
#: subprojects/extensions-tool/src/command-pack.c:481
msgid "Create an extension bundle"
msgstr ""
msgstr "Кеңейту дестесін жасау"
#: subprojects/extensions-tool/src/command-pack.c:501
msgid "More than one source directory specified"
msgstr ""
msgstr "Бірден көп қайнар көз бумасы көрсетілген"
#: subprojects/extensions-tool/src/command-prefs.c:47
#, c-format
#| msgid "Show extensions with preferences"
msgid "Extension “%s” doesn't have preferences\n"
msgstr ""
msgstr "\"%s\" кеңейтудің баптаулары жоқ\n"
#: subprojects/extensions-tool/src/command-prefs.c:79
#| msgid "GNOME Shell Extension Preferences"
msgid "Opens extension preferences"
msgstr ""
msgstr "Кеңейту баптауларын ашады"
#: subprojects/extensions-tool/src/command-reset.c:58
msgid "Reset an extension"
@ -2764,11 +2755,11 @@ msgstr "Кеңейтуді өшіру"
#: subprojects/extensions-tool/src/main.c:72
msgid "Do not print error messages"
msgstr ""
msgstr "Қате туралы хабарламаларды басып шығармау"
#: subprojects/extensions-tool/src/main.c:146
msgid "Failed to connect to GNOME Shell"
msgstr "GNOME Shell-ға байланысты орнату мүмкін емес"
msgstr "GNOME Shell-ға байланысты орнату сәтсіз аяқталды"
#: subprojects/extensions-tool/src/main.c:244
msgid "Path"
@ -2788,7 +2779,7 @@ msgstr "Қалып-күйі"
#: subprojects/extensions-tool/src/main.c:290
msgid "“version” takes no arguments"
msgstr ""
msgstr "“version” аргументтерді қабылдамайды"
#: subprojects/extensions-tool/src/main.c:292
#: subprojects/extensions-tool/src/main.c:312
@ -2860,11 +2851,11 @@ msgstr "Кеңейту дестесін орнату"
#: subprojects/extensions-tool/src/main.c:330
#, c-format
msgid "Use “%s” to get detailed help.\n"
msgstr ""
msgstr "Толық көмекті алу үшін \"%s\" пайдаланыңыз.\n"
#: subprojects/extensions-tool/src/templates/00-plain.desktop.in:4
msgid "Plain"
msgstr "Кәдімгі"
msgstr "Қалыпты"
#: subprojects/extensions-tool/src/templates/00-plain.desktop.in:5
msgid "An empty extension"
@ -2876,7 +2867,7 @@ msgstr "Индикатор"
#: subprojects/extensions-tool/src/templates/indicator.desktop.in:5
msgid "Add an icon to the top bar"
msgstr ""
msgstr "Жоғарғы панельге таңбашаны қосу"
#. translators:
#. * The number of sound outputs on a particular device
@ -2898,6 +2889,33 @@ msgstr[0] "%u кірісі"
msgid "System Sounds"
msgstr "Жүйелік дыбыстар"
#~ msgid "Frequently used applications will appear here"
#~ msgstr "Жиі қолданылатын қолданбалар осында көрінеді"
#~ msgid "Frequent"
#~ msgstr "Жиі қолданылатын"
#~ msgid "All"
#~ msgstr "Барлығы"
#~ msgctxt "calendar heading"
#~ msgid "%A, %B %-d"
#~ msgstr "%A, %B %-d"
#~ msgctxt "calendar heading"
#~ msgid "%A, %B %-d, %Y"
#~ msgstr "%A, %B %-d, %Y"
#~ msgid "%d Connected"
#~ msgid_plural "%d Connected"
#~ msgstr[0] "%d байланысқан"
#~ msgid "Off"
#~ msgstr "Сөнд."
#~ msgid "On"
#~ msgstr "Іске қос."
#~ msgid ""
#~ "Keybinding that pauses and resumes all running tweens, for debugging "
#~ "purposes"
@ -2927,21 +2945,6 @@ msgstr "Жүйелік дыбыстар"
#~ msgid "Sign In"
#~ msgstr "Кіру"
#~ msgid "Frequently used applications will appear here"
#~ msgstr "Жиі қолданылатын қолданбалар осында көрінеді"
#~ msgid "Frequent"
#~ msgstr "Жиі қолданылатын"
#~ msgid "All"
#~ msgstr "Барлығы"
#~| msgctxt "calendar heading"
#~| msgid "%A, %B %d, %Y"
#~ msgctxt "calendar heading"
#~ msgid "%A, %B %-d, %Y"
#~ msgstr "%A, %B %-d, %Y"
#~ msgid "Password:"
#~ msgstr "Пароль:"
@ -2971,16 +2974,6 @@ msgstr "Жүйелік дыбыстар"
#~ msgid_plural "%d new notifications"
#~ msgstr[0] "%d жаңа ескерту"
#~ msgid "%d Connected"
#~ msgid_plural "%d Connected"
#~ msgstr[0] "%d байланысқан"
#~ msgid "Off"
#~ msgstr "Сөнд."
#~ msgid "On"
#~ msgstr "Іске қос."
#~ msgid "Account Settings"
#~ msgstr "Тіркелгі баптаулары"

872
po/lt.po

File diff suppressed because it is too large Load Diff

941
po/lv.po

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,7 @@ struct _ShellApp
* want (e.g. it will be of TYPE_NORMAL from
* the way shell-window-tracker.c works).
*/
GIcon *fallback_icon;
ShellAppRunningState *running_state;
@ -180,66 +181,47 @@ window_backed_app_get_window (ShellApp *app)
return NULL;
}
static ClutterActor *
window_backed_app_get_icon (ShellApp *app,
int size)
/**
* shell_app_get_icon:
*
* Look up the icon for this application
*
* Return value: (transfer none): A #GIcon
*/
GIcon *
shell_app_get_icon (ShellApp *app)
{
MetaWindow *window = NULL;
StWidget *widget;
int scale, scaled_size;
ShellGlobal *global;
StThemeContext *context;
global = shell_global_get ();
context = st_theme_context_get_for_stage (shell_global_get_stage (global));
g_object_get (context, "scale-factor", &scale, NULL);
g_return_val_if_fail (SHELL_IS_APP (app), NULL);
scaled_size = size * scale;
if (app->info)
return g_app_info_get_icon (G_APP_INFO (app->info));
if (app->fallback_icon)
return app->fallback_icon;
/* During a state transition from running to not-running for
* window-backend apps, it's possible we get a request for the icon.
* Avoid asserting here and just return an empty image.
* Avoid asserting here and just return a fallback icon
*/
if (app->running_state != NULL)
window = window_backed_app_get_window (app);
if (window == NULL)
if (window &&
meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_X11)
{
ClutterActor *actor;
actor = clutter_actor_new ();
g_object_set (actor,
"opacity", 0,
"width", (float) scaled_size,
"height", (float) scaled_size,
NULL);
return actor;
}
if (meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_X11)
{
StWidget *texture_actor;
texture_actor =
app->fallback_icon =
st_texture_cache_bind_cairo_surface_property (st_texture_cache_get_default (),
G_OBJECT (window),
"icon",
scaled_size);
widget = g_object_new (ST_TYPE_BIN,
"child", texture_actor,
NULL);
"icon");
}
else
{
widget = g_object_new (ST_TYPE_ICON,
"icon-size", size,
"icon-name", "application-x-executable",
NULL);
app->fallback_icon = g_themed_icon_new ("application-x-executable");
}
st_widget_add_style_class_name (widget, "fallback-app-icon");
return CLUTTER_ACTOR (widget);
return app->fallback_icon;
}
/**
@ -257,16 +239,16 @@ shell_app_create_icon_texture (ShellApp *app,
GIcon *icon;
ClutterActor *ret;
if (app->info == NULL)
return window_backed_app_get_icon (app, size);
ret = st_icon_new ();
st_icon_set_icon_size (ST_ICON (ret), size);
st_icon_set_fallback_icon_name (ST_ICON (ret), "application-x-executable");
icon = g_app_info_get_icon (G_APP_INFO (app->info));
icon = shell_app_get_icon (app);
st_icon_set_gicon (ST_ICON (ret), icon);
if (shell_app_is_window_backed (app))
st_widget_add_style_class_name (ST_WIDGET (ret), "fallback-app-icon");
return ret;
}
@ -1576,6 +1558,7 @@ shell_app_dispose (GObject *object)
ShellApp *app = SHELL_APP (object);
g_clear_object (&app->info);
g_clear_object (&app->fallback_icon);
while (app->running_state)
_shell_app_remove_window (app, app->running_state->windows->data);

View File

@ -29,6 +29,7 @@ const char *shell_app_get_id (ShellApp *app);
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
GIcon *shell_app_get_icon (ShellApp *app);
const char *shell_app_get_name (ShellApp *app);
const char *shell_app_get_description (ShellApp *app);
gboolean shell_app_is_window_backed (ShellApp *app);

View File

@ -899,8 +899,9 @@ load_gl_symbol (const char *name,
}
static void
global_stage_after_paint (ClutterStage *stage,
ShellGlobal *global)
global_stage_after_paint (ClutterStage *stage,
ClutterStageView *stage_view,
ShellGlobal *global)
{
/* At this point, we've finished all layout and painting, but haven't
* actually flushed or swapped */

View File

@ -508,9 +508,7 @@ recorder_update_size (ShellRecorder *recorder)
}
static void
recorder_on_stage_notify_size (GObject *object,
GParamSpec *pspec,
ShellRecorder *recorder)
recorder_on_stage_notify_size (ShellRecorder *recorder)
{
recorder_update_size (recorder);
@ -614,12 +612,15 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
G_CALLBACK (recorder_on_stage_destroy), recorder);
g_signal_connect_after (recorder->stage, "paint",
G_CALLBACK (recorder_on_stage_paint), recorder);
g_signal_connect (recorder->stage, "notify::width",
G_CALLBACK (recorder_on_stage_notify_size), recorder);
g_signal_connect (recorder->stage, "notify::height",
G_CALLBACK (recorder_on_stage_notify_size), recorder);
g_signal_connect (recorder->stage, "notify::resource-scale",
G_CALLBACK (recorder_on_stage_notify_size), recorder);
g_signal_connect_swapped (recorder->stage, "notify::width",
G_CALLBACK (recorder_on_stage_notify_size),
recorder);
g_signal_connect_swapped (recorder->stage, "notify::height",
G_CALLBACK (recorder_on_stage_notify_size),
recorder);
g_signal_connect_swapped (recorder->stage, "resource-scale-changed",
G_CALLBACK (recorder_on_stage_notify_size),
recorder);
}
static void

View File

@ -393,8 +393,7 @@ grab_window_screenshot (ClutterActor *stage,
if (meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
float resource_scale;
if (!clutter_actor_get_resource_scale (window_actor, &resource_scale))
resource_scale = 1.0f;
resource_scale = clutter_actor_get_resource_scale (window_actor);
cairo_surface_set_device_scale (priv->image, resource_scale, resource_scale);
}

View File

@ -119,6 +119,16 @@ shell_window_tracker_class_init (ShellWindowTrackerClass *klass)
G_TYPE_NONE, 0);
}
static gboolean
check_app_id_prefix (ShellApp *app,
const char *prefix)
{
if (prefix == NULL)
return TRUE;
return g_str_has_prefix (shell_app_get_id (app), prefix);
}
/*
* get_app_from_window_wmclass:
*
@ -135,8 +145,10 @@ get_app_from_window_wmclass (MetaWindow *window)
ShellAppSystem *appsys;
const char *wm_class;
const char *wm_instance;
const char *sandbox_id;
appsys = shell_app_system_get_default ();
sandbox_id = meta_window_get_sandboxed_app_id (window);
/* Notes on the heuristics used here:
much of the complexity here comes from the desire to support
@ -176,23 +188,23 @@ get_app_from_window_wmclass (MetaWindow *window)
/* first try a match from WM_CLASS (instance part) to StartupWMClass */
wm_instance = meta_window_get_wm_class_instance (window);
app = shell_app_system_lookup_startup_wmclass (appsys, wm_instance);
if (app != NULL)
if (app != NULL && check_app_id_prefix (app, sandbox_id))
return g_object_ref (app);
/* then try a match from WM_CLASS to StartupWMClass */
wm_class = meta_window_get_wm_class (window);
app = shell_app_system_lookup_startup_wmclass (appsys, wm_class);
if (app != NULL)
if (app != NULL && check_app_id_prefix (app, sandbox_id))
return g_object_ref (app);
/* then try a match from WM_CLASS (instance part) to .desktop */
app = shell_app_system_lookup_desktop_wmclass (appsys, wm_instance);
if (app != NULL)
if (app != NULL && check_app_id_prefix (app, sandbox_id))
return g_object_ref (app);
/* finally, try a match from WM_CLASS to .desktop */
app = shell_app_system_lookup_desktop_wmclass (appsys, wm_class);
if (app != NULL)
if (app != NULL && check_app_id_prefix (app, sandbox_id))
return g_object_ref (app);
return NULL;
@ -214,7 +226,7 @@ get_app_from_id (MetaWindow *window,
{
ShellApp *app;
ShellAppSystem *appsys;
char *desktop_file;
g_autofree char *desktop_file = NULL;
g_return_val_if_fail (id != NULL, NULL);
@ -223,10 +235,9 @@ get_app_from_id (MetaWindow *window,
desktop_file = g_strconcat (id, ".desktop", NULL);
app = shell_app_system_lookup_app (appsys, desktop_file);
if (app)
g_object_ref (app);
return g_object_ref (app);
g_free (desktop_file);
return app;
return NULL;
}
/*
@ -391,6 +402,13 @@ get_app_for_window (ShellWindowTracker *tracker,
if (meta_window_is_remote (window))
return _shell_app_new_for_window (window);
/* Check if the app's WM_CLASS specifies an app; this is
* canonical if it does.
*/
result = get_app_from_window_wmclass (window);
if (result != NULL)
return result;
/* Check if the window was opened from within a sandbox; if this
* is the case, a corresponding .desktop file is guaranteed to match;
*/
@ -405,13 +423,6 @@ get_app_for_window (ShellWindowTracker *tracker,
if (result != NULL)
return result;
/* Check if the app's WM_CLASS specifies an app; this is
* canonical if it does.
*/
result = get_app_from_window_wmclass (window);
if (result != NULL)
return result;
result = get_app_from_window_pid (tracker, window);
if (result != NULL)
return result;

View File

@ -41,6 +41,8 @@ typedef struct _StAdjustmentPrivate StAdjustmentPrivate;
struct _StAdjustmentPrivate
{
ClutterActor *actor;
/* Do not sanity-check values while constructing,
* not all properties may be set yet. */
guint is_constructing : 1;
@ -66,6 +68,7 @@ enum
{
PROP_0,
PROP_ACTOR,
PROP_LOWER,
PROP_UPPER,
PROP_VALUE,
@ -106,9 +109,21 @@ static gboolean st_adjustment_set_page_increment (StAdjustment *adjustment,
static gboolean st_adjustment_set_page_size (StAdjustment *adjustment,
gdouble size);
static ClutterActor *
st_adjustment_get_actor (ClutterAnimatable *animatable)
{
StAdjustment *adjustment = ST_ADJUSTMENT (animatable);
StAdjustmentPrivate *priv = st_adjustment_get_instance_private (adjustment);
g_warn_if_fail (priv->actor);
return priv->actor;
}
static void
animatable_iface_init (ClutterAnimatableInterface *iface)
{
iface->get_actor = st_adjustment_get_actor;
}
static void
@ -141,6 +156,10 @@ st_adjustment_get_property (GObject *gobject,
switch (prop_id)
{
case PROP_ACTOR:
g_value_set_object (value, priv->actor);
break;
case PROP_LOWER:
g_value_set_double (value, priv->lower);
break;
@ -171,6 +190,18 @@ st_adjustment_get_property (GObject *gobject,
}
}
static void
actor_destroyed (gpointer user_data,
GObject *where_the_object_was)
{
StAdjustment *adj = ST_ADJUSTMENT (user_data);
StAdjustmentPrivate *priv = st_adjustment_get_instance_private (adj);
priv->actor = NULL;
g_object_notify_by_pspec (G_OBJECT (adj), props[PROP_ACTOR]);
}
static void
st_adjustment_set_property (GObject *gobject,
guint prop_id,
@ -178,9 +209,20 @@ st_adjustment_set_property (GObject *gobject,
GParamSpec *pspec)
{
StAdjustment *adj = ST_ADJUSTMENT (gobject);
StAdjustmentPrivate *priv;
priv = st_adjustment_get_instance_private (ST_ADJUSTMENT (gobject));
switch (prop_id)
{
case PROP_ACTOR:
if (priv->actor)
g_object_weak_unref (G_OBJECT (priv->actor), actor_destroyed, adj);
priv->actor = g_value_get_object (value);
if (priv->actor)
g_object_weak_ref (G_OBJECT (priv->actor), actor_destroyed, adj);
break;
case PROP_LOWER:
st_adjustment_set_lower (adj, g_value_get_double (value));
break;
@ -217,6 +259,11 @@ st_adjustment_dispose (GObject *object)
StAdjustmentPrivate *priv;
priv = st_adjustment_get_instance_private (ST_ADJUSTMENT (object));
if (priv->actor)
{
g_object_weak_unref (G_OBJECT (priv->actor), actor_destroyed, object);
priv->actor = NULL;
}
g_clear_pointer (&priv->transitions, g_hash_table_unref);
G_OBJECT_CLASS (st_adjustment_parent_class)->dispose (object);
@ -232,6 +279,11 @@ st_adjustment_class_init (StAdjustmentClass *klass)
object_class->set_property = st_adjustment_set_property;
object_class->dispose = st_adjustment_dispose;
props[PROP_ACTOR] =
g_param_spec_object ("actor", "Actor", "Actor",
CLUTTER_TYPE_ACTOR,
ST_PARAM_READWRITE);
props[PROP_LOWER] =
g_param_spec_double ("lower", "Lower", "Lower bound",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
@ -299,7 +351,8 @@ st_adjustment_init (StAdjustment *self)
}
StAdjustment *
st_adjustment_new (gdouble value,
st_adjustment_new (ClutterActor *actor,
gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,
@ -307,6 +360,7 @@ st_adjustment_new (gdouble value,
gdouble page_size)
{
return g_object_new (ST_TYPE_ADJUSTMENT,
"actor", actor,
"value", value,
"lower", lower,
"upper", upper,

View File

@ -48,7 +48,8 @@ struct _StAdjustmentClass
void (* changed) (StAdjustment *adjustment);
};
StAdjustment *st_adjustment_new (gdouble value,
StAdjustment *st_adjustment_new (ClutterActor *actor,
gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,

View File

@ -85,12 +85,7 @@ st_drawing_area_allocate (ClutterActor *self,
int width, height;
float resource_scale;
if (!st_widget_get_resource_scale (ST_WIDGET (self), &resource_scale))
{
ClutterActorBox empty = CLUTTER_ACTOR_BOX_INIT_ZERO;
clutter_actor_set_allocation (self, &empty);
return;
}
resource_scale = clutter_actor_get_resource_scale (self);
clutter_actor_set_allocation (self, box);
st_theme_node_get_content_box (theme_node, box, &content_box);
@ -111,13 +106,16 @@ st_drawing_area_style_changed (StWidget *self)
}
static void
st_drawing_area_resource_scale_changed (StWidget *self)
st_drawing_area_resource_scale_changed (ClutterActor *self)
{
float resource_scale;
ClutterContent *content = clutter_actor_get_content (CLUTTER_ACTOR (self));
ClutterContent *content = clutter_actor_get_content (self);
if (st_widget_get_resource_scale (ST_WIDGET (self), &resource_scale))
clutter_canvas_set_scale_factor (CLUTTER_CANVAS (content), resource_scale);
resource_scale = clutter_actor_get_resource_scale (self);
clutter_canvas_set_scale_factor (CLUTTER_CANVAS (content), resource_scale);
if (CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class)->resource_scale_changed)
CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class)->resource_scale_changed (self);
}
static void
@ -128,7 +126,7 @@ st_drawing_area_class_init (StDrawingAreaClass *klass)
actor_class->allocate = st_drawing_area_allocate;
widget_class->style_changed = st_drawing_area_style_changed;
widget_class->resource_scale_changed = st_drawing_area_resource_scale_changed;
actor_class->resource_scale_changed = st_drawing_area_resource_scale_changed;
st_drawing_area_signals[REPAINT] =
g_signal_new ("repaint",
@ -215,15 +213,10 @@ st_drawing_area_get_surface_size (StDrawingArea *area,
content = clutter_actor_get_content (CLUTTER_ACTOR (area));
clutter_content_get_preferred_size (content, &w, &h);
if (st_widget_get_resource_scale (ST_WIDGET (area), &resource_scale))
{
w /= resource_scale;
h /= resource_scale;
}
else
{
w = h = 0.0f;
}
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (area));
w /= resource_scale;
h /= resource_scale;
if (width)
*width = ceilf (w);

View File

@ -231,9 +231,12 @@ st_icon_style_changed (StWidget *widget)
}
static void
st_icon_resource_scale_changed (StWidget *widget)
st_icon_resource_scale_changed (ClutterActor *actor)
{
st_icon_update (ST_ICON (widget));
st_icon_update (ST_ICON (actor));
if (CLUTTER_ACTOR_CLASS (st_icon_parent_class)->resource_scale_changed)
CLUTTER_ACTOR_CLASS (st_icon_parent_class)->resource_scale_changed (actor);
}
static void
@ -250,7 +253,7 @@ st_icon_class_init (StIconClass *klass)
actor_class->paint = st_icon_paint;
widget_class->style_changed = st_icon_style_changed;
widget_class->resource_scale_changed = st_icon_resource_scale_changed;
actor_class->resource_scale_changed = st_icon_resource_scale_changed;
props[PROP_GICON] =
g_param_spec_object ("gicon",
@ -425,8 +428,7 @@ st_icon_update (StIcon *icon)
return;
}
if (!st_widget_get_resource_scale (ST_WIDGET (icon), &resource_scale))
return;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (icon));
theme_node = st_widget_peek_theme_node (ST_WIDGET (icon));
if (theme_node == NULL)

View File

@ -42,11 +42,17 @@ enum
};
static void clutter_content_interface_init (ClutterContentInterface *iface);
static void g_icon_interface_init (GIconIface *iface);
static void g_loadable_icon_interface_init (GLoadableIconIface *iface);
G_DEFINE_TYPE_WITH_CODE (StImageContent, st_image_content, CLUTTER_TYPE_IMAGE,
G_ADD_PRIVATE (StImageContent)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
clutter_content_interface_init))
clutter_content_interface_init)
G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
g_icon_interface_init)
G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON,
g_loadable_icon_interface_init))
static void
st_image_content_init (StImageContent *self)
@ -165,12 +171,157 @@ st_image_content_get_preferred_size (ClutterContent *content,
return TRUE;
}
static GdkPixbuf*
pixbuf_from_image (StImageContent *image)
{
CoglTexture *texture;
int width, height, rowstride;
uint8_t *data;
texture = clutter_image_get_texture (CLUTTER_IMAGE (image));
if (!texture || !cogl_texture_is_get_data_supported (texture))
return NULL;
width = cogl_texture_get_width (texture);
height = cogl_texture_get_width (texture);
rowstride = 4 * width;
data = g_new (uint8_t, rowstride * height);
cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_RGBA_8888, rowstride, data);
return gdk_pixbuf_new_from_data ((const guchar *)data,
GDK_COLORSPACE_RGB,
TRUE, 8, width, height, rowstride,
(GdkPixbufDestroyNotify)g_free, NULL);
}
static void
clutter_content_interface_init (ClutterContentInterface *iface)
{
iface->get_preferred_size = st_image_content_get_preferred_size;
}
static guint
st_image_content_hash (GIcon *icon)
{
return g_direct_hash (icon);
}
static gboolean
st_image_content_equal (GIcon *icon1,
GIcon *icon2)
{
return g_direct_equal (icon1, icon2);
}
static GVariant *
st_image_content_serialize (GIcon *icon)
{
g_autoptr (GdkPixbuf) pixbuf = NULL;
pixbuf = pixbuf_from_image (ST_IMAGE_CONTENT (icon));
if (!pixbuf)
return NULL;
return g_icon_serialize (G_ICON (pixbuf));
}
static void
g_icon_interface_init (GIconIface *iface)
{
iface->hash = st_image_content_hash;
iface->equal = st_image_content_equal;
iface->serialize = st_image_content_serialize;
}
static GInputStream *
st_image_load (GLoadableIcon *icon,
int size,
char **type,
GCancellable *cancellable,
GError **error)
{
g_autoptr (GdkPixbuf) pixbuf = NULL;
pixbuf = pixbuf_from_image (ST_IMAGE_CONTENT (icon));
if (!pixbuf)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to read texture");
return NULL;
}
return g_loadable_icon_load (G_LOADABLE_ICON (pixbuf),
size, type, cancellable, error);
}
static void
load_image_thread (GTask *task,
gpointer object,
gpointer task_data,
GCancellable *cancellable)
{
GInputStream *stream;
GError *error = NULL;
char *type;
stream = st_image_load (G_LOADABLE_ICON (object),
GPOINTER_TO_INT (task_data),
&type,
cancellable,
&error);
if (error)
{
g_task_return_error (task, error);
}
else
{
g_task_set_task_data (task, type, g_free);
g_task_return_pointer (task, stream, g_object_unref);
}
}
static void
st_image_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr (GTask) task = NULL;
task = g_task_new (icon, cancellable, callback, user_data);
g_task_set_task_data (task, GINT_TO_POINTER (size), NULL);
g_task_run_in_thread (task, load_image_thread);
}
static GInputStream *
st_image_load_finish (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error)
{
GInputStream *stream;
stream = g_task_propagate_pointer (G_TASK (res), error);
if (!stream)
return NULL;
if (type)
*type = g_strdup (g_task_get_task_data (G_TASK (res)));
return stream;
}
static void
g_loadable_icon_interface_init (GLoadableIconIface *iface)
{
iface->load = st_image_load;
iface->load_async = st_image_load_async;
iface->load_finish = st_image_load_finish;
}
/**
* st_image_content_new_with_preferred_size:
* @width: The preferred width to be used when drawing the content

View File

@ -201,44 +201,42 @@ st_label_paint (ClutterActor *actor,
if (shadow_spec)
{
ClutterActorBox allocation;
float width, height;
float resource_scale;
if (clutter_actor_get_resource_scale (priv->label, &resource_scale))
clutter_actor_get_allocation_box (priv->label, &allocation);
clutter_actor_box_get_size (&allocation, &width, &height);
resource_scale = clutter_actor_get_resource_scale (priv->label);
width *= resource_scale;
height *= resource_scale;
if (priv->text_shadow_pipeline == NULL ||
width != priv->shadow_width ||
height != priv->shadow_height)
{
ClutterActorBox allocation;
float width, height;
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
clutter_actor_get_allocation_box (priv->label, &allocation);
clutter_actor_box_get_size (&allocation, &width, &height);
priv->shadow_width = width;
priv->shadow_height = height;
priv->text_shadow_pipeline =
_st_create_shadow_pipeline_from_actor (shadow_spec,
priv->label);
}
width *= resource_scale;
height *= resource_scale;
if (priv->text_shadow_pipeline != NULL)
{
CoglFramebuffer *framebuffer;
if (priv->text_shadow_pipeline == NULL ||
width != priv->shadow_width ||
height != priv->shadow_height)
{
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
priv->shadow_width = width;
priv->shadow_height = height;
priv->text_shadow_pipeline =
_st_create_shadow_pipeline_from_actor (shadow_spec,
priv->label);
}
if (priv->text_shadow_pipeline != NULL)
{
CoglFramebuffer *framebuffer;
framebuffer =
clutter_paint_context_get_framebuffer (paint_context);
_st_paint_shadow_with_opacity (shadow_spec,
framebuffer,
priv->text_shadow_pipeline,
&allocation,
clutter_actor_get_paint_opacity (priv->label));
}
framebuffer =
clutter_paint_context_get_framebuffer (paint_context);
_st_paint_shadow_with_opacity (shadow_spec,
framebuffer,
priv->text_shadow_pipeline,
&allocation,
clutter_actor_get_paint_opacity (priv->label));
}
}
@ -246,11 +244,14 @@ st_label_paint (ClutterActor *actor,
}
static void
st_label_resource_scale_changed (StWidget *widget)
st_label_resource_scale_changed (ClutterActor *actor)
{
StLabelPrivate *priv = ST_LABEL (widget)->priv;
StLabelPrivate *priv = ST_LABEL (actor)->priv;
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
if (CLUTTER_ACTOR_CLASS (st_label_parent_class)->resource_scale_changed)
CLUTTER_ACTOR_CLASS (st_label_parent_class)->resource_scale_changed (actor);
}
static void
@ -268,9 +269,9 @@ st_label_class_init (StLabelClass *klass)
actor_class->allocate = st_label_allocate;
actor_class->get_preferred_width = st_label_get_preferred_width;
actor_class->get_preferred_height = st_label_get_preferred_height;
actor_class->resource_scale_changed = st_label_resource_scale_changed;
widget_class->style_changed = st_label_style_changed;
widget_class->resource_scale_changed = st_label_resource_scale_changed;
widget_class->get_accessible_type = st_label_accessible_get_type;
props[PROP_CLUTTER_TEXT] =
@ -293,6 +294,7 @@ st_label_class_init (StLabelClass *klass)
static void
st_label_init (StLabel *label)
{
ClutterActor *actor = CLUTTER_ACTOR (label);
StLabelPrivate *priv;
label->priv = priv = st_label_get_instance_private (label);
@ -304,7 +306,10 @@ st_label_init (StLabel *label)
label->priv->shadow_width = -1.;
label->priv->shadow_height = -1.;
clutter_actor_add_child (CLUTTER_ACTOR (label), priv->label);
clutter_actor_add_child (actor, priv->label);
clutter_actor_set_offscreen_redirect (actor,
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS);
}
/**

View File

@ -461,8 +461,7 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
if (width == 0 || height == 0)
return NULL;
if (!clutter_actor_get_resource_scale (actor, &resource_scale))
return NULL;
resource_scale = clutter_actor_get_resource_scale (actor);
width = ceilf (width * resource_scale);
height = ceilf (height * resource_scale);

View File

@ -899,13 +899,17 @@ st_scroll_view_init (StScrollView *self)
priv->hscrollbar_policy = ST_POLICY_AUTOMATIC;
priv->vscrollbar_policy = ST_POLICY_AUTOMATIC;
priv->hadjustment = g_object_new (ST_TYPE_ADJUSTMENT, NULL);
priv->hadjustment = g_object_new (ST_TYPE_ADJUSTMENT,
"actor", self,
NULL);
priv->hscroll = g_object_new (ST_TYPE_SCROLL_BAR,
"adjustment", priv->hadjustment,
"vertical", FALSE,
NULL);
priv->vadjustment = g_object_new (ST_TYPE_ADJUSTMENT, NULL);
priv->vadjustment = g_object_new (ST_TYPE_ADJUSTMENT,
"actor", self,
NULL);
priv->vscroll = g_object_new (ST_TYPE_SCROLL_BAR,
"adjustment", priv->vadjustment,
"vertical", TRUE,

View File

@ -722,8 +722,7 @@ load_texture_async (StTextureCache *cache,
typedef struct {
StTextureCache *cache;
ClutterActor *actor;
gint size;
ClutterContent *image;
GObject *source;
gulong notify_signal_id;
gboolean weakref_active;
@ -742,37 +741,33 @@ st_texture_cache_reset_texture (StTextureCachePropertyBind *bind,
(cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32 ||
cairo_image_surface_get_format (surface) == CAIRO_FORMAT_RGB24))
{
g_autoptr(ClutterContent) image = NULL;
g_autoptr(GError) error = NULL;
int size = bind->size;
int width, height, size;
if (size < 0)
clutter_actor_get_preferred_width (bind->actor, -1, NULL, (float *)&size);
width = cairo_image_surface_get_width (surface);
height = cairo_image_surface_get_width (surface);
size = MAX(width, height);
image = clutter_actor_get_content (bind->actor);
if (!image || !CLUTTER_IS_IMAGE (image))
image = st_image_content_new_with_preferred_size (size, size);
else
g_object_ref (image);
if (!bind->image)
bind->image = st_image_content_new_with_preferred_size (size, size);
clutter_image_set_data (CLUTTER_IMAGE (image),
clutter_image_set_data (CLUTTER_IMAGE (bind->image),
cairo_image_surface_get_data (surface),
cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32 ?
COGL_PIXEL_FORMAT_BGRA_8888 : COGL_PIXEL_FORMAT_BGR_888,
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
width,
height,
cairo_image_surface_get_stride (surface),
&error);
if (image)
clutter_actor_set_content (bind->actor, image);
else if (error)
if (error)
g_warning ("Failed to allocate texture: %s", error->message);
clutter_actor_set_opacity (bind->actor, 255);
}
else
clutter_actor_set_opacity (bind->actor, 0);
bind->image = g_object_new (ST_TYPE_IMAGE_CONTENT,
"preferred-width", 0, /* tough luck */
"preferred-height", 0,
NULL);
}
static void
@ -798,57 +793,48 @@ st_texture_cache_free_bind (gpointer data)
{
StTextureCachePropertyBind *bind = data;
if (bind->weakref_active)
g_object_weak_unref (G_OBJECT (bind->actor), st_texture_cache_bind_weak_notify, bind);
g_object_weak_unref (G_OBJECT (bind->image), st_texture_cache_bind_weak_notify, bind);
g_slice_free (StTextureCachePropertyBind, bind);
}
/**
* st_texture_cache_bind_cairo_surface_property:
* @cache:
* @object: A #GObject with a property @property_name of type #GdkPixbuf
* @object: A #GObject with a property @property_name of type #cairo_surface_t
* @property_name: Name of a property
*
* Create a #ClutterActor which tracks the #cairo_surface_t value of a GObject property
* Create a #GIcon which tracks the #cairo_surface_t value of a GObject property
* named by @property_name. Unlike other methods in StTextureCache, the underlying
* #CoglTexture is not shared by default with other invocations to this method.
*
* If the source object is destroyed, the texture will continue to show the last
* value of the property.
*
* Return value: (transfer none): A new #StWidget
* Return value: (transfer none): A new #GIcon
*/
StWidget *
GIcon *
st_texture_cache_bind_cairo_surface_property (StTextureCache *cache,
GObject *object,
const char *property_name,
gint size)
const char *property_name)
{
StWidget *widget;
gchar *notify_key;
StTextureCachePropertyBind *bind;
widget = g_object_new (ST_TYPE_WIDGET,
"opacity", 0,
"width", (float)size,
"height", (float)size,
NULL);
bind = g_slice_new0 (StTextureCachePropertyBind);
bind->cache = cache;
bind->actor = CLUTTER_ACTOR (widget);
bind->size = size;
bind->source = object;
g_object_weak_ref (G_OBJECT (widget), st_texture_cache_bind_weak_notify, bind);
bind->weakref_active = TRUE;
st_texture_cache_reset_texture (bind, property_name);
g_object_weak_ref (G_OBJECT (bind->image), st_texture_cache_bind_weak_notify, bind);
bind->weakref_active = TRUE;
notify_key = g_strdup_printf ("notify::%s", property_name);
bind->notify_signal_id = g_signal_connect_data (object, notify_key, G_CALLBACK(st_texture_cache_on_pixbuf_notify),
bind, (GClosureNotify)st_texture_cache_free_bind, 0);
g_free (notify_key);
return widget;
return G_ICON (bind->image);
}
/**
@ -981,6 +967,18 @@ st_texture_cache_load_gicon (StTextureCache *cache,
StIconStyle icon_style = ST_ICON_STYLE_REQUESTED;
GtkIconLookupFlags lookup_flags;
actor_size = size * paint_scale;
if (ST_IS_IMAGE_CONTENT (icon))
{
return g_object_new (CLUTTER_TYPE_ACTOR,
"request-mode", CLUTTER_REQUEST_CONTENT_SIZE,
"width", actor_size,
"height", actor_size,
"content", CLUTTER_CONTENT (icon),
NULL);
}
if (theme_node)
{
colors = st_theme_node_get_icon_colors (theme_node);
@ -1034,7 +1032,6 @@ st_texture_cache_load_gicon (StTextureCache *cache,
g_free (gicon_string);
actor = create_invisible_actor ();
actor_size = size * paint_scale;
clutter_actor_set_size (actor, actor_size, actor_size);
if (ensure_request (cache, key, policy, &request, actor))
{

View File

@ -64,10 +64,9 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
GFunc load_callback,
gpointer user_data);
StWidget *st_texture_cache_bind_cairo_surface_property (StTextureCache *cache,
GObject *object,
const char *property_name,
gint size);
GIcon *st_texture_cache_bind_cairo_surface_property (StTextureCache *cache,
GObject *object,
const char *property_name);
ClutterActor *st_texture_cache_load_gicon (StTextureCache *cache,
StThemeNode *theme_node,

View File

@ -84,10 +84,11 @@ on_timeline_new_frame (ClutterTimeline *timeline,
}
StThemeNodeTransition *
st_theme_node_transition_new (StThemeNode *from_node,
StThemeNode *to_node,
st_theme_node_transition_new (ClutterActor *actor,
StThemeNode *from_node,
StThemeNode *to_node,
StThemeNodePaintState *old_paint_state,
guint duration)
unsigned int duration)
{
StThemeNodeTransition *transition;
g_return_val_if_fail (ST_IS_THEME_NODE (from_node), NULL);
@ -103,7 +104,7 @@ st_theme_node_transition_new (StThemeNode *from_node,
st_theme_node_paint_state_copy (&transition->priv->old_paint_state,
old_paint_state);
transition->priv->timeline = clutter_timeline_new (duration);
transition->priv->timeline = clutter_timeline_new_for_actor (actor, duration);
transition->priv->timeline_completed_id =
g_signal_connect (transition->priv->timeline, "completed",

View File

@ -32,10 +32,11 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (StThemeNodeTransition, st_theme_node_transition,
ST, THEME_NODE_TRANSITION, GObject)
StThemeNodeTransition *st_theme_node_transition_new (StThemeNode *from_node,
StThemeNode *to_node,
StThemeNodeTransition *st_theme_node_transition_new (ClutterActor *actor,
StThemeNode *from_node,
StThemeNode *to_node,
StThemeNodePaintState *old_paint_state,
guint duration);
guint duration);
void st_theme_node_transition_update (StThemeNodeTransition *transition,
StThemeNode *new_node);

View File

@ -78,6 +78,7 @@ adjustment_value_notify_cb (StAdjustment *adjustment,
GParamSpec *pspec,
StViewport *viewport)
{
clutter_actor_invalidate_transform (CLUTTER_ACTOR (viewport));
clutter_actor_queue_relayout (CLUTTER_ACTOR (viewport));
}
@ -261,8 +262,10 @@ st_viewport_allocate (ClutterActor *actor,
clutter_actor_set_allocation (actor, box);
content_box = viewport_box;
content_box.x2 += MAX (0, min_width - avail_width);
content_box.y2 += MAX (0, min_height - avail_height);
if (priv->hadjustment)
content_box.x2 += MAX (0, min_width - avail_width);
if (priv->vadjustment)
content_box.y2 += MAX (0, min_height - avail_height);
clutter_layout_manager_allocate (layout, CLUTTER_CONTAINER (actor),
&content_box);

View File

@ -124,7 +124,6 @@ enum
{
STYLE_CHANGED,
POPUP_MENU,
RESOURCE_SCALE_CHANGED,
LAST_SIGNAL
};
@ -412,8 +411,7 @@ st_widget_paint_background (StWidget *widget,
float resource_scale;
guint8 opacity;
if (!st_widget_get_resource_scale (widget, &resource_scale))
return;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (widget));
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
theme_node = st_widget_get_theme_node (widget);
@ -820,6 +818,20 @@ st_widget_real_get_focus_chain (StWidget *widget)
return g_list_reverse (visible);
}
static void
st_widget_resource_scale_changed (ClutterActor *actor)
{
StWidget *widget = ST_WIDGET (actor);
StWidgetPrivate *priv = st_widget_get_instance_private (widget);
int i;
for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
st_theme_node_paint_state_invalidate (&priv->paint_states[i]);
if (CLUTTER_ACTOR_CLASS (st_widget_parent_class)->resource_scale_changed)
CLUTTER_ACTOR_CLASS (st_widget_parent_class)->resource_scale_changed (actor);
}
static void
st_widget_class_init (StWidgetClass *klass)
{
@ -849,6 +861,8 @@ st_widget_class_init (StWidgetClass *klass)
actor_class->get_accessible = st_widget_get_accessible;
actor_class->has_accessible = st_widget_has_accessible;
actor_class->resource_scale_changed = st_widget_resource_scale_changed;
klass->style_changed = st_widget_real_style_changed;
klass->navigate_focus = st_widget_real_navigate_focus;
klass->get_accessible_type = st_widget_accessible_get_type;
@ -1002,21 +1016,6 @@ st_widget_class_init (StWidgetClass *klass)
G_STRUCT_OFFSET (StWidgetClass, popup_menu),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
/**
* StWidget::resource-scale-changed:
* @widget: the #StWidget
*
* Emitted when the paint scale that the widget will be painted as
* changed.
*/
signals[RESOURCE_SCALE_CHANGED] =
g_signal_new ("resource-scale-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (StWidgetClass, resource_scale_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
static const gchar *
@ -1400,23 +1399,6 @@ st_widget_get_style (StWidget *actor)
return ST_WIDGET_PRIVATE (actor)->inline_style;
}
/**
* st_widget_get_resource_scale:
* @widget: A #StWidget
* @resource_scale: (out): return location for the resource scale
*
* Retrieves the resource scale for this #StWidget, if available.
*
* The resource scale refers to the scale the actor should use for its resources.
*/
gboolean
st_widget_get_resource_scale (StWidget *widget,
float *resource_scale)
{
return clutter_actor_get_resource_scale (CLUTTER_ACTOR (widget),
resource_scale);
}
static void
st_widget_set_first_visible_child (StWidget *widget,
ClutterActor *actor)
@ -1483,23 +1465,6 @@ st_widget_name_notify (StWidget *widget,
st_widget_style_changed (widget);
}
static void
st_widget_resource_scale_notify (StWidget *widget,
GParamSpec *pspec,
gpointer data)
{
StWidgetPrivate *priv = st_widget_get_instance_private (widget);
int i;
for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
st_theme_node_paint_state_invalidate (&priv->paint_states[i]);
g_signal_emit (widget, signals[RESOURCE_SCALE_CHANGED], 0);
if (clutter_actor_is_mapped (CLUTTER_ACTOR (widget)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (widget));
}
static void
st_widget_reactive_notify (StWidget *widget,
GParamSpec *pspec,
@ -1651,7 +1616,6 @@ st_widget_init (StWidget *actor)
/* connect style changed */
g_signal_connect (actor, "notify::name", G_CALLBACK (st_widget_name_notify), NULL);
g_signal_connect (actor, "notify::resource-scale", G_CALLBACK (st_widget_resource_scale_notify), NULL);
g_signal_connect (actor, "notify::reactive", G_CALLBACK (st_widget_reactive_notify), NULL);
g_signal_connect (actor, "notify::visible", G_CALLBACK (st_widget_visible_notify), NULL);
@ -1723,7 +1687,8 @@ st_widget_recompute_style (StWidget *widget,
*/
priv->transition_animation =
st_theme_node_transition_new (old_theme_node,
st_theme_node_transition_new (CLUTTER_ACTOR (widget),
old_theme_node,
new_theme_node,
current_paint_state (widget),
transition_duration);

View File

@ -63,7 +63,6 @@ struct _StWidgetClass
/* signals */
void (* style_changed) (StWidget *self);
void (* popup_menu) (StWidget *self);
void (* resource_scale_changed) (StWidget *self);
/* vfuncs */
@ -135,8 +134,6 @@ StThemeNode * st_widget_peek_theme_node (StWidget *widg
GList * st_widget_get_focus_chain (StWidget *widget);
void st_widget_paint_background (StWidget *widget,
ClutterPaintContext *paint_context);
gboolean st_widget_get_resource_scale (StWidget *widget,
float *resource_scale);
/* debug methods */
char *st_describe_actor (ClutterActor *actor);

View File

@ -566,26 +566,26 @@ main (int argc, char **argv)
root = st_theme_context_get_root_node (context);
group1 = st_theme_node_new (context, root, NULL,
CLUTTER_TYPE_GROUP, "group1", NULL, NULL, NULL);
CLUTTER_TYPE_ACTOR, "group1", NULL, NULL, NULL);
text1 = st_theme_node_new (context, group1, NULL,
CLUTTER_TYPE_TEXT, "text1", "special-text", NULL, NULL);
text2 = st_theme_node_new (context, group1, NULL,
CLUTTER_TYPE_TEXT, "text2", NULL, NULL, NULL);
group2 = st_theme_node_new (context, root, NULL,
CLUTTER_TYPE_GROUP, "group2", NULL, NULL, NULL);
CLUTTER_TYPE_ACTOR, "group2", NULL, NULL, NULL);
group4 = st_theme_node_new (context, root, NULL,
CLUTTER_TYPE_GROUP, "group4", NULL, NULL, NULL);
CLUTTER_TYPE_ACTOR, "group4", NULL, NULL, NULL);
group5 = st_theme_node_new (context, root, NULL,
CLUTTER_TYPE_GROUP, "group5", NULL, NULL, NULL);
CLUTTER_TYPE_ACTOR, "group5", NULL, NULL, NULL);
group6 = st_theme_node_new (context, root, NULL,
CLUTTER_TYPE_GROUP, "group6", NULL, NULL, NULL);
CLUTTER_TYPE_ACTOR, "group6", NULL, NULL, NULL);
text3 = st_theme_node_new (context, group2, NULL,
CLUTTER_TYPE_TEXT, "text3", NULL, NULL,
"color: #0000ff; padding-bottom: 12px;");
text4 = st_theme_node_new (context, group2, NULL,
CLUTTER_TYPE_TEXT, "text4", NULL, "visited hover", NULL);
group3 = st_theme_node_new (context, group2, NULL,
CLUTTER_TYPE_GROUP, "group3", NULL, "hover", NULL);
CLUTTER_TYPE_ACTOR, "group3", NULL, "hover", NULL);
button = st_theme_node_new (context, root, NULL,
ST_TYPE_BUTTON, "button", NULL, NULL, NULL);

View File

@ -39,6 +39,7 @@
</description>
<releases>
<release version="3.37.3" date="2020-07-07"/>
<release version="3.37.2" date="2020-06-02"/>
<release version="3.37.1" date="2020-04-29"/>
</releases>

View File

@ -1,5 +1,5 @@
project('gnome-extensions-app',
version: '3.37.2',
version: '3.37.3',
meson_version: '>= 0.53.0',
license: 'GPLv2+'
)

View File

@ -1,5 +1,5 @@
project('gnome-extensions-tool', 'c',
version: '3.37.2',
version: '3.37.3',
meson_version: '>= 0.53.0',
license: 'GPLv2+'
)

View File

@ -1,5 +1,5 @@
project('shew', 'c',
version: '3.37.2',
version: '3.37.3',
meson_version: '>= 0.53.0',
license: 'LGPLv2+',
)