Compare commits

...

296 Commits

Author SHA1 Message Date
Alexander Mikhaylenko
35aa7998bc power: Ceil percentage when looking for icon
Use correct battery icon. For example, use battery-level-10-symbolic, with
a warning, on 1%-10% instead of 10%-19%.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/726
2019-09-14 12:17:46 +05:00
Марко Костић
314a89a837 Update Serbian translation 2019-09-13 19:43:24 +00:00
Jonas Ådahl
57ed68541a environment: Disable fullscreen unredirect during all transitions
When there is a transition, it's likely that we are animating some part
of the desktop, and in such situations we don't want to unredirect
fullscreen windows.

This fixes unwanted unredirection when e.g. hiding a modal dialog by
re-enabling the unredirection after the animation has finished, instead
of when it starts.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/721
2019-09-13 16:10:17 +00:00
Georges Basile Stavracas Neto
413c677fcf iconGrid: Only animate visible icons
Mutter recently added an optimization to only allocate
visible children [1]. That broke ClutterClones, but it
was subsequently fixed [2].

However, that exposed a third problem, this time with
FrequentView: visible but transparent icons, that are
not allocated by the icon grid, were cloned and animated
during the spring animation.

Only animate visible icons with opacity greater than 0.

[1] https://gitlab.gnome.org/GNOME/mutter/commit/0eab73dc
[2] https://gitlab.gnome.org/GNOME/mutter/commit/08a3cbfc

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/696
2019-09-13 15:33:45 +00:00
Milo Casagrande
3d86e6e791 Update Italian translation 2019-09-13 12:55:53 +00:00
Daniel Mustieles
3fbd61cbf0 Updated Spanish translation 2019-09-13 08:27:06 +02:00
Georges Basile Stavracas Neto
43b4f2c7d5 lookingGlass: Only update window list when visible
Updating the window list in the Looking Glass is a costly
operation: it destroys a whole lot of actors, and recreates
them. This triggers CSS changes, repaints, and allocations.

It is specially bad when paired with Wayland's big number
of window creations and deletions when showing Builder's
and Epiphany's popup window.

Only update the window list in the Looking Glass when it is
visible.

Related: https://gitlab.gnome.org/GNOME/mutter/issues/556

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/719
2019-09-13 00:49:38 +00:00
Anders Jonsson
7eb4088f45 Update Swedish translation 2019-09-12 22:16:22 +00:00
Florian Müllner
f00201fa6c ci: Disable MR handling for now
We aren't quite ready to enforce non-legacy style for now, mostly due
to the xgettext bug that prevents us from using template strings in
some places, and vast amounts of legacy indentation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/716
2019-09-12 23:18:27 +02:00
Florian Müllner
1aca2ba6bb ci: Disallow legacy style in merge requests
In order to transition from the current legacy style to the modern
gjs one, use the MR line-filtering we used to do on common errors
to ensure new code complies with the new style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/716
2019-09-12 23:18:27 +02:00
Florian Müllner
e9131465dd ci: Fail on any common lint errors
Now that we fixed all pre-existing errors that are common between
regular and legacy configuration, we can stop filtering the result
by the lines modified by the merge request.

This will allow us to catch errors in merge requests that slipped
through until now, for example when leaving a newly-unused import
behind.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/716
2019-09-12 23:18:27 +02:00
Florian Müllner
0ee7f02f8e cleanup: Don't assume hasOwnProperty() method on objects
Since ES5, it is possible to create objects with no prototype at all:

    let foo = Object.create(null);

Those object won't have any builtin properties like hasOwnProperty(),
which is why eslint added a corresponding rule to its default rule set.

While this isn't an issue that affects our code, there's no harm in fol-
lowing the recommendation and call the method through Object.prototype.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/716
2019-09-12 23:18:27 +02:00
Florian Müllner
451f4e3636 cleanup: "Only" use two indentation styles for object literals
We currently use no less than three different ways of indenting
object literals:

    let obj1 = {
        foo: 42,
        bar: 23,
    };

    let obj2 = { foo: 42,
                 bar: 23 };

    let obj3 = { foo: 42,
                 bar: 23
               };

The first is the one we want to use everywhere eventually, while the
second is the most commonly used "legacy" style.

It is the third one that is most problematic, as it throws off eslint
fairly badly: It violates both the rule to have consistent line breaks
in braces as well as the indentation style of both regular and legacy
configurations.

Fortunately the third style was mostly used for tween parameters, so
is quite rare after the Tweener purge. Get rid of the remaining ones
to cut down on pre-existing eslint errors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/716
2019-09-12 23:18:24 +02:00
Florian Müllner
2fc4987c73 cleanup: Stop using Mainloop module
It is deprecated in favor of the regular GLib functions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/718
2019-09-12 19:09:24 +02:00
GB_2
4525ad346d windowMenu: Animate menu
Most menus have an animation, so add one to the window menu for
consistency and better looks (like !712).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/717
2019-09-12 16:01:46 +00:00
Danial Behzadi
e4b8a4b432 Update Persian translation 2019-09-12 12:27:27 +00:00
Enrico Nicoletto
62e594af6d Update Brazilian Portuguese translation 2019-09-12 11:35:40 +00:00
Florian Müllner
ce92270626 extensionSystem: Add missing return value
_callExtensionInit() should return whether the extension was initialized
successfully or not, but the early return added in commit 2a9e065cfb
doesn't.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/715
2019-09-12 12:45:05 +02:00
Jonas Dreßler
bdcf3037ca extensionSystem: Always disable multiple extensions in reverse order
Since disabling an extension will lead to disabling and re-enabling all
following extensions in the list, always disable multiple extensions by
looping through the list in reverse order.

This lowers the execution time of the event handlers quite a bit if many
extensions are installed.

Thanks to Philippe Troin for identifying the problem and proposing the
initial patch to change the extension order when reloading.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
9698ff491a extensionSystem: Only add to extensionOrder array if enabling worked
Only push uuids of newly enabled extensions to the `_extensionOrder`
array if enabling them was successful.

Otherwise, since `_callExtensionDisable()` doesn't remove uuids that
weren't successfully enabled from the array, those extensions get added
to the array multiple times when they're disabled and enabled.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
2a9e065cfb extensionSystem: Always enforce disallowing extensions using sessionMode
It's currently possible to circumvent the `sessionMode.allowExtensions`
property: For already enabled extensions one can call reloadExtension
via DBus, for new extensions it's possible by adding the extension to
the enabled-extensions gsettings key and setting the
disable-extension-version-validation key (which triggers a reload of
`this._enabledExtensions`) and then calling reloadExtension via DBus.

So to enforce `allowExtensions` while still allowing to update
extensions and keeping the extensionSystem synced with various gsettings
keys, replace the checks for `this._enabled` with simple checks for
`Main.sessionMode.allowExtensions` inside `_callExtensionInit()` and
`_callExtensionEnable()`.

The remaining checks for `this._enabled` are only small optimizations to
prevent running code on irrelevant sessionMode updates.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
4c93ef39fa extensionSystem: Handle added or removed sessionMode extensions
Right now we're only handling added sessionMode extensions correctly on
sessionMode updates, also handle the other case and disable removed
sessionMode extensions on sessionMode updates.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
22107c183b extensionSystem: Rename initted to initialized
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
c06eb5d0a7 extensionSystem: Log an extension error if loading the stylesheet failed
Instead of only logging a message that loading the extension stylesheet
failed and silently returning we should use `logExtensionError` for that
instead. This also sets the extension state to ERROR and makes sure we
don't try to enable it again.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
e76877c4b8 extensionSystem: Check if extension exists before accessing property
If the extension doesn't exist in the `this._extensions` Map, we'd try
to access `extension.dir` on undefined/null. So set the `dir` variable
after checking if `extension` is defined.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
2a32fb2e72 extensionSystem: Fix a wrong error message
The extension object is added to the `this._extensions` Map inside
`createExtensionObject`, not inside `loadExtension`.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
de86920e0e extensionSystem: Remove unncessary return statements
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Jonas Dreßler
8754736fda extensionUtils: Check version variable for undefined first
Avoid a warning message when trying to access requiredArray[2] by
checking if its undefined first.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
2019-09-12 10:24:49 +00:00
Iain Lane
d2ead59d74 data: Lower TimeoutStartSec in systemd units
If there's a stubborn process in our cgroup, we shouldn't hang around
waiting for the default (30 seconds) before the session closes. We've
logged out, SIGTERMed and the thing is refusing to go away, let's not
make people hang around for ages.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/699
2019-09-12 08:16:10 +00:00
Emin Tufan Çetin
2f4fcc59a1 Update Turkish translation 2019-09-12 04:26:07 +00:00
Florian Müllner
ba6dbb228d workspace: Minor clarification
Code and comment were based on the old get_input_rect() and get_outer_rect()
method names that were changed to the more appropriate get_buffer_rect() and
get_frame_rect() a long time ago.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/713
2019-09-11 23:32:16 +00:00
Florian Müllner
60e386048b backgroundMenu: Animate menu opening
The animation was removed in commit 6a00a504d4 for consistency with
other menus. However commit a9b12d5d73 then *added* animations to
those just four minutes later.

So add back the original animations for consistency, both with menu
closing and with other menus.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1595
2019-09-11 23:25:21 +00:00
Christian Kirbach
c2904fa14d Update German translation 2019-09-11 21:14:44 +00:00
Florian Müllner
dfdb139d9c workspaceThumbnails: Replace loops with Array.find()
This is much more idiomatic and concise than iterating over
thumbnails until we find the one we are looking for.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
ce63d21dcc overview: Minor cleanup
Safe one indentation level by combining conditions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
1da9937453 workspace: Use operator shorthand
Shorthands like a += b are well-established, so prefer them over the
less concise a = a + b.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
9f11fbad16 jsParse: Disambiguate regex
Make it clear that /= is part of a regex and not an operator shorthand.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
f54e7804c5 workspace: Don't initialize variables to undefined
The declaration itself already does this implicitly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
7db5f8b28e calendar: Use template strings over concatenation
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
743ce23fbc util: Separate statements with linebreak
Our eslint rules will soon forbid more than one statement per line.
We already follow that rule except for one lone offender; fix that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
a3267be192 network: Don't omit parens when constructing
While it is legal to omit parentheses when invoking a constructor
with no arguments, we generally avoid that in our coding style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
4ad2523877 messageTray: Add missing linebreak
Methods should be separated by an empty lines, even when short.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
4bfee3a8ca ibusManager: Wrap line before dot
When chaining function calls, our coding style asks for the dot to
start the new line, not end the preceding one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
fc964f975a kbdA11yDialog: Avoid unnecessary ternary operators
A condition is already boolean, there's no point in explicitly
turning it into true/false.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
52f85c9465 system: Properly separate statements
Whoops, that's some typo that sneaked into commit 9c3b3320f8 ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
691610f23c lookingGlass: Fix misleading typeof use
typeof is an operator, not a function. Putting unneeded parentheses
around the expression obfuscates that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Florian Müllner
b6a2b2b8a5 cleanup: Remove left-over imports
Unfortunately this slipped through our CI tests, as the script
filters errors by lines that are modified by the corresponding
merge request.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/710
2019-09-11 20:59:31 +00:00
Daniel Șerbănescu
1ad8a2fcf6 Update Romanian translation 2019-09-11 20:13:21 +00:00
Balázs Úr
7ce08845f1 Update Hungarian translation 2019-09-11 20:11:51 +00:00
Aurimas Černius
d469250130 Updated Lithuanian translation 2019-09-11 22:37:29 +03:00
Jordi Mas
7fd5c47e06 Update Catalan translation 2019-09-11 21:21:08 +02:00
Kukuh Syafaat
8704b1004e Update Indonesian translation 2019-09-11 18:31:47 +00:00
Piotr Drąg
65a9fb8c01 Update Polish translation 2019-09-11 19:22:04 +02:00
Florian Müllner
25a7a8006a gnome-extensions: Translate help command
The quotes and COMMAND string aren't part of the syntax, so they
should be translated.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1538
2019-09-11 17:09:30 +00:00
Marek Černocký
6fe1d3248a Updated Czech translation 2019-09-11 18:01:13 +02:00
Jonas Dreßler
13f97532bf overviewControls: Remove slide transitions before setting value manually
Remove transitions of the `slide-x` property of the layout manager
before we set the property to a fixed value, otherwise the transitions
might still be running and change the value after we set it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/707
2019-09-11 11:39:44 +00:00
Anders Jonsson
1acee3d702 Update Swedish translation 2019-09-10 23:53:06 +00:00
Marco Trevisan (Treviño)
1d17404471 selectArea: Ignore motion events once we got a result
When selecting an area for screenshot we monitor the events while we've valid
coordinates in order to redraw the rubber band.
However, we don't stop ignore the motion events after button release and so
while animating. This might cause an unwanted effect if moving the mouse away
during fade out that is way more visible slowing-down the animations.

To fix this ignore any motion event once we've set the results.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/711
2019-09-10 22:08:25 +02:00
Florian Müllner
48b860b69f ci: Turn on -Werror
Now that all compiler warnings are fixed, let's try to keep it that
way by making warnings fatal during CI.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/709
2019-09-10 17:51:02 +00:00
Florian Müllner
a030c54661 shell: Replace another GTimeVal
This slipped through in commit 9b7f228f8e.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/709
2019-09-10 17:51:02 +00:00
Florian Müllner
dcf7bae6c7 calendar-server: Temporarily ignore all deprecations in eds includes
Evolution draws in libsoup, which exposes deprecated types in its
API. While its headers have been fixed to guard the affected symbols,
those fixes aren't in our CI images yet.

Until we get a fixed version, just disable all deprecation warnings
during the include in order to not trip over "foreign" bugs.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/709
2019-09-10 17:51:02 +00:00
Florian Müllner
d0ace108e5 calendar-server: Disable deprecated e-d-s API
We aren't using any deprecated evolution-data-server API, so we can
turn it off; this avoids compiler warnings for glib deprecations
used by those functions, which makes it harder to spot warnings for
our own code base.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/709
2019-09-10 17:51:02 +00:00
Florian Müllner
32d5744014 build: Exclude private headers from GIR
They contain API that is explicitly not meant to be used externally
and - as it uses the "wrong" namespace due to the _ prefix - doesn't
end up in the introspection data anyway.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/709
2019-09-10 17:51:02 +00:00
Florian Müllner
d16094774b build: Remove st-private.h from "public" headers
It is currently listed both as public and private header, which is
clearly bonkers. As the name implies, the latter is correct ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/709
2019-09-10 17:51:02 +00:00
Piotr Drąg
ac664ba321 Update Polish translation 2019-09-10 17:58:11 +02:00
Florian Müllner
0888a9bffd environment: Skip property animations while hidden
For implicit animations, Clutter will skip any transitions while
an actor is unmapped, and just set the property directly. Do the
same in our ease_property() convencience method.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/708
2019-09-10 14:41:26 +00:00
Daniel Mustieles
5e82d72424 Updated Spanish translation 2019-09-10 15:56:03 +02:00
Jiri Grönroos
2513835e89 Update Finnish translation 2019-09-10 11:11:21 +00:00
Kukuh Syafaat
98b70ef00f Update Indonesian translation 2019-09-10 07:12:48 +00:00
Daniel Șerbănescu
ae11381b88 Update Romanian translation 2019-09-10 06:48:29 +00:00
Milo Casagrande
e9596f2775 Update Italian translation 2019-09-10 06:47:05 +00:00
Balázs Úr
8adbc8010a Update Hungarian translation 2019-09-10 04:40:55 +00:00
Fran Dieguez
76fb559964 Update Galician translation 2019-09-09 22:45:51 +00:00
Rafael Fontenelle
1bc1b4d9d8 Update Brazilian Portuguese translation 2019-09-09 22:44:55 +00:00
Georges Basile Stavracas Neto
dfc0ef56f6 appDisplay: Allow editing folder names
Add a new popover with a regular entry + button to rename
folders. The layout is similar to other GNOME applications.

The popup is implemented as a PopupMenu subclass, leaving
the grab management to PopupMenuManager.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/675
2019-09-09 22:15:49 +02:00
Jonas Dreßler
1e68e78d8e extensionPrefs: Block notify::active signal handler while updating state
We disable and enable extensions inside the `notify::active` signal
handler, but we shouldn't do that in case the change didn't come from
the user but because something else changed the state of the extension.

This causes an issue when the extensionPrefs window is open and the
session gets locked: The extensions are temporarily disabled by the
shell, extensionPrefs updates its switches on the state change and adds
those extensions to the `disabled-extensions` gsettings key inside the
signal handler. Now when the session is unlocked again, the extensions
won't be enabled again since they're forced-disabled.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/705
2019-09-09 19:50:31 +00:00
Jonas Dreßler
17fa5a2db4 extensionPrefs: Connect to ExtensionStateChanged after building UI
Since we manipulate parts of the UI (like the switch) in this signal
handler, let's only connect it after setting up the UI.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/705
2019-09-09 19:50:31 +00:00
Jonas Dreßler
004a5e1042 iconGrid: Queue a relayout after child opacity changes
We're using a vfunc override for `get_paint_volume` to exclude children
with an opacity of 0 from the paint volume and thus decrease the size of
the area we need to paint.

Now if the paint volume is requested during the spring animation (the
real icons are hidden using an opacity of 0 and clones are used for the
animation), `get_paint_volume` returns a paint volume with a height of
0. After that, the spring animation finishes and the icon-opacities are
set to 255 in `_resetAnimationActors`, and since we cache paint volumes
and there's no reason for Clutter to assume it got invalid, the icons
end up not being painted.

Fix this by queuing a relayout of the grid when the opacity of a child
is changed from or to 0, which manually invalidates the paint volume.

The reason why this is not an issue with the paginated icon grid
(all-apps view) is probably because StScrollView invalidates the paint
volume a lot more often than regular containers.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1502
2019-09-09 19:39:28 +00:00
Jonas Dreßler
4915a9e8e4 iconGrid: Delete private child property when removing child
Delete a private property we set when the child got added to make sure
the reference is deleted after the child got removed from the grid.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/704
2019-09-09 19:39:28 +00:00
Marco Trevisan (Treviño)
8a7e44ccf0 extensionSystem: Use logError to record extension errors with stack trace
Extensions might emit JS errors explicitly or implicitly, however GNOME
Shell doesn't present any stack trace for those making them quite hard
to debug.

Make this easier by logging errors with logError() whichs includes the
stack dump.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:19 +00:00
Marco Trevisan (Treviño)
a497afe695 system: Track buttonGroup visibility using a group of actors
Cleanup the visibility check on actions by using an array of actors to
track, so that we don't repeat the same variables multiple times.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:19 +00:00
Marco Trevisan (Treviño)
15c252c11d popupMenu: Remove extra parameter on boolean ParamSpec initialization
PopupBaseMenuItem properties were initialized using wrong param spec
signature, fix this by removing the extra parameter.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
27da3ed1fe calendar: Use binding for clearButton visibility
When the calendar PlaceHolder is visible, the ClearButton shouldn't
be. Instead of setting the visibility explicitly, we can use a property
binding.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
8656102182 workspacesDisplay: Disconnect MetaLater and parent signals on destroy
When the WorkspacesDisplay actor is destroyed we should remove the
ongoing later and parent widget connections to avoid accessing an
invalid object on callback.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
24d3744cb9 workspace: Don't use clones' delegate to check children
The WindowClones are now themselves actors, so we can just check for
their type instead of checking for the delegate.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
031913b9df workspace: Use Workspace prefix for WindowClone class
We have both Workspace's WindowClone and workspaceThumbnail's WindowClone,
so better to be clear about them using a class prefix.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
e53443daf9 workspace: Remove Long-press later with the actor
Ensure that the long-press later is removed with the actor, otherwise
it will try to use invalidated data.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
06317f4f6a status/keyboard: Make Input source types var
These are used by keyboard so they need to be readable outside the
status.keyboard module.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
c69e195441 search: Remove updateSearch later on destruction
When the GridSearchBase actor is destroyed we should remove the
ongoing later that might try to access to invalid resources.

To do this, add an _onDestroy() callback function to SearchResultsBase
and override it in GridSearchBase.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
a53b48de4c locatePointer: Bind ripples creation to settings
Don't create ripples if locate pointer is not enabled, and bind
creation to the relative desktop interface settings key.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
eca98aee42 ripples: Add destroy() method and remove them when unneeded
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
ea5aaa8ab2 realmd: Set login format to null on start and update if invalid
We were checking an undefined property but that would lead to a a warning.
Instead we can consider the login format unset until is null, and in case
update it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
72566eda43 messageTray: Remove unused source object parameter
This is has been added in commit b150869b5 but is never used

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
7a4f9a5ff3 keyboard: Treat menu items as actors
This is a leftover of GNOME/gnome-shell!499, since menu items are all
actors now, we can just avoid using the actor property when adding an
action item.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
ba23fd9989 lookingGlass: Throw a clearer error on referencing invalid result index
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
c101196f5b lightbox: Use common ease parameters and avoid similar codepaths
Easing calls on show/hide functions have some parameters in common whether the
radial effect is enabled or not.

So instead of doing repeated calls with similar parameters, initialize common
values in params objects.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
1687a5451e altTab: use AltTab prefix on AppIcon class
There's an AppIcon class on appDisplay, so it won't be easy to discern
the one we're going to add in altTab.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Marco Trevisan (Treviño)
ea4d5f89eb animation: Stop the animation before removing all the children
If the resource scale or the scale factor changes while the animation
is playing, we need to stop the animation and start it again once the
texture is loaded, as the idle might try to access an invalidated
animation child otherwise.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
2019-09-09 19:28:18 +00:00
Florian Müllner
9e388ebcfd Bump version to 3.34.0
Update NEWS.
2019-09-09 19:21:11 +00:00
Carlos Garnacho
8d9cae45f9 st-clipboard: Add trailing 0 to pasted text
We translate the raw stream content far too directly into a char*,
it notably forgets that the stream does not have nul-ended data,
this means we are potentially adding garbage after the pasted content.

Tentatively fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1570
2019-09-09 19:04:31 +00:00
Claude Paroz
406d0900a7 Update French translation 2019-09-08 15:44:41 +00:00
Balázs Meskó
cf611d2be8 Update Hungarian translation 2019-09-07 18:25:17 +00:00
Dušan Kazik
7875fc831b Update Slovak translation 2019-09-07 14:20:05 +00:00
Sabri Ünal
44bca36385 Update Turkish translation 2019-09-07 07:16:54 +00:00
Carmen Bianca BAKKER
e2c3198627 Update Esperanto translation 2019-09-06 23:22:30 +00:00
Efstathios Iosifidis
8b549f3d5b Update Greek translation 2019-09-06 21:05:07 +00:00
Ryuta Fujii
a0e3c342a6 Update Japanese translation 2019-09-06 13:58:48 +00:00
Ryuta Fujii
a80331dbcf Update Japanese translation 2019-09-06 13:52:41 +00:00
Milo Casagrande
0068dab001 Update Italian translation 2019-09-06 08:41:20 +00:00
Tom Tryfonidis
7d42990462 Update Greek translation 2019-09-05 16:30:45 +00:00
Iain Lane
e6dec7a9dd volume: Ignore slider changes we initiated ourselves
Commit 21e14bd46f fixed this for the
brightness slider, but we have the same problem for volume too. When the
volume is muted - for example in Settings or via a media key, we update
the slider to '0' to indicate this visually. But we also actually invoke
the slider's callback to *set* the volume to zero. That means that the
previous level is overwritten so it can't be restored when unmuting.

The fix is the same - when we update the slider internally ourselves,
don't call the signal handler.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1557
2019-09-05 11:30:33 +01:00
Carlos Garnacho
8adfc5b106 windowManager: Handle starting/stopping of X11 services
We now do 2 things along Xwayland startup/shutdown:
- Start or stop the gnome-session-x11-services target, that will
  pull all X11 related services that the session might depend on.
- As we start ibus-daemon manually, trigger a restart in order to
  toggle the XIM daemon on and off along with Xwayland presence.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/680
2019-09-05 07:42:46 +00:00
Carlos Garnacho
8be95b5785 ibusManager: Add call to restart the ibus daemon
We may need to restart it with different arguments, so make it
possible to do that. Also, avoid to just restart it on _clear(),
this is now most likely through our --replace call than it is
through ibus-daemon eg. dying, avoids some noise in logs as
there is already an ongoing ibus-daemon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/680
2019-09-05 07:42:46 +00:00
Carlos Garnacho
9194de8460 shell: Add helpers to start/stop systemd units
These just send the respective DBus message to the systemd user service.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/680
2019-09-05 07:42:46 +00:00
Florian Müllner
6dccbc5a90 Bump version to 3.33.92
Update NEWS.
2019-09-04 20:54:34 +02:00
Rafael Fontenelle
efba1e83c7 Update Brazilian Portuguese translation 2019-09-03 19:36:12 +00:00
Goran Vidović
d1442765a6 Update Croatian translation 2019-09-03 15:48:10 +00:00
Kukuh Syafaat
72e5caf6e1 Update Indonesian translation 2019-09-03 12:19:11 +00:00
Florian Müllner
3768b6b701 keyboard: Fix EmojiSelection:delta range
The setter clamps the values to the range (-width, width), so we
must not limit the property to positive values.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/698
2019-09-03 03:20:17 +02:00
Will Thompson
e5cde4700f notificationDaemon: Catch exceptions while loading notifications
An Endless OS system was found in the wild with a malformed
.local/share/gnome-shell/notifications which causes _loadNotifications()
to raise an exception. This exception was not previously handled and
bubbles all the way out to gnome_shell_plugin_start(), whereupon the
shell exit(1)s. The user could no longer log into their computer.

Handle exceptions from _loadNotifications(), log them, and attempt to
continue. Ensure that this._isLoading is set to 'false' even on error,
so that future calls to _saveNotifications() can overwrite the (corrupt)
state file.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552
2019-09-03 01:00:50 +00:00
Will Thompson
a207f67f73 global: Don't trust persistent/runtime state data
An Endless OS system was found in the wild with a malformed
.local/share/gnome-shell/notifications. When deserialized in Python,
after passing trusted=True to g_variant_new_from_bytes(), the first
element of the first struct in the array looks like this:

    In [41]: _38.get_child_value(0).get_child_value(0)
    Out[41]: GLib.Variant('s', '\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff')

When deserialised in GJS, we get:

    gjs> v.get_child_value(0).get_child_value(0)
    [object variant of type "s"]
    gjs> v.get_child_value(0).get_child_value(0).get_string()
    typein:43:1 malformed UTF-8 character sequence at offset 0
      @typein:43:1
      @<stdin>:1:34

While g_variant_new_from_bytes() doesn't have much to say about its
'trusted' parameter, g_variant_new_from_data() does:

> If data is trusted to be serialised data in normal form then trusted
> should be TRUE. This applies to serialised data created within this
> process or read from a trusted location on the disk (such as a file
> installed in /usr/lib alongside your application). You should set
> trusted to FALSE if data is read from the network, a file in the
> user's home directory, etc.

Persistent state is read from the user's home directory, so it should
not be trusted. With trusted=False, the string value above comes out as
"".

I don't have an explanation for how this file ended up being malformed.
I also don't have an explanation for when this started crashing: my
guess is that recent GJS became stricter about validating UTF-8 but I
could be wrong!

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1552
2019-09-03 01:00:50 +00:00
Jonas Ådahl
b73aace476 shell: Get cairo surface via window actor
Instead of going via the MetaShapedTexture to get the cairo surface, get
it from the window actor. The window actor can then handle this in a way
that makes it include potential subsurfaces.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/692
2019-09-02 16:53:55 +00:00
Marek Černocký
346d37ecbb Updated Czech translation 2019-09-02 08:53:00 +02:00
Daniel Rusek
7bb29817f7 Update Czech translation 2019-09-01 21:21:10 +00:00
Aurimas Černius
92b92a2e0a Updated Lithuanian translation 2019-09-01 22:32:34 +03:00
Jordi Mas
8e79f9f2dc Update Catalan translation 2019-09-01 16:37:08 +02:00
Jonas Dreßler
05b345cc92 endSessionDialog: Initialize Polkit permission asynchronously
The updatesPermission is currently initialized synchronously, which
blocks the Mainloop for quite some time and therefore slows down startup
of the shell, let's do it asynchronously instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/689
2019-09-01 12:45:49 +02:00
Changwoo Ryu
89f9925208 Update Korean translation 2019-09-01 09:00:28 +00:00
A S Alam
fcc1d7beff Update Punjabi translation 2019-08-31 13:45:30 +00:00
Ryuta Fujii
f226398c7c Update Japanese translation 2019-08-29 11:49:39 +00:00
Ryuta Fujii
890ac9ff38 Update Japanese translation 2019-08-29 11:36:39 +00:00
Pawan Chitrakar
6a027cd566 Update Nepali translation 2019-08-29 08:32:16 +00:00
Fabio Tomat
1dc971d760 Update Friulian translation 2019-08-28 09:19:25 +00:00
Tim Sabsch
dcf0bf0bb1 Update German translation 2019-08-27 21:24:29 +00:00
Benjamin Berg
cf156b469c Notify service startup to systemd
Using the bus name to notify service startup to systemd has some
disadvantages. The main one being that systemd will consider a
gnome-shell restart (Alt+F2 r) a service failure and restart the shell,
cleaning up all its children (i.e. user launched applications). In the
future the shell should launch applications in their own transient unit
so that a service restart does not affect applications.

Another potential issue is that we must never load
gnome-shell-wayland.service and gnome-shell-x11.service at the same
time, as systemd does not like two services providing the same bus
name.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/690
2019-08-27 17:42:32 +00:00
Florian Müllner
da6c154ceb ci: Set XDG_RUNTIME_DIR for tests
Mutter's backend code depends on it being set.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/691
2019-08-27 15:30:51 +03:00
Florian Müllner
957fa910b3 st: Adjust theme test
Mutter's Clutter fork can no longer be initialized separatedly, as
its backend now draws from MetaBackend. Adjust the code to use the
newly added test initialization function instead to get the test
back up.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/691
2019-08-27 15:30:51 +03:00
Florian Müllner
8ac5be95d3 tests: Don't initialize Clutter
Clutter's backend code depends on MetaBackend now, which makes it
impossible to initialize without resorting to private mutter API.

Luckily we only need Clutter for interactive tests which are broken
anyway, as Clutter.main() and friends were removed a while ago.

So for now, get at least unit tests working again by simply the
unnecessary Clutter initialization.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/691
2019-08-27 15:30:51 +03:00
Ryuta Fujii
c27bd62106 Update Japanese translation 2019-08-27 11:26:32 +00:00
Ryuta Fujii
480e8b8842 Update Japanese translation 2019-08-27 10:45:55 +00:00
Florian Müllner
c6580421b3 shell-extension-tool: Fix typo
Spotted by Amr Ibrahim.
2019-08-27 12:16:27 +03:00
Jonas Dreßler
c2f5331187 pointerA11yTimeout: Create new PieTimer object for each timeout
Since we now put a short timeout in before the start of the actual pie
timer we don't start the timer as often as we used to. This allows us to
create a new PieTimer object each time a timeout is started and
therefore play a finish animation independently of other (new) timeouts.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/688
2019-08-27 08:03:49 +00:00
Jonas Dreßler
5d0c403f1d pointerA11yTimeout: Add a zoom out+fade animation on success
We currently don't indicate success of the pie timer at all, let's do
this by animating the circle's scale and fading it out at the same time.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/688
2019-08-27 08:03:49 +00:00
Jonas Dreßler
20fc4b4490 pointerA11yTimeout: Draw a clean circle if the pie is finished
If the circle is complete and the pie timeout finished, we don't need
the lines to the center point indicating the ends of the pie anymore.
We just draw a clean circle instead, which allows for a zoom-out and
fade animation of the circle when we're done.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/688
2019-08-27 08:03:49 +00:00
Jonas Dreßler
ea3f906f38 pointerA11yTimeout: Don't stop the pie timer if it finished successfully
If the pie timeout has finished successfully there's no need to cancel
the pie animation, instead we can just wait for that animation to finish
and show some visual feedback like a zoom-out animation to indicate the
click afterwards.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/688
2019-08-27 08:03:49 +00:00
Jonas Dreßler
2c4df6abcf pointerA11yTimeout: Fade the pie timer in
Fade the pie timer in using a duration of 1/4 of the timeout and a
EASE_IN_QUAD animation. This significantly reduces flickering of the pie
timer while moving the cursor and makes the timer less distracting.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/688
2019-08-27 08:03:49 +00:00
Jonas Dreßler
67a0b3b98e pointerA11yTimeout: Remove unused properties
Those properties were overlooked in 5cb02c1c, remove them now.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/688
2019-08-27 08:03:49 +00:00
Zander Brown
c366e9f3ca Update British English translation 2019-08-26 21:21:58 +00:00
Matej Urbančič
812a8552e5 Updated Slovenian translation 2019-08-26 22:20:53 +02:00
Fran Dieguez
069d7d6cac Update Galician translation 2019-08-26 15:22:53 +00:00
Daniel Mustieles
785a8b78b1 Updated Spanish translation 2019-08-26 12:26:03 +02:00
Jordi Mas
2d927639fe Update Catalan translation 2019-08-25 21:54:37 +02:00
Fran Dieguez
d5cad10181 Update Galician translation 2019-08-25 16:47:04 +00:00
Anders Jonsson
441a56b916 Update Swedish translation 2019-08-24 20:05:19 +00:00
Rūdolfs Mazurs
c2a6a6c939 Update Latvian translation 2019-08-24 16:21:58 +00:00
Piotr Drąg
15d1aee21a Update Polish translation 2019-08-23 18:41:05 +02:00
Asier Sarasua Garmendia
f1bc2d56f4 Update Basque translation 2019-08-23 07:18:19 +00:00
Asier Sarasua Garmendia
6f62965305 Update Basque translation 2019-08-22 21:45:29 +00:00
Jiri Grönroos
a6aa0ac74a Update Finnish translation 2019-08-22 16:36:37 +00:00
Daniel Mustieles
32ed4ee12e Updated Spanish translation 2019-08-22 15:06:34 +02:00
Danial Behzadi
33a48aecb7 Update Persian translation 2019-08-22 12:10:52 +00:00
Daniel Șerbănescu
3b63062a30 Update Romanian translation 2019-08-22 08:05:48 +00:00
Piotr Drąg
b680952197 Update POTFILES.in 2019-08-22 01:17:50 +02:00
Florian Müllner
a4ec460f96 Bump version to 3.33.91
Update NEWS.
2019-08-21 19:47:37 +00:00
Florian Müllner
5bd295842b extensionPrefs: Request correct GDK/GTK versions
gjs no longer has an implicit dependency on GTK 3.0, so without
requesting an explicit version, we will get the highest available.

Our code isn't GTK-4 ready, so request 3.0 explicitly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/686
2019-08-21 19:43:33 +02:00
Carlos Garnacho
db9a7ea7a9 shell: Ignore non-toplevels for ShellWindowTracker::tracked-windows-changed
Popups and other override-redirect windows are meaningless to everything
that depends on the ShellWindowTracker. Ignoring those windows will result
in less ShellApp::windows-changed signal emissions, and less activity in
the AppMenuButton and everything else that depends on them.

Reduces gnome-shell CPU activity while typing on the Epiphany addressbar,
as the pop up animation there results in a number of xdg_popup being
created and destroyed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/642
https://gitlab.gnome.org/GNOME/mutter/issues/556
2019-08-21 16:53:36 +00:00
Florian Müllner
490a62e781 shell-extension-tool: Turn into a small wrapper
Now that we have a replacement, deprecate the existing tool and make
it call out to the new one instead of implementing any functionality
on its own.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
d4b8912c0e extensions-tool: Add 'reset' command
Now that we allow to disable session mode extensions, it can be useful
to reset an extension to its original state, that is disabled in the
regular session, but possibly enabled via the session mode.

Add a corresponding command.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
532acf4c4a extensions-tool: Adjust enable/disable commands to shell changes
Change both 'enabled-extensions' and 'disabled-extensions' keys as in
commit ce1bee727. While those actions are now also exposed by the
shell's D-Bus API, there is some value in allowing the tool to be used
outside a running GNOME session (for example in setup scripts), so
keep changing the GSettings keys directly.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
7141c5be6d extensions-tool: Split out settings_list_add/remove helpers
With the addition of the 'disabled-extensions' key in commit ce1bee727,
the way extensions are enabled/disabled changed: Now a UUID is always
added to one list and removed from another.

Prepare for that by generalizing the relevant bits of the existing
enable/disable commands as helper functions.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
2df7757905 extensions-tool: Add 'uninstall' command
Uninstall is another action that can be useful from the command line,
so expose that as well.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
9d5c743a98 extensions-tool: Handle existing extension folder
g_file_make_directory_with_parents() returns an error if the directory
already exists (unlike g_mkdir_with_parents()), so it is currently
impossible to install more than a single extension, whoops.

Handle the error properly by just carrying on.

https://gitlab.gnome.org/fmuellner/gnome-extensions-tool/merge_requests/3
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
653e6c85bb extensions-tool: Add 'prefs' command
Easily launching an extension's preference dialog from the command
line can be quicker than using a UI like Tweaks or the extension
website, so add that functionality.

https://gitlab.gnome.org/fmuellner/gnome-extensions-tool/merge_requests/2
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
d9fa389079 extensions-tool: Add '--prefs' list option
We are about to add a 'prefs' command for launching an extension's
preference dialog. As that command only makes sense for extensions
that actually have preferences, shell completion should filter the
list of extensions accordingly. To allow that, add an appropriate
list option.

https://gitlab.gnome.org/fmuellner/gnome-extensions-tool/merge_requests/2
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
a429fdbd08 extensions-tool: Add 'install' command
The ability to install unaudited extensions directly from a zip file
can be useful for testing and code review, so implement a corresponding
command that complements the previously added 'pack' command.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
f9357457bf extensions-tool: Add new 'pack' command
Extensions are uploaded to extensions.gnome.org as zip files that
not only contain the extension sources, but also compiled GSettings
schemas and message catalogues. To make this more convenient, add
a corresponding command for creating an archive suitable for up-
loading.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
369e400e32 extensions-tool: Show Philip some info
Add a 'show' alias for the previously added 'info' command
because it makes sense:

https://twitter.com/pwithnall/status/1036895943004762112

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
07ad4d8911 extensions-tool: Add info command
We already support displaying extension details for the list command,
so it's a logical extension to also support showing extension info
for a particular extension (not least because the shell has a
corresponding D-Bus method).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
803a096b7e ci: Turn off man pages
There is little to test there, and excluding them slightly reduces the
dependencies in the CI image.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
1b40abe37a extensions-tool: Add a man page
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
0de5209cf1 extensions-tool: Add bash completion
Completions are clearly helpful, in particular for extension UUIDs
that are often lengthy strings containing random usernames.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
07fad38a50 extensions-tool: Add list options
In addition to a plain list of all extensions, add options to display
additional details of each extensions and to filter the list by
enabled state or install location.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
ac4b88f25d extensions-tool: Implement list command
Seeing at a glance which extensions are installed is surely useful,
so add a corresponding command.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
23a7aa5740 extensions-tool: Add create options
As we are using git-style command syntax, we can allow for data to be
provided on the command line rather than asking for it interactively.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
0b1e29e5e3 extensions-tool: Implement create command
This implements more functionality of the existing tool and, as
'reload' is an unreliable feature that doesn't work more often
than not, the last bit that we will replicate.

The command follows the original for the most part, with the most
important difference being the installed template, which doesn't
provide any sample functionality and uses modern JS syntax.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
c8c93b2a70 extensions-tool: Implement enable/disable commands
This replicates the most basic functionality of the existing
gnome-shell-extension-tool, albeit using a git/gio/gsettings
style command interface rather than plain options; this will
allow us to implement more complex commands that have options
on their own in the future.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Florian Müllner
d8c7cac536 extensions-tool: Start import
The gnome-extensions tool[0] was started as an external project, and
provides a replacement for the existing gnome-shell-extension-tool.
It was decided to ship the tool as part of the gnome-shell repository,
so start importing it with its history into a subdir.

[0] https://gitlab.gnome.org/fmuellner/gnome-extensions-tool

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
2019-08-21 18:28:02 +02:00
Jonas Dreßler
5cb02c1cb5 pieTimer: Use custom GObject property for animating pie
Before the move to Clutters implicit animations with 0846238f6 and
bf497ed64, we used Tweener to do a fake-animation of the opacity and
Tweeners `onUpdate` signal to queue a repaint of the PieTimer everytime
Tweener tries to update the animation.

Now, with Clutters implicit animations, there is no `onUpdate` signal
anymore and also `notify::opacity` no longer gets emitted since the
value doesn't actually change. This lead to the PieTimer no longer being
repainted, which broke the animation.

Fix this by implementing the current angle of the pie using a custom
GObject property `angle` and animating this property using the new
`actor.ease_property` method.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1533
2019-08-21 17:14:40 +02:00
Danial Behzadi
10c1df61cd Update Persian translation 2019-08-21 11:31:51 +00:00
Piotr Drąg
387e5ef0f1 Update Polish translation
Closes https://gitlab.gnome.org/Teams/Translation/pl/issues/4
2019-08-20 19:19:52 +02:00
Daniel Mustieles
f8f40f247f Updated Spanish translation 2019-08-20 12:43:51 +02:00
Jonas Ådahl
16cb918e0d shell-global: Set stage input region via MetaX11Display
The API in mutter changed to set it via MetaX11Display; lets jump on the
train.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/682
2019-08-19 09:20:44 +00:00
Jonas Ådahl
638b315e40 shell-global: Only sync input region if X11 session
We'd do an early out in the called functions eventually anyway.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/682
2019-08-19 09:20:44 +00:00
Aurimas Černius
a20b8dc1ad Updated Lithuanian translation 2019-08-18 22:05:31 +03:00
Jiri Grönroos
4370aee81e Update Finnish translation 2019-08-18 14:38:55 +00:00
Florentina Mușat
779e37fbd9 Update Romanian translation 2019-08-18 12:26:25 +00:00
Jonas Dreßler
6f4c5022eb iconGrid: Only add one onComplete callback for the animations
We only need a callback on the last animated actor, so no need to
register the callback for all actors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/678
2019-08-16 14:55:25 +00:00
Jonas Dreßler
b499ca47a3 iconGrid: Restore grid actors when cancelling animations
When cancelling the animations of the icon grid, right now we simply
destroy all the clones without resetting the opacity and making the
actor reactive again. So if the spring animation to show the grid is
cancelled by pressing a key to start a search, the icon clones would be
destroyed, but the icon-opacity would still be set to 0. Now if the
Escape key is pressed, viewSelector will show the last active page (ie.
the iconGrid) without a custom animation and only fade in the page, and
because the icons still have an opacity of 0, they will be invisible.

Fix this by always restoring the opacity and reactive property of the
original actors if the animation is cancelled instead of only destroying
the clones.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/678
2019-08-16 14:55:25 +00:00
Kukuh Syafaat
dc38e48202 Update Indonesian translation 2019-08-16 08:38:32 +00:00
Jordi Mas
7efdb97641 Update Catalan translation 2019-08-15 09:24:26 +02:00
Asier Sarasua Garmendia
14fd7c7532 Update Basque translation 2019-08-14 14:31:21 +00:00
Florian Müllner
21e14bd46f brightness: Ignore slider changes we initiated ourselves
Since we set the proxy value when the slider changes and set the slider
value on proxy property changes, we run into a cycle.

Before commit 3d3dca4aa this was addressed by not notifying on all slider
changes, but only in reaction to direct user action. Given that since the
splitting out of the BarLevel class those events are handled in a subclass,
that approach is at least unconvential and fairly fragile.

Instead, make the brightness indicator ignore any changes to the slider it
initiated itself.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1500
2019-08-13 16:35:17 +02:00
Florian Müllner
f0e1dc5715 slider: Do not notify on parent's behalf
Instead just use the regular property setter which since commit 3d3dca4aa
already emits the signal and queues a redraw.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1500
2019-08-13 16:35:17 +02:00
Florian Müllner
6b7af407e1 barLevel: Remove duplicated assignment
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1500
2019-08-13 16:35:17 +02:00
Anders Jonsson
d67c64af83 Update Swedish translation 2019-08-12 19:40:31 +00:00
Sveinn í Felli
5d2e5fe85a Update Icelandic translation
(cherry picked from commit 40db793230)
2019-08-12 07:47:40 +00:00
Asier Sarasua Garmendia
308da6ae53 Update Basque translation 2019-08-11 14:29:45 +00:00
Florian Müllner
76eceec1f5 Bump version to 3.33.90
Update NEWS.
2019-08-09 23:47:13 +02:00
Marco Trevisan (Treviño)
209d332a30 AppIcon: Nullify _draggable if available on destruction
When an AppIcon actor is destroyed we try to unset a non-existent draggable
property.

Fix the typo, doing this even if we're not currently in a drag operation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/677
2019-08-09 23:30:52 +02:00
Marco Trevisan (Treviño)
35dbc3fcc9 appDisplay: Disconnect Main item-drag signals on icons destruction
Icons connect to overview's item-drag events to react to start/end drags,
however the icons should disconnect from signals once destroyed.

So, disconnect from Main events once the actors have been destroyed.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/677
2019-08-09 23:30:52 +02:00
Jonas Dreßler
ada01507a4 viewSelector: Use onStopped callback when fading out pages
With 8b368d010 we fixed a bug where the onComplete callback was always
called no matter whether the transition was interrupted before or not.
This exposed another bug: viewSelector depends on this behaviour when
fading out pages: After fading out a page, we call `this._animateIn` to
show the new page. Now if the fade-out animation gets interrupted, with
the correct behaviour of onComplete we end up not showing a new page and
the viewSelector remains empty instead. One case where this happens is
when pressing a key to start a search during the overview-animation.

Obviously we also want to show the new page in case the fade-out
animation was interrupted, so use the onStopped callback instead of the
onComplete callback here.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/674
2019-08-09 21:02:58 +00:00
Marco Trevisan (Treviño)
826ac95726 environment: Don't use actor if an ease callback destroys it
An actor ease callback could destroy the actor, in such case we should do not
touch the actor anymore.

So, before calling the callback, reset restore the easing state and don't
perform any further action with it.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1507
2019-08-09 21:00:22 +00:00
Florian Müllner
9b7f228f8e src: Stop using g_get_current_time()
It isn't 2k38 safe and has therefore been deprecated. Replace it
with GDateTime or g_get_real_time() as appropriate.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/657
2019-08-09 19:22:18 +00:00
Florian Müllner
5d8ea4f9a3 main: Remove left-over variable
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/657
2019-08-09 19:22:18 +00:00
Georges Basile Stavracas Neto
4c89eac9a4 folderIcon: Properly reject drop
When a drop is rejected, we are mistakenly returning
true instead of false.

Return false when the rejecting the drop.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/671
2019-08-09 10:58:46 -03:00
Georges Basile Stavracas Neto
f76f30fd6a dnd: Fix drag cancel animation scale
When a drag is cancelled and the source actor
is visible, the drag actor is animated back to
the source position. The scale that the drag
actor will become is calculated as:

    scale = this._dragActor.width / sourceScaledWidth

However, this is wrong; what we wanted to do
is the opposite:

    scale = sourceScaledWidth / this._dragActor.width

Fix the scale calculation to match the math
above.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/671
2019-08-09 10:58:46 -03:00
Georges Basile Stavracas Neto
488d98289c appIcon: Create and delete folders with DnD
Create a new folder when dropping an icon over another
icon. Try and find a good folder name by looking into
the categories of the applications.

Delete the folder when removing the last icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/671
2019-08-09 10:58:45 -03:00
Georges Basile Stavracas Neto
ff3d32dd18 appIcon: Make AppIcon a drop target
Because the Dash icons are not drop targets themselves,
add a tiny DashIcon class, which is an AppDisplay.AppIcon
subclass, and disable all DND drop code from it.

Show a folder preview when dragging an app icon over another
app icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/671
2019-08-09 10:58:38 -03:00
Georges Basile Stavracas Neto
be6ce3c5b4 appIcon: Scale and fade itself when starting drag
As per design direction, scale and fade the app icon
when starting dragging it, and show it again if the
drop is accepted. Clutter takes care of animating the
rest of icon positions through implicit animations.

Scale and fade the dragged icon while it's being dragged.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/671
2019-08-09 10:58:38 -03:00
Jonas Dreßler
21966afbc6 search: Defer updating results on allocation changes until redraw
Since the `notify::allocation` signal will obviously get emitted while
the actor is inside an allocation cycle and we might end up doing
changes to its allocation inside `updateSearch` by hiding or showing the
actor (which queues a relayout), we get a warning from Clutter.

Fix this by delaying the call to the parent method until the next
redraw, which should happen a few moments after the current relayout.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/672
2019-08-08 17:37:12 +00:00
Jonas Dreßler
68e3f74ffd search: Don't use max number of results if allocation width is 0
Since commit 1a27ff6130 we use the
allocation width of the GridSearchResults actor to calculate the max
number of results that can be shown for this search provider.

On the first run of the search, when no previous (cached) allocation is
available for the actor of GridSearchResults, the allocation width used
in `_getMaxDisplayedResults` will be 0, which in turn will make
`updateSearch` filter out all results returned by the search provider.

Now if this search provider is the only search provider that's enabled,
after calling `updateSearch`, the `SearchResults` class will call
`_updateSearchProgress` to check if any results are visible, assume
nothing was found and therefore hide the scrollView. This in turn causes
the GridSearchResults actor to not get a new allocation, which prevents
our code to fixup the max number of results on `notify::allocation` from
working: The number will continue to be 0 and we'll never show any
results.

To fix this regression, return -1 in `_getMaxDisplayedResults` if the
allocation width is 0 to inform `updateSearch` that we can't calculate
the maximum number yet and interpret a return value of -1 as "show all
results" in `updateSearch`. The same problem would probably also appear
if the allocation width is anything between 0 and the width of the
iconGrid with one icon in it, although this might as well be a valid
width in case a very small screen is used or with very large icons. So
let's only check for a width of 0 and hope the GridSearchResults actor
won't get weird temporary allocations in that range.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/672
2019-08-08 17:37:12 +00:00
Jonas Dreßler
87f5aa7a13 appDisplay: Animate activate-discrete-gpu action in the AppIconMenu
Just as we animate the apps launch using the zoom out animation if the
'new-window' action provided by the app is launched, we should also show
this animation if the 'activate-discrete-gpu' action provided by the app
via its AppInfo is launched.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/673
2019-08-08 16:48:48 +00:00
Jonas Dreßler
1dadbd0cbb appDisplay: Always animate our own new window and discrete gpu actions
For the "New Window" entry we add to the AppIcons popup menu we should
always animate the app icon if the menu entry is activated as it was
intended by commit 62786c09a8.

For the "Launch using Dedicated Graphics Card" entry we can also always
show the animation if the entry is activated since the entry should only
be visible if the app is stopped.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/673
2019-08-08 16:48:48 +00:00
Florian Müllner
481490fdc7 util: Remove AppSettingsMonitor
It is now unused.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158
2019-08-08 17:41:46 +02:00
Florian Müllner
3114a24d1f dateMenu: Stop accessing app settings directly
Clocks has exactly the same issue as Weather: Its integration currently
relies on accessing its settings directly, which isn't possible when
the app is sandboxed.

Fix this the same way we did for Weather, by adding our own setting
and syncing it with the app via a custom D-Bus interface.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158
2019-08-08 17:41:46 +02:00
Jonas Dreßler
73850fee02 appDisplay: Animate launch of new-window action in the AppIconMenu
We add our own "New Window" menu entry if the app doesn't already
provide a 'new-window' action. For this menu entry, we show the zoom out
animation on the app icon when the user clicks the entry.

To be consistent in case the app already provides its own 'new-window'
action via its AppInfo, also show the zoom out animation when this
action is activated.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/662
2019-08-08 15:28:48 +00:00
Georges Basile Stavracas Neto
c0047cd11d shell/app-system: Monitor for icon theme changes
Whenever an app is installed, the usual routine is
to run 'gtk-update-icon-cache' after installing all
of the app's files.

The side effect of that is that the .desktop file of
the application is installed before the icon theme
is updated. By the time GAppInfoMonitor emits the
'changed' signal, the icon theme is not yet updated,
leading to StIcon use the fallback icon.

Under some circumstances (e.g. on very slow spinning
disks) the app icon is never actually loaded, and we
see the fallback icon forever.

Monitor the icon theme for changes when an app is
installed. Try as many as 6 times before giving up
on detecting an icon theme update.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661
2019-08-08 15:22:44 +00:00
Georges Basile Stavracas Neto
dd9a452594 st/texture-cache: Monitor GtkIconTheme changes
The texture cache, right now, only monitors for
complete theme changes. If the contents of the
icon theme change, however, the texture cache
isn't properly invalidated.

This manifests itself as a randomly reproducible
bug when installing an app; the app icon may be
the fallback forever, or as long as something else
updates the icon theme.

Watch for the GtkIconTheme:changed signal, and
evict the texture cache when the theme changes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661
2019-08-08 15:22:44 +00:00
Georges Basile Stavracas Neto
e45c917811 controlsManager: Don't fade icon grid while dragging
As pointed out by designers, fading it signals that the
icon grid is not a drop target, when now it actually is.

Remove the fade effect applied to the icon grid when
dragging. Since this is the only caller of fadeIn() and
fadeHalf(), also remove these methods.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:12:00 -03:00
Georges Basile Stavracas Neto
fd19906c64 allView: Scale in when moving icons from folders
App icons inside folders are already animated when the folder is
opened, but moving an app icon from a folder doesn't, making the
transition abrupt.

Fortunately, it's easy to detect icons that were previously hidden
but are not anymore.

Add an animation to these icons when showing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:12:00 -03:00
Georges Basile Stavracas Neto
54a2773046 folderIcon: Add visual drag-over feedback
WIP: This is not exactly what was discussed on IRC, but
it's looking alright as a first iteration. Design feedback
welcomed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:11:59 -03:00
Georges Basile Stavracas Neto
ec8b7bc7b2 allView: Remove icon from folder when dropping outside
When dropping an app icon to outside the folder, remove the
app from that folder. GNOME Shell is already smart enough
to figure out the setting changes and update the icons.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:11:59 -03:00
Georges Basile Stavracas Neto
ea71172d44 allView: Switch pages when dragging above or below the grid
This is necessary for being able to drag application icons
to folders in different pages.

Add a drag motion handler to AllView and handle overshoots
when dragging. Only handle it when dragging from AllView.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:11:59 -03:00
Georges Basile Stavracas Neto
5dfa620f86 folderIcon: Update folder icon after dropping
After dropping an application into the folder icon, the
list of applications is updated but the folder icon itself
is not.

Introduce BaseIcon.update() and call it from FolderIcon
when redisplaying.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:11:59 -03:00
Georges Basile Stavracas Neto
09d5f0779d folderIcon: Allow dropping application icons
Connect to the overview signals related to Drag n' Drop, and
allow dropping application icons in it. Dropping an icon
appends the application id to the folder's GSettings key.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:11:56 -03:00
Georges Basile Stavracas Neto
d1880dc987 appDisplay: Add event blocker inhibition API
The event blocker is an actor that is added in between the
icon grid and the app folder popup in order to guarantee
that clicking outside the app folder will collapse it.

However, the next patch will require allowing dragging events
to be passed to folder icons, and the event blocker gets in
our way here, preventing drag n' drop to work properly.

Add an API to inhibit the event blocker. This API will be
used by the app folders while an item is dragged.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/664
2019-08-08 09:09:46 -03:00
Florian Müllner
928b49705f systemActions: Create SensorProxy unconditionally
When plugging in a device with sensors that are unsupported by
iio-sensor-proxy, the proxy may quit so fast that the name disappears
from the bus before we get to construct the SensorProxy in response
to the name-appeared handler, resulting in the following warning:

JS ERROR: TypeError: this._sensorProxy is null
_sensorProxyAppeared/this._sensorProxy<@resource:///org/gnome/shell/misc/systemActions.js:217:17
_makeProxyWrapper/</<@resource:///org/gnome/gjs/modules/overrides/Gio.js:243:21

Address this by creating the proxy unconditionally instead of monitoring
the bus name, and using the g-name-owner property to determine whether
iio-sensor-proxy is active.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1357
2019-08-08 11:42:28 +00:00
Sergey Bugaev
f50cac3005 workspace: Sort windows to minimize travel distance
When transitioning to or from the overview, windows travel
a certain distance between their real desktop position and
their place in the overview window grid. The less this travel
distance is, the smoother, more polished, and less jarring
the overall transition looks. This is why it makes sense to
try reordering and repositioning windows to minimize their
travel distance. That being said, there are other factors
that impact the quality of the overview layout, such as how
much the windows get scaled and what portion of the overall
available space they take up.

The existing code tries to minimize the travel distance by
sorting the windows in each row by their horizontal position.
There are, however, two problems with this implementation.
First, it compares the coordinates of windows' left edges as
opposed to their centers, which means it yields unexpected
results when a small window is positioned next to the left
edge of a large window. Second, it completely disregards
vertical coordinates, instead assigning windows to the grid
rows using their monotonically increasing window numbers,
effectively vertically sorting them by the order they were
created in.

This commit changes both vertical and horizontal ordering
to work based on the coordinates of the geometric centers
of the windows. That is to say, windows are first assigned
to grid rows based on the vertical coordinates of their
centers, and subsequently sorted inside each row based on
the horizontal coordinates of said centers. In my testing,
this leads to a much more intuitive and visually pleasing
window placement.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/267
2019-08-08 13:13:35 +02:00
Florian Müllner
ec6e1315a5 weather: Pick up original settings values
We mirror Weather's location settings to not depend on the app running,
but then don't read the original values, oops.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158
2019-08-07 18:53:41 +00:00
Florian Müllner
ad55cb6d5d weather: Fix warning on closing Weather
GDBusProxy::g-properties-changed is also emitted when the name drops from
the bus, at which point any properties will be null. That's not a valid
gsettings value, so to avoid the corresponding warning, move the g-name-owner
check accordingly.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158
2019-08-07 18:53:41 +00:00
Florian Müllner
0ce0376725 docs: Update animation section
Replace the existing Tweener section with a small outline of the
Clutter animation API and our wrappers.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:49 +02:00
Florian Müllner
015ca2c507 lookingGlass: Remove Tweener from preimported modules
We want to encourage using Clutter's implicit animations directly,
so stop importing the discouraged animation framework by default.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:49 +02:00
Florian Müllner
21e752e5e4 keybindings: Remove pause-resume-tweens shortcut
It is no longer useful since we replaced Tweener.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:49 +02:00
Florian Müllner
1e20a1249a dnd: Stop using getTweenCount()
Those checks were carried over from the very first DND implementation;
if they were ever actually required at all, this is no longer the case
as we moved away from Tweener for all our animations.

The number of cases where an extension is still using Tweener, creates
draggable actors, *AND* requires the checks for proper functioning
should be indistinguishable from zero, so drop the code.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:49 +02:00
Florian Müllner
b67c300484 js: Use Clutter transitions for adjustment changes
This concludes our quest of moving from Tweener to Clutter's
animation framework.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:49 +02:00
Florian Müllner
8ac2086ed1 environment: Add convenience method for adjustment transitions
By now, Tweener is used exclusively to animate changes to the
StAdjustment:value property. But not for long, as now that we
implement the same transition API as Clutter.Actor, we can
re-use the existing convenience method for property transitions
for adjustment changes as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:49 +02:00
Florian Müllner
72defaa97e st: Use StAdjustment's new transition API
Now that the adjustment itself can be used to track its transitions,
do that for animating the scroll bar handle.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:47 +02:00
Florian Müllner
9097c5e9c0 st: Add transition API to StAdjustment
StAdjustment implements the ClutterAnimatable interface, so we can
already animate its properties with ClutterPropertyTransitions.

But as it is currently not possible to associate a transition with
an adjustment, it must be owned (and kept alive in case of GC) by
the calling code.

Change that by implementing the same (add|remove|get)_transition() API
as ClutterActor, so we can use a familiar API and even duck typing in
case of javascript.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
2019-08-07 18:40:44 +02:00
Florian Müllner
79b54f65b4 volume: Fix overdrive in slider
When setting a maximum value above 1, we currently set a non-existant
maximum_level property instead of the actual 'maximum-value' one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/670
2019-08-07 16:17:45 +00:00
Florian Müllner
52c2417685 barLevel: Fix value range
The range is usually within [0, 1], but since we support overdrive
as well, the upper limit must be the maximum value we allow for
overdrive.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/670
2019-08-07 16:17:45 +00:00
Florian Müllner
9073debe60 environment: Remove transition tracking
The tracking was important in an earlier iteration, but as the helper
functions now remove overwritten transitions before setting up the
new ones, we can just as well connect to the ::stopped signal directly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/668
2019-08-07 02:40:17 +02:00
Florian Müllner
8b368d010f environment: Fix transition callback
This is rather embarrassing - we currently confuse the transition with
the finished parameter, which means we always run the onComplete handler
no matter whether the transition was interrupted or actually completed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/668
2019-08-07 02:40:13 +02:00
Georges Basile Stavracas Neto
8b97a06961 allView: Always update currentPage
Commit 0f178c3b3d added a shortcirtuit to avoid running
an animation on an invisible actor. However, it introduced
a bug where the current page is not properly updated. That
leads to the wrong set of icons being animated under some
circumstances.

Update the current page even if we bail out early.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/667
2019-08-06 21:09:13 -03:00
Florian Müllner
fffe7bdf9c js: Ease non-animatable actor properties
Properties that aren't marked as animatable don't support *implicit*
animations, but they can still be animated with explicit transitions.
Use the newly added convenience method to cut down further on Tweener
usage.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
2019-08-06 23:54:29 +02:00
Florian Müllner
ef18f621ac environment: Add convenience method for property transitions
While we are now using implicit animations for all animatable properties,
there are still some cases where we animate other actor properties (for
example from a custom subclass) or associated objects like effects.

Those can still be animated using Clutter animations, as long as we use
the explicit API rather than implicit animations. Again this API is
cumbersome and tricky enough to warrant a convenience wrapper.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
2019-08-06 23:54:29 +02:00
Florian Müllner
dfa41f6926 js: Use GObject properties for animated properties
Clutter animations work on GObject properties on animatables. The
last commit took care of the latter by turning all animated objects
into actor subclasses, now it's time to make all properties used
in Tweens into GObject properties.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
2019-08-06 23:54:29 +02:00
Florian Müllner
3d3dca4aa2 js: Actorize animated objects
We have a couple of places where we don't tween the actor, but a
custom property on the delegate object. In order to move those
to Clutter animations, we will need an animatable, so turn those
objects into widget subclasses.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
2019-08-06 23:54:29 +02:00
Florian Müllner
928595fe21 windowManager: Change effect's brightness property
The set_brightness() method is the most convenient way of controlling
the effect's brightness, but Clutter animations only deal with properties,
so start using the (ClutterColor) brightness property instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
2019-08-06 23:54:29 +02:00
Florian Müllner
fc958f4215 windowManager: Move animation into WindowDimmer
Currently WindowDimmer exposes a JS property that is used to control the
underlying effect. This works fine with Tweener, but not with Clutter
animations which we want to use ultimately.

As a first step towards that, expose a setDimmed() method instead of
the property and handle the animation internally, so it can be adapted
more easily.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
2019-08-06 23:54:29 +02:00
Florian Müllner
0846238f69 js: Use implicit animations for animatable properties
We now have everything in place to replace Tweener for all animatable
properties with implicit animations, which has the following benefits:

 - they run entirely in C, while Tweener requires context switches
   to JS each frame

 - they are more reliable, as Tweener only detects when an animation
   is overwritten with another Tween, while Clutter considers any
   property change

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 23:54:29 +02:00
Florian Müllner
007b6ca2e8 environment: Add convenience method for implicit animations
Setting up implicit animations is more verbose than using tweener, in
particular when setting up a callbacks to run on overwrite or completion.
In order to make its use more convenient, monkey-patch ClutterActor
with an ease() method that works similarly to Tweener.addTween().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
0b4a4487a0 environment: Support slow down factor when easing
Being able to slow down animations is a helpful debugging tool; to not
lose it when starting to use Clutter's implicit animations, monkey-patch
the appropriate methods to support our global slow down factor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
99b4e047dd tweener: Use new adjustAnimationTime() helper
Now that we have a new helper function for adjusting animation times,
make Tweener use it so that we keep the code in a single place.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
ae2af34453 environment: Add adjustAnimationTime() helper
As we currently use Tweener for all animations, we have a single place
for hooking up the enable-animations and slow-down-factor settings.
However that will no longer hold true when we'll start to use Clutter's
built-in animation facilities, so add a small helper function that
applies the necessary adjustments.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
fdf24ceecc messageTray: Stop tweening custom opacity property
Notifications use a transition that overshoots the target value, however
we can only really do that for the position and not the opacity where
some values would end up out of the valid range.

We currently address this by proxying the actual opacity property in a
javascript property, and clamp it to the valid range in an onUpdate()
callback.

This won't be an option if we want to use Clutter animations, so instead,
use separate tweens for opacity and position.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
870dd84a50 pageIndicators: Defer IN animation until redraw
Unlike Tweener, which doesn't know or care about actor state, Clutter
will skip implicit animations on actors that aren't mapped. This makes
sense of course, but it will break the page indicator animation we
do on map: When we get notified about the container being mapped, the
individual indicators (which are the actors being animated) are still
unmapped.

Resolve this by deferring the animation to a LaterFunc.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
5d6db923b7 screenShield: Stop using custom transition
For animating the arrows on the screenshield, we currently use a custom
transition function that tweens the opacity from 0 to maxOpacity in the
first half of the animation, and from maxOpacity back to 0 in the second
half.

This doesn't easily translate to Clutter's own animation framework, so
replace the custom transition with two consecutive tweens which do.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
8eb88d17fe dash: Directly tween actors
Dash items are currently animated via the custom "childScale" and
"childOpacity" properties. However since commit efb3025d8c, those
properties actually control the scale-x/scale-y and opacity properties
of the actor itself (not the child), so cut out the intermediate
custom properties in favor of the "real" ones.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
abe012b9fc ripple: Split animation
Similar to the previous patch, splitting the existing tween into two
will allow us to use implicit animations.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
749f52fc8b popupMenu: Split submenu expansion and arrow rotation
When expanding a submenu, we currently use a single tween to animate
both the submenu actor and the source arrow. We do this by tweening
a monkey-patched JS property on the main actor, which we then use
to update the arrow's GObject property on updates. As Clutter cannot
animate random JS properties, this trick will prevent us from using
implicit animations here.

The only reason I can think of for using a single tween is to keep
both animations in perfect lock step, but as expansion and rotation
are visually quite distinct, this shouldn't be required, so just
set up separate animations for each actor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22
2019-08-06 20:50:43 +02:00
Florian Müllner
1e6cb43815 shell-app: Consider desktop actions in can_open_new_window()
We currently only consider a remote "app.new-window" action when running,
but not a fixed "new-window" action in the .desktop file. The latter is
clearly useful as well, in particular as open_new_window() already does,
so add it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/665
2019-08-06 15:04:24 +02:00
Florian Müllner
213d10bf4e messageTray: Drop tween helper function
It makes the code harder to follow and saves little in terms of code
duplication.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
1abfbb82c5 windowManager: Small cleanup
We start with a dim factor of 0, so the syncEnabled() call in the
constructor will always disable the effect. Just create the effect
disabled and save the method call.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
bf36d99a33 barLevel: Don't reset value on overview-start changes
While it makes sense to cap the current value to a new maximum value,
I can't think of a good reason why changing the overdrive-start should
reset the current value to that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
3ee525833e loginDialog: Use GObject bindings over onUpdate handler
Instead of iterating over all actors each frame and sync'ing their
opacities, we can set up bindings once before the animation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
bf497ed643 pointerA11yTimeout: Use notify handler instead of onUpdate callback
We either need to queue a repaint on opacity updates or we don't,
whether the opacity change happens in an animation or not shouldn't
matter.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
9b8c0f7519 pointerA11yTimeout: Fix style nit
There's a stray space after the opening parentheses. While at it,
reindent the object literal.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
12ec5d1cbe switcherPopup: Avoid unnecessary animation
Ever since commit 28bb0c1fb2, the popup's actual visibility has been
controlled by its :opacity property, not :visible.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Florian Müllner
0f178c3b3d appDisplay: Skip animation when hidden
The time computation isn't just unnecessary in that case, it's likely
wrong as well: If we don't have a valid allocation, we may well end
up with a negative value, NaN or Infinity.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654
2019-08-06 14:52:41 +02:00
Kukuh Syafaat
9aa06e3001 Update Indonesian translation 2019-08-06 10:49:56 +00:00
Georges Basile Stavracas Neto
00ec8ca989 allView: Redisplay on folder changes
Now that redisplaying is a lightweight operation that only
adds and removes what changed, we can not be concerned about
redisplaying on folder changes.

Redisplaying will be necessary when custom order in the app
grid is implemented, in order to update not only which icons
are hidden, but also their position.

Call _redisplay() in AllView when folders change.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:20:31 -03:00
Georges Basile Stavracas Neto
9c6f558c9e baseAppView: Remove unused BaseAppView.addItem
Now that BaseAppView does not allow for subclasses to add
and remove items directly, the addItem() method can be
removed.

Remove BaseAppView.addItem().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:20:31 -03:00
Georges Basile Stavracas Neto
1c172955ee allView, folderView: Only add icons once
FolderView and AllView currently check if the item is
present in the BaseAppView._items map, in order to avoid
adding the same icon multiple times.

Now that BaseAppView._loadApps() has a different role --
it returns a list with all app icons, and BaseAppView
diffs with the current list of app icons -- checking the
BaseAppView._items map is wrong.

Make sure there are no duplicated items in the temporary
array returned by all _loadApps() implementations. Remove
the now unused BaseAppView.hasItem() method.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:20:31 -03:00
Georges Basile Stavracas Neto
1d44bf7ce6 baseAppView: Only add and remove when necessary
BaseAppView currently removes all icons, and readds them, every
time the list of app icons needs to be redisplayed. In order to
allow animating app icon positions in the future, however, we
cannot destroy the actors of the app icons.

Previous commits paved the way for us to do differential loading,
i.e. add only the icons that were added, and remove only what was
removed.

Make the BaseAppView effectively implement differential loading.
The BaseAppView.removeAll() method is removed, since we do not
remove all icons anymore. BaseAppView._loadApps() now returns an
array with the new apps, instead of putting them directly at the
BaseAppView lists.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:20:29 -03:00
Georges Basile Stavracas Neto
036e41621d baseAppView: Move _loadGrid() into _redisplay()
Next commit will introduce differential loading of
app icons, and will reorganize this part of the
codebase.

When doing that, the ideal symmetry of the new code
would be:

 * Update BaseAppView._allItems array
 * Update BaseAppView._items map
 * Update BaseAppView._grid actor

Move the code in _loadGrid() into _redisplay() so that
we can check in-place which new icons need to be added.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:19:26 -03:00
Georges Basile Stavracas Neto
3003e9091d baseAppView: Call loadGrid() directly
Now that the three views follow the exact same loading routine
(remove all + load apps + load grid), we don't need each view
call loadGrid() directly anymore.

This is an important step in order to animate adding and removing
icons, since now we can diff old and new app icons properly.

Move all calls to BaseAppView.loadGrid() to a single one after
BaseAppView._loadApps(). Also add the underscore prefix, since
this is now considered a protected function.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:19:25 -03:00
Georges Basile Stavracas Neto
8d9da10710 frequentView: Use BaseAppView.addItem() and loadGrid()
FrequentView is another view that is slightly not unified with how
BaseAppView expects subclasses to load app icons. Instead of using
BaseAppView.addItem() and then calling BaseAppview.loadGrid(), it
adds the app icons directly to the icon grid.

Make FrequentView add icons using BaseAppview.addItem(), and load
the icons using BaseAppView.loadGrid().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:19:25 -03:00
Georges Basile Stavracas Neto
4d23c12028 folderIcon: Move app icon loading to FolderView
Future patches will diff the old and new icons of views, in order to
animate them when necessary (e.g. adding an app icon to a folder, or
from a folder back to the app grid). In order to do that, all views
must be streamlined in how they load app icons.

Currently, FrequentView and AllView are already following the behavior
expected by BaseAppView, but FolderView isn't. Its icons are loaded by
FolderIcon, and FolderView doesn't implement BaseView._loadApps(),
which makes it impossible to diff old and new apps.

Move the app icon loading routine from FolderIcon to FolderView, by
implementing the _loadApps() method.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-05 21:19:24 -03:00
Florian Müllner
476816732f cleanup: Use milliseconds for animation times
The different units - seconds for Tweener and milliseconds for
timeouts - are not a big issue currently, as there is little
overlap. However this will change when we start using Clutter's
own animation framework (which uses milliseconds as well), in
particular where constants are shared between modules.

In order to prepare for the transition, define all animation times
as milliseconds and adjust them when passing them to Tweener.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/663
2019-08-05 21:55:20 +00:00
Benjamin Berg
31968ea53c meson: Avoid using relative paths to po directory
Replace the relative path to the po directory with a toplevel definition
of po_dir and use that instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/507
2019-08-05 21:38:51 +00:00
Benjamin Berg
7e00d22bfa data: Update systemd units
The existing units were never used as the corresponding support was
never merged into gnome-session.

This commits updates units to be usable with the newer gnome-session
unit definitions. Also added is appropriate failure/restart logic
including the ability to disable extensions. Note that extensions will
only be disabled if a failure happens in the first two minutes after
login.

https://gitlab.gnome.org/GNOME/gnome-session/merge_requests/13
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/507
2019-08-05 21:38:51 +00:00
Benjamin Berg
50055004f5 data: Flag in desktop file that gnome-shell can be started using systemd
As gnome-shell is a required component for GNOME sessions, gnome-session
will currently always try to autostart it. However as we are moving towards
using systemd's user instance for session startup, gnome-session should only
be responsible for launching the shell when either not running under systemd
or when we were built without systemd support.

gnome-session can detect the former but not the latter, so communicate this
via the newly added X-GNOME-HiddenUnderSystemd key in the .desktop file.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/507
https://gitlab.gnome.org/GNOME/gnome-session/merge_requests/13
2019-08-05 21:38:51 +00:00
Anders Jonsson
abe2f07779 Update Swedish translation 2019-08-05 20:41:06 +00:00
Daniel Șerbănescu
277f0d77f3 Update Romanian translation 2019-08-04 13:09:14 +00:00
Daniel Mustieles
01d2ad760a Updated Spanish translation 2019-08-02 09:14:52 +02:00
Jor Teron
25f118bf2c Update Karbi translation 2019-08-02 07:12:56 +00:00
182 changed files with 35165 additions and 18495 deletions

View File

@@ -54,7 +54,7 @@ build:
- meson mutter mutter/build --prefix=/usr -Dtests=false
- ninja -C mutter/build install
script:
- meson . build -Dbuiltype=debugoptimized
- meson . build -Dbuiltype=debugoptimized -Dman=false --werror
- ninja -C build
- ninja -C build install
<<: *only_default
@@ -67,6 +67,8 @@ build:
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: test
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
before_script:
- ninja -C mutter/build install
script:

View File

@@ -66,6 +66,10 @@ create_common() {
rm $OUTPUT_FINAL.tmp
}
# Disable MR handling for now. We aren't ready to enforce
# non-legacy style just yet ...
unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
@@ -86,12 +90,16 @@ run_eslint LEGACY
echo Done.
create_common
if ! is_empty $OUTPUT_FINAL; then
cat $OUTPUT_FINAL
exit 1
fi
# Just show the report and succeed when not testing a MR
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
cat $OUTPUT_FINAL
exit 0
fi
copy_matched_lines $OUTPUT_FINAL $LINE_CHANGES $OUTPUT_MR
copy_matched_lines $OUTPUT_REGULAR $LINE_CHANGES $OUTPUT_MR
cat $OUTPUT_MR
is_empty $OUTPUT_MR

View File

@@ -84,7 +84,6 @@ don't use.
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
```
The alphabetical ordering should be done independently of the location of the
@@ -277,34 +276,49 @@ If your usage of an object is like a hash table (and thus conceptually the keys
can have special chars in them), don't use quotes, but use brackets: `{ bar: 42
}`, `foo['bar']`.
## Getters, setters, and Tweener
## Animations
Most objects that are animated are actors, and most properties used in animations
are animatable, which means they can use implicit animations:
Getters and setters should be used when you are dealing with an API that is
designed around setting properties, like Tweener. If you want to animate an
arbitrary property, create a getter and setter, and use Tweener to animate the
property.
```javascript
var ANIMATION_TIME = 2000;
var MyClass = class {
constructor() {
this.actor = new St.BoxLayout();
this._position = 0;
}
get position() {
return this._position;
}
set position(value) {
this._position = value;
this.actor.set_position(value, value);
}
};
let myThing = new MyClass();
Tweener.addTween(myThing,
{ position: 100,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
moveActor(actor, x, y) {
actor.ease({
x,
y,
duration: 500, // ms
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
```
The above is a convenience wrapper around the actual Clutter API, and should generally
be preferred over the more verbose:
```javascript
moveActor(actor, x, y) {
actor.save_easing_state();
actor.set_easing_duration(500);
actor.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
actor.set({
x,
y
});
actor.restore_easing_state();
}
```
There is a similar convenience API around Clutter.PropertyTransition to animate
actor (or actor meta) properties that cannot use implicit animations:
```javascript
desaturateActor(actor, desaturate) {
let factor = desaturate ? 1.0 : 0.0;
actor.ease_property('@effects.desaturate.factor', factor, {
duration: 500, // ms
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
```

77
NEWS
View File

@@ -1,3 +1,80 @@
3.34.0
======
* Handle startup/shutdown of misc X11 services [Carlos; !680]
* Fix sound volume mute/unmute [Iain; #1557]
* Correctly terminate pasted text [Carlos; #1570]
Contributors:
Carlos Garnacho, Iain Lane
Translators:
Tom Tryfonidis [el], Milo Casagrande [it], Ryuta Fujii [ja],
Efstathios Iosifidis [el], Carmen Bianca BAKKER [eo], Sabri Ünal [tr],
Dušan Kazik [sk], Balázs Meskó [hu], Claude Paroz [fr]
3.33.92
=======
* Animate pointer a11y pie timer [Jonas D.; !688]
* Fix restarting shell in systemd user session [Benjamin; !690]
* Misc. bug fixes and cleanups [Florian, Jonas D., Jonas Å., Will;
!691, !689, !692, #1552, !698]
Contributors:
Jonas Ådahl, Benjamin Berg, Piotr Drąg, Jonas Dreßler, Florian Müllner,
Will Thompson
Translators:
Daniel Șerbănescu [ro], Danial Behzadi [fa], Daniel Mustieles [es],
Jiri Grönroos [fi], Asier Sarasua Garmendia [eu], Piotr Drąg [pl],
Rūdolfs Mazurs [lv], Anders Jonsson [sv], Fran Dieguez [gl], Jordi Mas [ca],
Matej Urbančič [sl], Zander Brown [en_GB], Ryuta Fujii [ja], Tim Sabsch [de],
Fabio Tomat [fur], Pawan Chitrakar [ne], A S Alam [pa], Changwoo Ryu [ko],
Aurimas Černius [lt], Daniel Rusek [cs], Marek Černocký [cs],
Kukuh Syafaat [id], Goran Vidović [hr], Rafael Fontenelle [pt_BR]
3.33.91
=======
* Fix regression when adjusting brightness [Florian; #1500]
* Fix pointer a11y timeout animation [Jonas D.; #1533]
* Add new extensions CLI tool [Florian; #1234]
* Only track top-level windows [Carlos; #556]
* Misc. bug fixes and cleanups [Jonas D., Jonas Å., Piotr, Florian;
!678, !682, !686]
Contributors:
Jonas Ådahl, Jonas Dreßler, Carlos Garnacho, Florian Müllner
Translators:
Asier Sarasua Garmendia [eu], Sveinn í Felli [is], Anders Jonsson [sv],
Jordi Mas [ca], Kukuh Syafaat [id], Florentina Mușat [ro], Jiri Grönroos [fi],
Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl],
Danial Behzadi [fa]
3.33.90
=======
* Implement DND app picker folder management [Georges; !643, !645, !664, !671]
* Make Clocks/Weather integration work with sandboxed apps [Florian; #1158]
* Support startup via systemd user instance [Benjamin; !507]
* Replace Tweener with Clutter animations [Florian; !663, !22, !666, !668, !669]
* Minimize travel distance in overview animation [Sergey; !267]
* Rescan icon theme when installed apps changed [Georges; !661]
* Consistently animate new window actions [Jonas; !662, !673]
* Misc. bug fixes and cleanups [Florian, Daniel, Ray, Bastien, Jonas, Niels,
Marco, Georges; !635, !636, !637, #1462, !628, !640, !641, !627, !644, !647,
!385, #1474, !651, #1144, !646, !653, !652, !655, #1482, !656, $654, !665,
!667, !670, #1357, !672, !657, #1507, !674, !677]
Contributors:
Benjamin Berg, Sergey Bugaev, Jonas Dreßler, Niels De Graef, Florian Müllner,
Georges Basile Stavracas Neto, Bastien Nocera, Ray Strode,
Marco Trevisan (Treviño), verdre, Daniel van Vugt
Translators:
Asier Sarasua Garmendia [eu], Rafael Fontenelle [pt_BR],
Kristjan SCHMIDT [eo], Jor Teron [mjw], Daniel Mustieles [es],
Kukuh Syafaat [id], Jordi Mas [ca], Fabio Tomat [fur], Daniel Șerbănescu [ro],
Anders Jonsson [sv]
3.33.4
======
* Fix unintentional interference between gestures [Jonas; !598]

View File

@@ -0,0 +1,15 @@
<node>
<!--
org.gnome.Shell.ClocksIntegration:
@short_description: Clocks integration interface
The interface used for exporting location settings to GNOME Shell's
world clocks integration.
-->
<interface name="org.gnome.Shell.ClocksIntegration">
<property name="Locations" type="av" access="read"/>
</interface>
</node>

View File

@@ -40,6 +40,7 @@
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.CalendarServer.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.ClocksIntegration.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file>

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Disable GNOME Shell extensions after failure
DefaultDependencies=no
# Only disable extensions for a short period of time after login.
# This means we err on the side of failing the first login after a broken
# extension was installed.
Requisite=gnome-session-stable.timer
[Service]
Type=simple
# Disable extensions
ExecStart=gsettings set org.gnome.shell disable-user-extensions true
Restart=no

View File

@@ -0,0 +1,27 @@
[Unit]
Description=GNOME Shell on Wayland
# On wayland, force a session shutdown
OnFailure=gnome-shell-disable-extensions.service gnome-session-shutdown.target
OnFailureJobMode=replace-irreversibly
CollectMode=inactive-or-failed
RefuseManualStart=on
RefuseManualStop=on
After=gnome-session-manager.target
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
# The units already conflict because they use the same BusName
#Conflicts=gnome-shell-x11.service
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On wayland we cannot restart
Restart=no
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@@ -1,5 +1,10 @@
[Unit]
Description=GNOME Shell (wayland sync point)
After=gnome-shell.service
BindsTo=gnome-shell.service
Conflicts=gnome-shell-x11.target
Description=GNOME Shell on Wayland
DefaultDependencies=no
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
Requires=gnome-shell-wayland.service
After=gnome-shell-wayland.service

View File

@@ -0,0 +1,33 @@
[Unit]
Description=GNOME Shell on X11
# On X11, try to show the GNOME Session Failed screen
OnFailure=gnome-shell-disable-extensions.service gnome-session-failed.target
OnFailureJobMode=replace
CollectMode=inactive-or-failed
RefuseManualStart=on
RefuseManualStop=on
After=gnome-session-manager.target
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
# The units already conflict because they use the same BusName
#Conflicts=gnome-shell-wayland.service
# Limit startup frequency more than the default
StartLimitIntervalSec=15s
StartLimitBurst=3
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On X11 we want to restart on-success (Alt+F2 + r) and on-failure.
Restart=always
# Do not wait before restarting the shell
RestartSec=0ms
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@@ -1,5 +1,10 @@
[Unit]
Description=GNOME Shell (x11 sync point)
After=gnome-shell.service
BindsTo=gnome-shell.service
Conflicts=gnome-shell-wayland.target
Description=GNOME Shell on X11
DefaultDependencies=no
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
Requires=gnome-shell-x11.service
After=gnome-shell-x11.service

View File

@@ -1,11 +0,0 @@
[Unit]
Description=GNOME Shell
Wants=gnome-session.service
After=graphical-session-pre.target gnome-session-bus.target
PartOf=graphical-session.target
[Service]
Type=dbus
ExecStart=@bindir@/gnome-shell
Restart=on-failure
BusName=org.gnome.Shell

View File

@@ -14,6 +14,8 @@ desktopconf = configuration_data()
# file when built in a non-system prefix
desktopconf.set('bindir', bindir)
desktopconf.set('VERSION', meson.project_version())
desktopconf.set('systemd_hidden', have_systemd ? 'true' : 'false')
foreach desktop_file : desktop_files
i18n.merge_file('desktop',
input: configure_file(
@@ -22,7 +24,7 @@ foreach desktop_file : desktop_files
configuration: desktopconf
),
output: desktop_file,
po_dir: '../po',
po_dir: po_dir,
install: true,
install_dir: desktopdir,
type: 'desktop'
@@ -98,15 +100,23 @@ if have_systemd
unitconf = configuration_data()
unitconf.set('bindir', bindir)
unit = configure_file(
input: 'gnome-shell.service.in',
output: 'gnome-shell.service',
configure_file(
input: 'gnome-shell-x11.service.in',
output: 'gnome-shell-x11.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
units = files('gnome-shell-wayland.target',
'gnome-shell-x11.target')
configure_file(
input: 'gnome-shell-wayland.service.in',
output: 'gnome-shell-wayland.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
units = files('gnome-shell-x11.target',
'gnome-shell-wayland.target',
'gnome-shell-disable-extensions.service')
install_data(units, install_dir: systemduserunitdir)
endif

View File

@@ -14,3 +14,4 @@ X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Provides=panel;windowmanager;
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=false
X-GNOME-HiddenUnderSystemd=@systemd_hidden@

View File

@@ -150,11 +150,6 @@
Keybinding to focus the active notification.
</description>
</key>
<key name="pause-resume-tweens" type="as">
<default>[]</default>
<summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
<description></description>
</key>
<key name="switch-to-application-1" type="as">
<default>["&lt;Super&gt;1"]</default>
<summary>Switch to application 1</summary>
@@ -233,6 +228,17 @@
</key>
</schema>
<schema id="org.gnome.shell.world-clocks" path="/org/gnome/shell/world-clocks/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="locations" type="av">
<summary>Locations</summary>
<description>
The locations to show in world clocks
</description>
<default>[]</default>
</key>
</schema>
<schema id="org.gnome.shell.weather" path="/org/gnome/shell/weather/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="automatic-location" type="b">

View File

@@ -611,6 +611,14 @@ StScrollBar {
}
// Rename popup
.rename-folder-popup-box {
spacing: 6px;
margin-left: 12px;
margin-right: 12px;
}
// Background menu
.background-menu { -boxpointer-gap: 4px; -arrow-rise: 0px; }
@@ -1514,6 +1522,9 @@ StScrollBar {
border-image: none;
background-image: none;
}
&:drop .overview-icon {
background-color: transparentize($selected_bg_color,.15);
}
&:active .overview-icon,
&:checked .overview-icon {
background-color: transparentize(darken($osd_bg_color,10%), 0.5);

View File

@@ -1,4 +1,7 @@
/* exported main */
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const Gettext = imports.gettext;
const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
const Format = imports.format;
@@ -564,6 +567,10 @@ class ExtensionRow extends Gtk.ListBoxRow {
this._extension = extension;
this._prefsModule = null;
this.connect('destroy', this._onDestroy.bind(this));
this._buildUI();
this._extensionStateChangedId = this._app.shellProxy.connectSignal(
'ExtensionStateChanged', (p, sender, [uuid, newState]) => {
if (this.uuid !== uuid)
@@ -571,13 +578,13 @@ class ExtensionRow extends Gtk.ListBoxRow {
this._extension = ExtensionUtils.deserializeExtension(newState);
let state = (this._extension.state == ExtensionState.ENABLED);
GObject.signal_handler_block(this._switch, this._notifyActiveId);
this._switch.state = state;
GObject.signal_handler_unblock(this._switch, this._notifyActiveId);
this._switch.sensitive = this._canToggle();
});
this.connect('destroy', this._onDestroy.bind(this));
this._buildUI();
}
get uuid() {
@@ -643,7 +650,7 @@ class ExtensionRow extends Gtk.ListBoxRow {
sensitive: this._canToggle(),
state: this._extension.state === ExtensionState.ENABLED
});
this._switch.connect('notify::active', () => {
this._notifyActiveId = this._switch.connect('notify::active', () => {
if (this._switch.active)
this._app.shellProxy.EnableExtensionRemote(this.uuid);
else

View File

@@ -8,14 +8,13 @@ const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util;
const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
var DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3;
var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000;
var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 0.5;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
var AuthPromptMode = {
UNLOCK_ONLY: 0,
@@ -267,7 +266,7 @@ var AuthPrompt = class {
let oldActor = this._defaultButtonWellActor;
if (oldActor)
Tweener.removeTweens(oldActor);
oldActor.remove_all_transitions();
let wasSpinner;
if (oldActor == this._spinner.actor)
@@ -290,18 +289,18 @@ var AuthPrompt = class {
this._spinner.stop();
}
} else {
Tweener.addTween(oldActor,
{ opacity: 0,
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear',
onComplete: () => {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
}
});
oldActor.ease({
opacity: 0,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
}
});
}
}
@@ -312,11 +311,12 @@ var AuthPrompt = class {
if (!animate)
actor.opacity = 255;
else
Tweener.addTween(actor,
{ opacity: 255,
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear' });
actor.ease({
opacity: 255,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR
});
}
this._defaultButtonWellActor = actor;
@@ -365,12 +365,12 @@ var AuthPrompt = class {
_fadeOutMessage() {
if (this._message.opacity == 0)
return;
Tweener.removeTweens(this._message);
Tweener.addTween(this._message,
{ opacity: 0,
time: MESSAGE_FADE_OUT_ANIMATION_TIME,
transition: 'easeOutQuad'
});
this._message.remove_all_transitions();
this._message.ease({
opacity: 0,
duration: MESSAGE_FADE_OUT_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
setMessage(message, type) {
@@ -385,7 +385,7 @@ var AuthPrompt = class {
this._message.remove_style_class_name('login-dialog-message-hint');
if (message) {
Tweener.removeTweens(this._message);
this._message.remove_all_transitions();
this._message.text = message;
this._message.opacity = 255;
} else {

View File

@@ -20,7 +20,7 @@
* In order for transformation animations to look good, they need to be
* incremental and have some order to them (e.g., fade out hidden items,
* then shrink to close the void left over). Chaining animations in this way can
* be error-prone and wordy using just Tweener callbacks.
* be error-prone and wordy using just ease() callbacks.
*
* The classes in this file help with this:
*

View File

@@ -31,11 +31,10 @@ const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Realmd = imports.gdm.realmd;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 0.5;
const _FADE_ANIMATION_TIME = 250;
const _SCROLL_ANIMATION_TIME = 500;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5;
@@ -205,11 +204,10 @@ var UserList = class {
let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
Tweener.removeTweens(adjustment);
Tweener.addTween (adjustment,
{ value: value,
time: _SCROLL_ANIMATION_TIME,
transition: 'easeOutQuad' });
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: _SCROLL_ANIMATION_TIME
});
}
jumpToItem(item) {
@@ -759,14 +757,15 @@ var LoginDialog = GObject.registerClass({
_fadeInBannerView() {
this._bannerView.show();
Tweener.addTween(this._bannerView,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
this._bannerView.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
_hideBannerView() {
Tweener.removeTweens(this._bannerView);
this._bannerView.remove_all_transitions();
this._bannerView.opacity = 0;
this._bannerView.hide();
}
@@ -859,10 +858,11 @@ var LoginDialog = GObject.registerClass({
return;
this._authPrompt.actor.opacity = 0;
this._authPrompt.actor.show();
Tweener.addTween(this._authPrompt.actor,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
this._authPrompt.actor.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._fadeInBannerView();
}
@@ -906,26 +906,31 @@ var LoginDialog = GObject.registerClass({
this._showPrompt();
}
_bindOpacity() {
this._bindings = Main.layoutManager.uiGroup.get_children()
.filter(c => c != Main.layoutManager.screenShieldGroup)
.map(c => this.bind_property('opacity', c, 'opacity', 0));
}
_unbindOpacity() {
this._bindings.forEach(b => b.unbind());
}
_loginScreenSessionActivated() {
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
return;
Tweener.addTween(this,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate: () => {
let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.opacity;
}
},
onComplete: () => {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
} });
this._bindOpacity();
this.actor.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
this._unbindOpacity();
}
});
}
_gotGreeterSessionProxy(proxy) {
@@ -938,21 +943,16 @@ var LoginDialog = GObject.registerClass({
}
_startSession(serviceName) {
Tweener.addTween(this,
{ opacity: 0,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate: () => {
let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.opacity;
}
},
onComplete: () => {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
} });
this._bindOpacity();
this.actor.ease({
opacity: 0,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
this._unbindOpacity();
}
});
}
_onSessionOpened(client, serviceName) {
@@ -1225,10 +1225,11 @@ var LoginDialog = GObject.registerClass({
Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
Tweener.addTween(this,
{ opacity: 255,
time: 1,
transition: 'easeInQuad' });
this.ease({
opacity: 255,
duration: 1000,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
return true;
}

View File

@@ -21,6 +21,7 @@ var Manager = class {
'/org/freedesktop/realmd',
this._reloadRealms.bind(this));
this._realms = {};
this._loginFormat = null;
this._signalId = this._aggregateProvider.connect('g-properties-changed',
(proxy, properties) => {
@@ -86,7 +87,7 @@ var Manager = class {
}
get loginFormat() {
if (this._loginFormat !== undefined)
if (this._loginFormat)
return this._loginFormat;
this._updateLoginFormat();

View File

@@ -11,14 +11,13 @@ const OVirt = imports.gdm.oVirt;
const Main = imports.ui.main;
const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
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 = 0.16;
var CLONE_FADE_ANIMATION_TIME = 0.25;
var FADE_ANIMATION_TIME = 160;
var CLONE_FADE_ANIMATION_TIME = 250;
var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
@@ -51,16 +50,16 @@ function fadeInActor(actor) {
actor.opacity = 0;
actor.set_height(0);
Tweener.addTween(actor,
{ opacity: 255,
height: naturalHeight,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
this.set_height(-1);
hold.release();
},
});
actor.ease({
opacity: 255,
height: naturalHeight,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.set_height(-1);
hold.release();
}
});
return hold;
}
@@ -73,17 +72,17 @@ function fadeOutActor(actor) {
}
let hold = new Batch.Hold();
Tweener.addTween(actor,
{ opacity: 0,
height: 0,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
this.hide();
this.set_height(-1);
hold.release();
},
});
actor.ease({
opacity: 0,
height: 0,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.hide();
this.set_height(-1);
hold.release();
}
});
return hold;
}
@@ -103,15 +102,15 @@ function cloneAndFadeOutActor(actor) {
clone.set_position(x, y);
let hold = new Batch.Hold();
Tweener.addTween(clone,
{ opacity: 0,
time: CLONE_FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
clone.destroy();
hold.release();
}
});
clone.ease({
opacity: 0,
duration: CLONE_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
clone.destroy();
hold.release();
}
});
return hold;
}

View File

@@ -165,8 +165,8 @@ function versionCheck(required, current) {
let requiredArray = required[i].split('.');
if (requiredArray[0] == major &&
requiredArray[1] == minor &&
(requiredArray[2] == point ||
(requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
((requiredArray[2] === undefined && parseInt(minor) % 2 == 0) ||
requiredArray[2] == point))
return true;
}
return false;

View File

@@ -2,7 +2,6 @@
/* exported getIBusManager */
const { Gio, GLib, IBus } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
@@ -19,9 +18,9 @@ function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
IBus.MICRO_VERSION >= requiredMicro))
return;
throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro);
throw "Found IBus version %d.%d.%d but required is %d.%d.%d"
.format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro);
}
function getIBusManager() {
@@ -59,15 +58,19 @@ var IBusManager = class {
this._spawn();
}
_spawn() {
_spawn(extraArgs = []) {
try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs];
Gio.Subprocess.new(cmdLine, Gio.SubprocessFlags.NONE);
} catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`);
}
}
restartDaemon(extraArgs = []) {
this._spawn(['-r', ...extraArgs]);
}
_clear() {
if (this._panelService)
this._panelService.destroy();
@@ -80,8 +83,6 @@ var IBusManager = class {
this._currentEngineName = null;
this.emit('ready', false);
this._spawn();
}
_onConnected() {
@@ -214,21 +215,23 @@ var IBusManager = class {
return;
if (this._preloadEnginesId != 0) {
Mainloop.source_remove(this._preloadEnginesId);
GLib.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
this._preloadEnginesId =
Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
() => {
this._ibus.preload_engines_async(
ids,
-1,
null,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
this._PRELOAD_ENGINES_DELAY_TIME,
() => {
this._ibus.preload_engines_async(
ids,
-1,
null,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
});
}
};
Signals.addSignalMethods(IBusManager.prototype);

View File

@@ -217,7 +217,7 @@ function isUnsafeExpression(str) {
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/=/)) {
if (prunedStr.match(/[=]/)) {
return true;
} else if (prunedStr.match(/;/)) {
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well

View File

@@ -174,13 +174,21 @@ const SystemActions = GObject.registerClass({
});
Main.layoutManager.connect('monitors-changed',
() => this._updateOrientationLock());
Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
Gio.BusNameWatcherFlags.NONE,
() => this._sensorProxyAppeared(),
() => {
this._sensorProxy = null;
this._updateOrientationLock();
});
this._sensorProxy = new SensorProxy(Gio.DBus.system,
SENSOR_BUS_NAME,
SENSOR_OBJECT_PATH,
(proxy, error) => {
if (error)
log(error.message);
},
null,
Gio.DBusProxyFlags.DO_NOT_AUTO_START);
this._sensorProxy.connect('g-properties-changed', () => {
this._updateOrientationLock();
});
this._sensorProxy.connect('notify::g-name-owner', () => {
this._updateOrientationLock();
});
this._updateOrientationLock();
this._updateOrientationLockIcon();
@@ -223,22 +231,9 @@ const SystemActions = GObject.registerClass({
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
}
_sensorProxyAppeared() {
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._sensorProxy.connect('g-properties-changed',
() => this._updateOrientationLock());
this._updateOrientationLock();
});
}
_updateOrientationLock() {
let available = false;
if (this._sensorProxy)
if (this._sensorProxy.g_name_owner)
available = this._sensorProxy.HasAccelerometer &&
this._monitorManager.get_is_builtin_display_on();

View File

@@ -5,14 +5,11 @@
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Params = imports.misc.params;
var SCROLL_TIME = 0.1;
var SCROLL_TIME = 100;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\([^\\s()<>]+\\)';
@@ -316,7 +313,8 @@ function lowerBound(array, val, cmp) {
if (array.length == 0)
return 0;
min = 0; max = array.length;
min = 0;
max = array.length;
while (min < (max - 1)) {
mid = Math.floor((min + max) / 2);
v = cmp(array[mid], val);
@@ -426,97 +424,8 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
else
return;
Tweener.addTween(adjustment,
{ value: value,
time: SCROLL_TIME,
transition: 'easeOutQuad' });
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SCROLL_TIME
});
}
var AppSettingsMonitor = class {
constructor(appId, schemaId) {
this._appId = appId;
this._schemaId = schemaId;
this._app = null;
this._settings = null;
this._handlers = [];
this._schemaSource = Gio.SettingsSchemaSource.get_default();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
}
get available() {
return this._app != null && this._settings != null;
}
activateApp() {
if (this._app)
this._app.activate();
}
watchSetting(key, callback) {
let handler = { id: 0, key: key, callback: callback };
this._handlers.push(handler);
this._connectHandler(handler);
}
_connectHandler(handler) {
if (!this._settings || handler.id > 0)
return;
handler.id = this._settings.connect(`changed::${handler.key}`,
handler.callback);
handler.callback(this._settings, handler.key);
}
_disconnectHandler(handler) {
if (this._settings && handler.id > 0)
this._settings.disconnect(handler.id);
handler.id = 0;
}
_onInstalledChanged() {
let hadApp = (this._app != null);
this._app = this._appSystem.lookup_app(this._appId);
let haveApp = (this._app != null);
if (hadApp == haveApp)
return;
if (haveApp)
this._checkSettings();
else
this._setSettings(null);
}
_setSettings(settings) {
this._handlers.forEach((handler) => this._disconnectHandler(handler));
let hadSettings = (this._settings != null);
this._settings = settings;
let haveSettings = (this._settings != null);
this._handlers.forEach((handler) => this._connectHandler(handler));
if (hadSettings != haveSettings)
this.emit('available-changed');
}
_checkSettings() {
let schema = this._schemaSource.lookup(this._schemaId, true);
if (schema) {
this._setSettings(new Gio.Settings({ settings_schema: schema }));
} else if (this._app) {
Mainloop.timeout_add_seconds(1, () => {
this._checkSettings();
return GLib.SOURCE_REMOVE;
});
}
}
};
Signals.addSignalMethods(AppSettingsMonitor.prototype);

View File

@@ -94,8 +94,10 @@ var WeatherClient = class {
});
this._settings.connect('changed::automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._onAutomaticLocationChanged();
this._settings.connect('changed::locations',
this._onLocationsChanged.bind(this));
this._onLocationsChanged();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
@@ -153,12 +155,13 @@ var WeatherClient = class {
this._weatherProxy.connect('g-properties-changed',
this._onWeatherPropertiesChanged.bind(this));
if (this._weatherProxy.g_name_owner != null)
this._onWeatherPropertiesChanged();
this._onWeatherPropertiesChanged();
}
_onWeatherPropertiesChanged() {
if (this._weatherProxy.g_name_owner == null)
return;
this._settings.set_boolean('automatic-location',
this._weatherProxy.AutomaticLocation);
this._settings.set_value('locations',
@@ -258,8 +261,8 @@ var WeatherClient = class {
this._setLocation(location);
}
_onAutomaticLocationChanged(settings, key) {
let useAutoLocation = settings.get_boolean(key);
_onAutomaticLocationChanged() {
let useAutoLocation = this._settings.get_boolean('automatic-location');
if (this._autoLocationRequested == useAutoLocation)
return;
@@ -277,8 +280,9 @@ var WeatherClient = class {
this._setLocation(this._mostRecentLocation);
}
_onLocationsChanged(settings, key) {
let serialized = settings.get_value(key).deep_unpack().shift();
_onLocationsChanged() {
let locations = this._settings.get_value('locations').deep_unpack();
let serialized = locations.shift();
let mostRecentLocation = null;
if (serialized)

View File

@@ -3,17 +3,15 @@
WindowCyclerPopup */
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
const Tweener = imports.ui.tweener;
var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
var THUMBNAIL_DEFAULT_SIZE = 256;
var THUMBNAIL_POPUP_TIME = 500; // milliseconds
var THUMBNAIL_FADE_TIME = 0.1; // seconds
var THUMBNAIL_FADE_TIME = 100; // milliseconds
var WINDOW_PREVIEW_SIZE = 128;
var APP_ICON_SIZE = 96;
@@ -293,7 +291,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
if (this._thumbnails)
this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0)
Mainloop.source_remove(this._thumbnailTimeoutId);
GLib.source_remove(this._thumbnailTimeoutId);
}
/**
@@ -328,7 +326,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}
if (this._thumbnailTimeoutId != 0) {
Mainloop.source_remove(this._thumbnailTimeoutId);
GLib.source_remove(this._thumbnailTimeoutId);
this._thumbnailTimeoutId = 0;
}
@@ -345,7 +343,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.highlight(window, forceAppFocus);
} else if (this._items[this._selectedIndex].cachedWindows.length > 1 &&
!forceAppFocus) {
this._thumbnailTimeoutId = Mainloop.timeout_add (
this._thumbnailTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
THUMBNAIL_POPUP_TIME,
this._timeoutPopupThumbnails.bind(this));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
@@ -362,15 +361,15 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_destroyThumbnails() {
let thumbnailsActor = this._thumbnails;
Tweener.addTween(thumbnailsActor,
{ opacity: 0,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
}
});
this._thumbnails.ease({
opacity: 0,
duration: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
}
});
this._thumbnails = null;
if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
@@ -393,12 +392,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.get_allocation_box();
this._thumbnails.opacity = 0;
Tweener.addTween(this._thumbnails,
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => this.thumbnailsVisible = true
});
this._thumbnails.ease({
opacity: 255,
duration: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.thumbnailsVisible = true;
}
});
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
}
@@ -647,8 +648,9 @@ class WindowCyclerPopup extends CyclerPopup {
}
});
var AppIcon = GObject.registerClass(
class AppIcon extends St.BoxLayout {
var AppIcon = GObject.registerClass({
GTypeName: 'AltTab_AppIcon'
}, class AppIcon extends St.BoxLayout {
_init(app) {
super._init({ style_class: 'alt-tab-app',
vertical: true });
@@ -710,7 +712,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_onDestroy() {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
GLib.source_remove(this._mouseTimeOutId);
this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId);
@@ -789,14 +791,16 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// activation when the thumbnail list is open
_onItemEnter(index) {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
GLib.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) {
this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
() => {
this._enterItem(index);
this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE;
});
this._mouseTimeOutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
APP_ICON_HOVER_TIMEOUT,
() => {
this._enterItem(index);
this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else {
this._itemEntered(index);

View File

@@ -1,14 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */
const { GLib, Gio, St } = imports.gi;
const Mainloop = imports.mainloop;
const Tweener = imports.ui.tweener;
const { Clutter, GLib, Gio, St } = imports.gi;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1.0;
var SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000;
var Animation = class {
constructor(file, width, height, speed) {
@@ -47,7 +44,7 @@ var Animation = class {
stop() {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
@@ -56,12 +53,19 @@ var Animation = class {
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
this.stop();
this._isLoaded = false;
this.actor.destroy_all_children();
if (!validResourceScale)
if (!validResourceScale) {
if (wasPlaying)
this.play();
return;
}
let textureCache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
@@ -69,6 +73,9 @@ var Animation = class {
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
if (wasPlaying)
this.play();
}
_showFrame(frame) {
@@ -138,15 +145,15 @@ var Spinner = class extends AnimatedIcon {
}
play() {
Tweener.removeTweens(this.actor);
this.actor.remove_all_transitions();
if (this._animate) {
super.play();
Tweener.addTween(this.actor, {
this.actor.ease({
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
time: SPINNER_ANIMATION_TIME,
transition: 'linear'
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR
});
} else {
this.actor.opacity = 255;
@@ -155,16 +162,14 @@ var Spinner = class extends AnimatedIcon {
}
stop() {
Tweener.removeTweens(this.actor);
this.actor.remove_all_transitions();
if (this._animate) {
Tweener.addTween(this.actor, {
this.actor.ease({
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => {
super.stop();
}
onComplete: () => super.stop()
});
} else {
this.actor.opacity = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -147,12 +147,11 @@ class AppFavorites {
let app = Shell.AppSystem.get_default().lookup_app(appId);
Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()),
{ forFeedback: true,
undoCallback: () => {
this._removeFavorite(appId);
}
});
let msg = _("%s has been added to your favorites.").format(app.get_name());
Main.overview.setMessage(msg, {
forFeedback: true,
undoCallback: () => this._removeFavorite(appId),
});
}
addFavorite(appId) {
@@ -181,12 +180,11 @@ class AppFavorites {
if (!this._removeFavorite(appId))
return;
Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
{ forFeedback: true,
undoCallback: () => {
this._addFavorite(appId, pos);
}
});
let msg = _("%s has been removed from your favorites.").format(app.get_name());
Main.overview.setMessage(msg, {
forFeedback: true,
undoCallback: () => this._addFavorite(appId, pos),
});
}
}
Signals.addSignalMethods(AppFavorites.prototype);

View File

@@ -99,7 +99,6 @@ const Signals = imports.signals;
const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
@@ -110,7 +109,7 @@ const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
const BACKGROUND_STYLE_KEY = 'picture-options';
const PICTURE_URI_KEY = 'picture-uri';
var FADE_ANIMATION_TIME = 1.0;
var FADE_ANIMATION_TIME = 1000;
// These parameters affect how often we redraw.
// The first is how different (percent crossfaded) the slide show
@@ -442,20 +441,21 @@ var Background = class Background {
}
_loadAnimation(file) {
this._cache.getAnimation({ file: file,
settingsSchema: this._settings.schema_id,
onLoaded: animation => {
this._animation = animation;
this._cache.getAnimation({
file: file,
settingsSchema: this._settings.schema_id,
onLoaded: animation => {
this._animation = animation;
if (!this._animation || this._cancellable.is_cancelled()) {
this._setLoaded();
return;
}
if (!this._animation || this._cancellable.is_cancelled()) {
this._setLoaded();
return;
}
this._updateAnimation();
this._watchFile(file);
}
});
this._updateAnimation();
this._watchFile(file);
}
});
}
_loadImage(file) {
@@ -710,14 +710,12 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = null;
this.emit('changed');
Tweener.addTween(oldBackgroundActor,
{ opacity: 0,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
oldBackgroundActor.destroy();
}
});
oldBackgroundActor.ease({
opacity: 0,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => oldBackgroundActor.destroy()
});
}
_updateBackgroundActor() {
@@ -751,13 +749,14 @@ var BackgroundManager = class BackgroundManager {
_createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: this._monitorIndex,
background: background.background,
vignette: this._vignette,
vignette_sharpness: 0.5,
brightness: 0.5,
});
let backgroundActor = new Meta.BackgroundActor({
meta_display: global.display,
monitor: this._monitorIndex,
background: background.background,
vignette: this._vignette,
vignette_sharpness: 0.5,
brightness: 0.5,
});
this._container.add_child(backgroundActor);

View File

@@ -31,7 +31,7 @@ function addBackgroundMenu(actor, layoutManager) {
function openMenu(x, y) {
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.FULL);
}
let clickAction = new Clutter.ClickAction();

View File

@@ -1,37 +1,48 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported BarLevel */
const { Atk, Clutter, St } = imports.gi;
const Signals = imports.signals;
const { Atk, Clutter, GObject, St } = imports.gi;
var BarLevel = class {
constructor(value, params = {}) {
if (isNaN(value))
// Avoid spreading NaNs around
throw TypeError('The bar level value must be a number');
var BarLevel = GObject.registerClass({
Properties: {
'value': GObject.ParamSpec.double(
'value', 'value', 'value',
GObject.ParamFlags.READWRITE,
0, 2, 0),
'maximum-value': GObject.ParamSpec.double(
'maximum-value', 'maximum-value', 'maximum-value',
GObject.ParamFlags.READWRITE,
1, 2, 1),
'overdrive-start': GObject.ParamSpec.double(
'overdrive-start', 'overdrive-start', 'overdrive-start',
GObject.ParamFlags.READWRITE,
1, 2, 1)
}
}, class BarLevel extends St.DrawingArea {
_init(params) {
this._maxValue = 1;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this._value = 0;
this._overdriveStart = 1;
this._barLevelWidth = 0;
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
can_focus: params['canFocus'] || false,
reactive: params['reactive'] || false,
accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
this.actor.connect('repaint', this._barLevelRepaint.bind(this));
this.actor.connect('allocation-changed', (actor, box) => {
let defaultParams = {
style_class: 'barlevel',
accessible_role: Atk.Role.LEVEL_BAR
};
super._init(Object.assign(defaultParams, params));
this.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width();
});
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.actor.set_accessible(this._customAccessible);
this._customAccessible = St.GenericAccessible.new_for_actor(this);
this.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('value-changed', this._valueChanged.bind(this));
this.connect('notify::value', this._valueChanged.bind(this));
}
get value() {
@@ -39,16 +50,14 @@ var BarLevel = class {
}
set value(value) {
if (isNaN(value))
throw TypeError('The bar level value must be a number');
value = Math.max(Math.min(value, this._maxValue), 0);
if (this._value == value)
return;
this._value = value;
this.actor.queue_repaint();
this.notify('value');
this.queue_repaint();
}
// eslint-disable-next-line camelcase
@@ -58,9 +67,6 @@ var BarLevel = class {
// eslint-disable-next-line camelcase
set maximum_value(value) {
if (isNaN(value))
throw TypeError('The bar level max value must be a number');
value = Math.max(value, 1);
if (this._maxValue == value)
@@ -68,7 +74,8 @@ var BarLevel = class {
this._maxValue = value;
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.actor.queue_repaint();
this.notify('maximum-value');
this.queue_repaint();
}
// eslint-disable-next-line camelcase
@@ -78,9 +85,6 @@ var BarLevel = class {
// eslint-disable-next-line camelcase
set overdrive_start(value) {
if (isNaN(value))
throw TypeError('The overdrive limit value must be a number');
if (this._overdriveStart == value)
return;
@@ -89,14 +93,14 @@ var BarLevel = class {
`which is a number greater than the maximum allowed value ${this._maxValue}`);
this._overdriveStart = value;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
this.notify('overdrive-start');
this.queue_repaint();
}
_barLevelRepaint(area) {
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
vfunc_repaint() {
let cr = this.get_context();
let themeNode = this.get_theme_node();
let [width, height] = this.get_surface_size();
let barLevelHeight = themeNode.get_length('-barlevel-height');
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
@@ -226,5 +230,4 @@ var BarLevel = class {
_valueChanged() {
this._customAccessible.notify("accessible-value");
}
};
Signals.addSignalMethods(BarLevel.prototype);
});

View File

@@ -4,7 +4,6 @@
const { Clutter, GObject, Shell, St } = imports.gi;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var PopupAnimation = {
NONE: 0,
@@ -13,7 +12,7 @@ var PopupAnimation = {
FULL: ~0,
};
var POPUP_ANIMATION_TIME = 0.15;
var POPUP_ANIMATION_TIME = 150;
/**
* BoxPointer:
@@ -106,16 +105,18 @@ var BoxPointer = GObject.registerClass({
}
}
Tweener.addTween(this, { opacity: 255,
translation_x: 0,
translation_y: 0,
transition: 'linear',
onComplete: () => {
this._unmuteInput();
if (onComplete)
onComplete();
},
time: animationTime });
this.ease({
opacity: 255,
translation_x: 0,
translation_y: 0,
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this._unmuteInput();
if (onComplete)
onComplete();
}
});
}
close(animate, onComplete) {
@@ -148,21 +149,22 @@ var BoxPointer = GObject.registerClass({
this._muteInput();
Tweener.removeTweens(this);
Tweener.addTween(this, { opacity: fade ? 0 : 255,
translation_x: translationX,
translation_y: translationY,
transition: 'linear',
time: animationTime,
onComplete: () => {
this.hide();
this.opacity = 0;
this.translation_x = 0;
this.translation_y = 0;
if (onComplete)
onComplete();
}
});
this.remove_all_transitions();
this.ease({
opacity: fade ? 0 : 255,
translation_x: translationX,
translation_y: translationY,
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this.hide();
this.opacity = 0;
this.translation_x = 0;
this.translation_y = 0;
if (onComplete)
onComplete();
}
});
}
_adjustAllocationForArrow(isWidth, minSize, natSize) {

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList */
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
@@ -688,15 +688,15 @@ var EventMessage = class EventMessage extends MessageList.Message {
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
if (this._event.date < periodBegin && !this._event.allDay) {
if (rtl)
title = title + ELLIPSIS_CHAR;
title = `${title}${ELLIPSIS_CHAR}`;
else
title = ELLIPSIS_CHAR + title;
title = `${ELLIPSIS_CHAR}${title}`;
}
if (this._event.end > periodEnd && !this._event.allDay) {
if (rtl)
title = ELLIPSIS_CHAR + title;
title = `${ELLIPSIS_CHAR}${title}`;
else
title = title + ELLIPSIS_CHAR;
title = `${title}${ELLIPSIS_CHAR}`;
}
return title;
}
@@ -1075,6 +1075,10 @@ var CalendarMessageList = class CalendarMessageList {
});
box.add_actor(this._clearButton);
this._placeholder.actor.bind_property('visible',
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
vertical: true,
y_expand: true,
@@ -1145,7 +1149,6 @@ var CalendarMessageList = class CalendarMessageList {
let empty = sections.every(s => s.empty || !s.actor.visible);
this._placeholder.actor.visible = empty;
this._clearButton.visible = !empty;
let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear;

View File

@@ -5,10 +5,9 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var FROZEN_WINDOW_BRIGHTNESS = -0.3;
var DIALOG_TRANSITION_TIME = 0.15;
var DIALOG_TRANSITION_TIME = 150;
var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({
@@ -149,12 +148,12 @@ var CloseDialog = GObject.registerClass({
this._dialog.scale_y = 0;
this._dialog.set_pivot_point(0.5, 0.5);
Tweener.addTween(this._dialog,
{ scale_y: 1,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this)
});
this._dialog.ease({
scale_y: 1,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this)
});
}
vfunc_hide() {
@@ -176,14 +175,12 @@ var CloseDialog = GObject.registerClass({
this._dialog = null;
this._removeWindowEffect();
Tweener.addTween(dialog,
{ scale_y: 0,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: () => {
dialog.destroy();
}
});
dialog.ease({
scale_y: 0,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
onComplete: () => dialog.destroy()
});
}
vfunc_focus() {

View File

@@ -2,7 +2,6 @@
/* exported Component */
const { Gio, GLib } = imports.gi;
const Mainloop = imports.mainloop;
const Params = imports.misc.params;
const GnomeSession = imports.misc.gnomeSession;
@@ -39,7 +38,7 @@ var AutomountManager = class {
this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', this._onDriveDisconnected.bind(this));
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', this._onDriveEjectButton.bind(this));
this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
this._mountAllId = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._startupMountAll.bind(this));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
}
@@ -51,7 +50,7 @@ var AutomountManager = class {
this._volumeMonitor.disconnect(this._driveEjectButtonId);
if (this._mountAllId > 0) {
Mainloop.source_remove(this._mountAllId);
GLib.source_remove(this._mountAllId);
this._mountAllId = 0;
}
}
@@ -220,7 +219,7 @@ var AutomountManager = class {
_onVolumeRemoved(monitor, volume) {
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
Mainloop.source_remove(volume._allowAutorunExpireId);
GLib.source_remove(volume._allowAutorunExpireId);
delete volume._allowAutorunExpireId;
}
this._volumeQueue =
@@ -249,7 +248,7 @@ var AutomountManager = class {
}
_allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
let id = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
volume.allowAutorun = false;
delete volume._allowAutorunExpireId;
return GLib.SOURCE_REMOVE;

View File

@@ -325,10 +325,10 @@ var AutorunNotification = class extends MessageTray.Notification {
style_class: 'hotplug-notification-item-icon' });
box.add(icon);
let label = new St.Bin({ y_align: St.Align.MIDDLE,
child: new St.Label
({ text: _("Open with %s").format(app.get_name()) })
});
let label = new St.Bin({
y_align: St.Align.MIDDLE,
child: new St.Label({ text: _("Open with %s").format(app.get_name()) }),
});
box.add(label);
let button = new St.Button({ child: box,

View File

@@ -112,16 +112,17 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
expand: true });
}
this._okButton = { label: _("Connect"),
action: this._onOk.bind(this),
default: true
};
this._okButton = {
label: _("Connect"),
action: this._onOk.bind(this),
default: true,
};
this.setButtons([{ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
},
this._okButton]);
this.setButtons([{
label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
}, this._okButton]);
this._updateOkButton();
}
@@ -551,11 +552,12 @@ var VPNRequestHandler = class {
let shouldAsk = keyfile.get_boolean(groups[i], 'ShouldAsk');
if (shouldAsk) {
contentOverride.secrets.push({ label: keyfile.get_string(groups[i], 'Label'),
key: groups[i],
value: value,
password: keyfile.get_boolean(groups[i], 'IsSecret')
});
contentOverride.secrets.push({
label: keyfile.get_string(groups[i], 'Label'),
key: groups[i],
value: value,
password: keyfile.get_boolean(groups[i], 'IsSecret'),
});
} else {
if (!value.length) // Ignore empty secrets
continue;
@@ -609,10 +611,11 @@ Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = class {
constructor() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false
});
this._native = new Shell.NetworkAgent({
identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false,
});
this._dialogs = { };
this._vpnRequests = { };

View File

@@ -3,7 +3,6 @@
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
var Tpl = null;
var Tp = null;
@@ -546,8 +545,8 @@ var ChatSource = class extends MessageTray.Source {
// Wait a bit before notifying for the received message, a handler
// could ack it in the meantime.
if (this._notifyTimeoutId != 0)
Mainloop.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = Mainloop.timeout_add(500,
GLib.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500,
this._notifyTimeout.bind(this));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
}
@@ -641,7 +640,7 @@ var ChatNotification = class extends MessageTray.Notification {
destroy(reason) {
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
GLib.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
super.destroy(reason);
}
@@ -729,7 +728,7 @@ var ChatNotification = class extends MessageTray.Notification {
// Reset the old message timeout
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
GLib.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
let message = { realMessage: props.group != 'meta',
@@ -747,7 +746,8 @@ var ChatNotification = class extends MessageTray.Notification {
} else {
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
// from the timestamp of the message.
this._timestampTimeoutId = Mainloop.timeout_add_seconds(
this._timestampTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
this.appendTimestamp.bind(this));
GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp');
@@ -952,14 +952,15 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
// Remove composing timeout.
if (this._composingTimeoutId > 0) {
Mainloop.source_remove(this._composingTimeoutId);
GLib.source_remove(this._composingTimeoutId);
this._composingTimeoutId = 0;
}
if (text != '') {
this.notification.source.setChatState(Tp.ChannelChatState.COMPOSING);
this._composingTimeoutId = Mainloop.timeout_add_seconds(
this._composingTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
COMPOSING_STOP_TIMEOUT,
this._composingStopTimeout.bind(this));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');

View File

@@ -2,7 +2,6 @@
/* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
@@ -10,11 +9,10 @@ const AppFavorites = imports.ui.appFavorites;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var DASH_ANIMATION_TIME = 0.2;
var DASH_ITEM_LABEL_SHOW_TIME = 0.15;
var DASH_ITEM_LABEL_HIDE_TIME = 0.1;
var DASH_ANIMATION_TIME = 200;
var DASH_ITEM_LABEL_SHOW_TIME = 150;
var DASH_ITEM_LABEL_HIDE_TIME = 100;
var DASH_ITEM_HOVER_TIMEOUT = 300;
function getAppFromSource(source) {
@@ -25,6 +23,30 @@ function getAppFromSource(source) {
}
}
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
constructor(app) {
super(app, {
setSizeManually: true,
showLabel: false
});
}
// Disable all DnD methods
_onDragBegin() {
}
_onDragEnd() {
}
handleDragOver() {
return DND.DragMotionResult.CONTINUE;
}
acceptDrop() {
return false;
}
};
// A container like StBin, but taking the child's scale into account
// when requesting a size
var DashItemContainer = GObject.registerClass(
@@ -32,6 +54,9 @@ class DashItemContainer extends St.Widget {
_init() {
super._init({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }),
scale_x: 0,
scale_y: 0,
opacity: 0,
x_expand: true,
x_align: Clutter.ActorAlign.CENTER });
@@ -42,10 +67,11 @@ class DashItemContainer extends St.Widget {
this.label_actor = this.label;
this.child = null;
this._childScale = 0;
this._childOpacity = 0;
this.animatingOut = false;
this.connect('notify::scale-x', () => this.queue_relayout());
this.connect('notify::scale-y', () => this.queue_relayout());
this.connect('destroy', () => {
if (this.child != null)
this.child.destroy();
@@ -96,11 +122,11 @@ class DashItemContainer extends St.Widget {
x = stageX + this.get_width() + xOffset;
this.label.set_position(x, y);
Tweener.addTween(this.label,
{ opacity: 255,
time: DASH_ITEM_LABEL_SHOW_TIME,
transition: 'easeOutQuad',
});
this.label.ease({
opacity: 255,
duration: DASH_ITEM_LABEL_SHOW_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
setLabelText(text) {
@@ -109,14 +135,12 @@ class DashItemContainer extends St.Widget {
}
hideLabel() {
Tweener.addTween(this.label,
{ opacity: 0,
time: DASH_ITEM_LABEL_HIDE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.label.hide();
}
});
this.label.ease({
opacity: 0,
duration: DASH_ITEM_LABEL_HIDE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.label.hide()
});
}
setChild(actor) {
@@ -127,9 +151,6 @@ class DashItemContainer extends St.Widget {
this.child = actor;
this.add_actor(this.child);
this.set_scale(this._childScale, this._childScale);
this.set_opacity(this._childOpacity);
}
show(animate) {
@@ -137,12 +158,13 @@ class DashItemContainer extends St.Widget {
return;
let time = animate ? DASH_ANIMATION_TIME : 0;
Tweener.addTween(this,
{ childScale: 1.0,
childOpacity: 255,
time: time,
transition: 'easeOutQuad'
});
this.ease({
scale_x: 1,
scale_y: 1,
opacity: 255,
duration: time,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
animateOutAndDestroy() {
@@ -154,37 +176,14 @@ class DashItemContainer extends St.Widget {
}
this.animatingOut = true;
Tweener.addTween(this,
{ childScale: 0.0,
childOpacity: 0,
time: DASH_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.destroy();
}
});
}
set childScale(scale) {
this._childScale = scale;
this.set_scale(scale, scale);
this.queue_relayout();
}
get childScale() {
return this._childScale;
}
set childOpacity(opacity) {
this._childOpacity = opacity;
this.set_opacity(opacity);
this.queue_redraw();
}
get childOpacity() {
return this._childOpacity;
this.ease({
scale_x: 0,
scale_y: 0,
opacity: 0,
duration: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.destroy()
});
}
});
@@ -352,8 +351,7 @@ var Dash = class Dash {
this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._showAppsIcon = new ShowAppsIcon();
this._showAppsIcon.childScale = 1;
this._showAppsIcon.childOpacity = 255;
this._showAppsIcon.show(false);
this._showAppsIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(this._showAppsIcon);
@@ -475,19 +473,7 @@ var Dash = class Dash {
}
_createAppItem(app) {
let appIcon = new AppDisplay.AppIcon(app,
{ setSizeManually: true,
showLabel: false });
if (appIcon._draggable) {
appIcon._draggable.connect('drag-begin',
() => {
appIcon.actor.opacity = 50;
});
appIcon._draggable.connect('drag-end',
() => {
appIcon.actor.opacity = 255;
});
}
let appIcon = new DashIcon(app);
appIcon.connect('menu-state-changed',
(appIcon, opened) => {
@@ -513,7 +499,7 @@ var Dash = class Dash {
// that the notify::hover handler does everything we need to.
if (opened) {
if (this._showLabelTimeoutId > 0) {
Mainloop.source_remove(this._showLabelTimeoutId);
GLib.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0;
}
@@ -527,7 +513,7 @@ var Dash = class Dash {
if (shouldShow) {
if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout,
() => {
this._labelShowing = true;
item.showLabel();
@@ -536,17 +522,17 @@ var Dash = class Dash {
});
GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId);
GLib.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0;
}
}
} else {
if (this._showLabelTimeoutId > 0)
Mainloop.source_remove(this._showLabelTimeoutId);
GLib.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0;
item.hideLabel();
if (this._labelShowing) {
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
this._resetHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, DASH_ITEM_HOVER_TIMEOUT,
() => {
this._labelShowing = false;
this._resetHoverTimeoutId = 0;
@@ -634,12 +620,12 @@ var Dash = class Dash {
icon.icon.set_size(icon.icon.width * scale,
icon.icon.height * scale);
Tweener.addTween(icon.icon,
{ width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
transition: 'easeOutQuad',
});
icon.icon.ease({
width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported DateMenuButton */
const { Clutter, GLib, GnomeDesktop,
const { Clutter, Gio, GLib, GnomeDesktop,
GObject, GWeather, Shell, St } = imports.gi;
const Util = imports.misc.util;
@@ -11,8 +11,13 @@ const Calendar = imports.ui.calendar;
const Weather = imports.misc.weather;
const System = imports.system;
const { loadInterfaceXML } = imports.misc.fileUtils;
const MAX_FORECASTS = 5;
const ClocksIntegrationIface = loadInterfaceXML('org.gnome.Shell.ClocksIntegration');
const ClocksProxy = Gio.DBusProxy.makeProxyWrapper(ClocksIntegrationIface);
function _isToday(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
@@ -25,11 +30,13 @@ var TodayButton = class TodayButton {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
this.actor = new St.Button({ style_class: 'datemenu-today-button',
x_expand: true, x_align: St.Align.START,
can_focus: true,
reactive: false
});
this.actor = new St.Button({
style_class: 'datemenu-today-button',
x_align: St.Align.START,
x_expand: true,
can_focus: true,
reactive: false,
});
this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false);
});
@@ -83,7 +90,8 @@ var WorldClocksSection = class WorldClocksSection {
x_fill: true,
can_focus: true });
this.actor.connect('clicked', () => {
this._clockAppMon.activateApp();
if (this._clocksApp)
this._clocksApp.activate();
Main.overview.hide();
Main.panel.closeCalendar();
@@ -96,29 +104,40 @@ var WorldClocksSection = class WorldClocksSection {
this.actor.child = this._grid;
this._clockAppMon = new Util.AppSettingsMonitor('org.gnome.clocks.desktop',
'org.gnome.clocks');
this._clockAppMon.connect('available-changed',
this._sync.bind(this));
this._clockAppMon.watchSetting('world-clocks',
this._clocksChanged.bind(this));
this._clocksApp = null;
this._clocksProxy = new ClocksProxy(
Gio.DBus.session,
'org.gnome.clocks',
'/org/gnome/clocks',
this._onProxyReady.bind(this),
null /* cancellable */,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES);
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.world-clocks'
});
this._settings.connect('changed', this._clocksChanged.bind(this));
this._clocksChanged();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._sync.bind(this));
this._sync();
}
_sync() {
this.actor.visible = this._clockAppMon.available;
this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop');
this.actor.visible = this._clocksApp != null;
}
_clocksChanged(settings) {
_clocksChanged() {
this._grid.destroy_all_children();
this._locations = [];
let world = GWeather.Location.get_world();
let clocks = settings.get_value('world-clocks').deep_unpack();
let clocks = this._settings.get_value('locations').deep_unpack();
for (let i = 0; i < clocks.length; i++) {
if (!clocks[i].location)
continue;
let l = world.deserialize(clocks[i].location);
let l = world.deserialize(clocks[i]);
if (l && l.get_timezone() != null)
this._locations.push({ location: l });
}
@@ -197,6 +216,25 @@ var WorldClocksSection = class WorldClocksSection {
l.actor.text = Util.formatTime(now, { timeOnly: true });
}
}
_onProxyReady(proxy, error) {
if (error) {
log(`Failed to create GNOME Clocks proxy: ${error}`);
return;
}
this._clocksProxy.connect('g-properties-changed',
this._onClocksPropertiesChanged.bind(this));
this._onClocksPropertiesChanged();
}
_onClocksPropertiesChanged() {
if (this._clocksProxy.g_name_owner == null)
return;
this._settings.set_value('locations',
new GLib.Variant('av', this._clocksProxy.Locations));
}
};
var WeatherSection = class WeatherSection {

View File

@@ -6,14 +6,13 @@ const Signals = imports.signals;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
// Time to scale down to maxDragActorSize
var SCALE_ANIMATION_TIME = 0.25;
var SCALE_ANIMATION_TIME = 250;
// Time to animate to original position on cancel
var SNAP_BACK_ANIMATION_TIME = 0.25;
var SNAP_BACK_ANIMATION_TIME = 250;
// Time to animate to original position on success
var REVERT_ANIMATION_TIME = 0.75;
var REVERT_ANIMATION_TIME = 750;
var DragMotionResult = {
NO_DROP: 0,
@@ -112,9 +111,6 @@ var _Draggable = class _Draggable {
if (event.get_button() != 1)
return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true;
this._grabActor(event.get_device());
@@ -140,9 +136,6 @@ var _Draggable = class _Draggable {
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true;
this._grabActor(event.get_device(), event.get_event_sequence());
@@ -429,19 +422,22 @@ var _Draggable = class _Draggable {
// to the final position because that tween would
// fight with updates as the user continues dragging
// the mouse; instead we do the position computations in
// an onUpdate() function.
Tweener.addTween(this._dragActor,
{ scale_x: scale * origScale,
scale_y: scale * origScale,
time: SCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate: () => {
let currentScale = this._dragActor.scale_x / origScale;
this._dragOffsetX = currentScale * origDragOffsetX;
this._dragOffsetY = currentScale * origDragOffsetY;
this._dragActor.set_position(this._dragX + this._dragOffsetX,
this._dragY + this._dragOffsetY);
} });
// a ::new-frame handler.
this._dragActor.ease({
scale_x: scale * origScale,
scale_y: scale * origScale,
duration: SCALE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._dragActor.get_transition('scale-x').connect('new-frame', () => {
let currentScale = this._dragActor.scale_x / origScale;
this._dragOffsetX = currentScale * origDragOffsetX;
this._dragOffsetY = currentScale * origDragOffsetY;
this._dragActor.set_position(
this._dragX + this._dragOffsetX,
this._dragY + this._dragOffsetY);
});
}
}
}
@@ -615,7 +611,7 @@ var _Draggable = class _Draggable {
// Snap the clone back to its source
[x, y] = this._dragActorSource.get_transformed_position();
let [sourceScaledWidth] = this._dragActorSource.get_transformed_size();
scale = sourceScaledWidth ? this._dragActor.width / sourceScaledWidth : 0;
scale = sourceScaledWidth ? sourceScaledWidth / this._dragActor.width : 0;
} else if (this._dragOrigParent) {
// Snap the actor back to its original position within
// its parent, adjusting for the fact that the parent
@@ -658,13 +654,13 @@ var _Draggable = class _Draggable {
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
this._animateDragEnd(eventTime,
{ x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
time: SNAP_BACK_ANIMATION_TIME,
});
this._animateDragEnd(eventTime, {
x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
duration: SNAP_BACK_ANIMATION_TIME
});
}
_restoreDragActor(eventTime) {
@@ -676,21 +672,22 @@ var _Draggable = class _Draggable {
this._dragActor.set_scale(restoreScale, restoreScale);
this._dragActor.opacity = 0;
this._animateDragEnd(eventTime,
{ time: REVERT_ANIMATION_TIME });
this._animateDragEnd(eventTime, {
duration: REVERT_ANIMATION_TIME
});
}
_animateDragEnd(eventTime, params) {
this._animationInProgress = true;
params['opacity'] = this._dragOrigOpacity;
params['transition'] = 'easeOutQuad';
params['onComplete'] = this._onAnimationComplete;
params['onCompleteScope'] = this;
params['onCompleteParams'] = [this._dragActor, eventTime];
// start the animation
Tweener.addTween(this._dragActor, params);
this._dragActor.ease(Object.assign(params, {
opacity: this._dragOrigOpacity,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._onAnimationComplete(this._dragActor, eventTime);
}
}));
}
_finishAnimation() {

View File

@@ -17,8 +17,6 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
const Mainloop = imports.mainloop;
const { AccountsService, Clutter, Gio,
GLib, GObject, Pango, Polkit, Shell, St } = imports.gi;
@@ -352,12 +350,15 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
// It only makes sense to check for this permission if PackageKit is available.
try {
this._updatesPermission = Polkit.Permission.new_sync(
'org.freedesktop.packagekit.trigger-offline-update', null, null);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null,
(source, res) => {
try {
this._updatesPermission = Polkit.Permission.new_finish(res);
} catch (e) {
log(`No permission to trigger offline updates: ${e}`);
}
});
}
_onDestroy() {
@@ -448,14 +449,16 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
for (let i = 0; i < dialogContent.confirmButtons.length; i++) {
let signal = dialogContent.confirmButtons[i].signal;
let label = dialogContent.confirmButtons[i].label;
buttons.push({ action: () => {
this.close(true);
let signalId = this.connect('closed', () => {
this.disconnect(signalId);
this._confirm(signal);
});
},
label: label });
buttons.push({
action: () => {
this.close(true);
let signalId = this.connect('closed', () => {
this.disconnect(signalId);
this._confirm(signal);
});
},
label: label,
});
}
this.setButtons(buttons);
@@ -562,7 +565,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let startTime = GLib.get_monotonic_time();
this._secondsLeft = this._totalSecondsToStayOpen;
this._timerId = Mainloop.timeout_add_seconds(1, () => {
this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => {
let currentTime = GLib.get_monotonic_time();
let secondsElapsed = ((currentTime - startTime) / 1000000);
@@ -584,7 +587,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
_stopTimer() {
if (this._timerId > 0) {
Mainloop.source_remove(this._timerId);
GLib.source_remove(this._timerId);
this._timerId = 0;
}

View File

@@ -10,7 +10,7 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, GLib, Shell, St } = imports.gi;
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
// We can't import shell JS modules yet, because they may have
@@ -58,6 +58,121 @@ function _patchLayoutClass(layoutClass, styleProps) {
};
}
function _makeEaseCallback(params, cleanup) {
let onComplete = params.onComplete;
delete params.onComplete;
let onStopped = params.onStopped;
delete params.onStopped;
return isFinished => {
cleanup();
if (onStopped)
onStopped(isFinished);
if (onComplete && isFinished)
onComplete();
};
}
function _getPropertyTarget(actor, propName) {
if (!propName.startsWith('@'))
return [actor, propName];
let [type, name, prop] = propName.split('.');
switch (type) {
case '@layout':
return [actor.layout_manager, name];
case '@actions':
return [actor.get_action(name), prop];
case '@constraints':
return [actor.get_constraint(name), prop];
case '@effects':
return [actor.get_effect(name), prop];
}
throw new Error(`Invalid property name ${propName}`);
}
function _easeActor(actor, params) {
actor.save_easing_state();
if (params.duration != undefined)
actor.set_easing_duration(params.duration);
delete params.duration;
if (params.delay != undefined)
actor.set_easing_delay(params.delay);
delete params.delay;
if (params.mode != undefined)
actor.set_easing_mode(params.mode);
delete params.mode;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
// cancel overwritten transitions
let animatedProps = Object.keys(params).map(p => p.replace('_', '-', 'g'));
animatedProps.forEach(p => actor.remove_transition(p));
actor.set(params);
actor.restore_easing_state();
let transition = actor.get_transition(animatedProps[0]);
if (transition)
transition.connect('stopped', (t, finished) => callback(finished));
else
callback(true);
}
function _easeActorProperty(actor, propName, target, params) {
// Avoid pointless difference with ease()
if (params.mode)
params.progress_mode = params.mode;
delete params.mode;
if (params.duration)
params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0);
// Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
// cancel overwritten transition
actor.remove_transition(propName);
if (duration == 0) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
callback(true);
return;
}
let pspec = actor.find_property(propName);
let transition = new Clutter.PropertyTransition(Object.assign({
property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true
}, params));
actor.add_transition(propName, transition);
transition.set_to(target);
transition.connect('stopped', (t, finished) => callback(finished));
}
function _loggingFunc(...args) {
let fields = { 'MESSAGE': args.join(', ') };
let domain = "GNOME Shell";
@@ -94,6 +209,27 @@ function init() {
column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
let origSetEasingDuration = Clutter.Actor.prototype.set_easing_duration;
Clutter.Actor.prototype.set_easing_duration = function(msecs) {
origSetEasingDuration.call(this, adjustAnimationTime(msecs));
};
let origSetEasingDelay = Clutter.Actor.prototype.set_easing_delay;
Clutter.Actor.prototype.set_easing_delay = function(msecs) {
origSetEasingDelay.call(this, adjustAnimationTime(msecs));
};
Clutter.Actor.prototype.ease = function(props, easingParams) {
_easeActor(this, props, easingParams);
};
Clutter.Actor.prototype.ease_property = function(propName, target, params) {
_easeActorProperty(this, propName, target, params);
};
St.Adjustment.prototype.ease = function(target, params) {
// we're not an actor of course, but we implement the same
// transition API as Clutter.Actor, so this works anyway
_easeActorProperty(this, 'value', target, params);
};
Clutter.Actor.prototype.toString = function() {
return St.describe_actor(this);
};
@@ -145,3 +281,17 @@ function init() {
Tweener.init();
String.prototype.format = Format.format;
}
// adjustAnimationTime:
// @msecs: time in milliseconds
//
// Adjust @msecs to account for St's enable-animations
// and slow-down-factor settings
function adjustAnimationTime(msecs) {
let settings = St.Settings.get();
if (!settings.enable_animations)
return 1;
return settings.slow_down_factor * msecs;
}

View File

@@ -186,14 +186,15 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this._info = info;
this._invocation = invocation;
this.setButtons([{ label: _("Cancel"),
action: this._onCancelButtonPressed.bind(this),
key: Clutter.Escape
},
{ label: _("Install"),
action: this._onInstallButtonPressed.bind(this),
default: true
}]);
this.setButtons([{
label: _("Cancel"),
action: this._onCancelButtonPressed.bind(this),
key: Clutter.Escape,
}, {
label: _("Install"),
action: this._onInstallButtonPressed.bind(this),
default: true,
}]);
let content = new Dialog.MessageDialogContent({
title: _("Download and install “%s” from extensions.gnome.org?").format(info.name),

View File

@@ -17,7 +17,7 @@ const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validatio
var ExtensionManager = class {
constructor() {
this._initted = false;
this._initialized = false;
this._enabled = false;
this._extensions = new Map();
@@ -98,6 +98,9 @@ var ExtensionManager = class {
}
_callExtensionEnable(uuid) {
if (!Main.sessionMode.allowExtensions)
return;
let extension = this.lookup(uuid);
if (!extension)
return;
@@ -108,8 +111,6 @@ var ExtensionManager = class {
if (extension.state != ExtensionState.DISABLED)
return;
this._extensionOrder.push(uuid);
let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
for (let i = 0; i < stylesheetNames.length; i++) {
@@ -121,7 +122,7 @@ var ExtensionManager = class {
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue; // not an error
log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
this.logExtensionError(uuid, e);
return;
}
}
@@ -129,15 +130,14 @@ var ExtensionManager = class {
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
this._extensionOrder.push(uuid);
this.emit('extension-state-changed', extension);
return;
} catch (e) {
if (extension.stylesheet) {
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
this.logExtensionError(uuid, e);
return;
}
}
@@ -194,7 +194,7 @@ var ExtensionManager = class {
extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message));
logError(error, `Extension ${uuid}`);
this.emit('extension-state-changed', extension);
}
@@ -304,12 +304,14 @@ var ExtensionManager = class {
}
_callExtensionInit(uuid) {
if (!Main.sessionMode.allowExtensions)
return false;
let extension = this.lookup(uuid);
let dir = extension.dir;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
throw new Error("Extension was not properly created. Call createExtensionObject first");
let dir = extension.dir;
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
this.logExtensionError(uuid, new Error('Missing extension.js'));
@@ -388,9 +390,6 @@ var ExtensionManager = class {
_onEnabledExtensionsChanged() {
let newEnabledExtensions = this._getEnabledExtensions();
if (!this._enabled)
return;
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
@@ -401,9 +400,9 @@ var ExtensionManager = class {
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
this._enabledExtensions.filter(
item => !newEnabledExtensions.includes(item)
).forEach(uuid => {
this._extensionOrder.filter(
uuid => !newEnabledExtensions.includes(uuid)
).reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
@@ -418,22 +417,19 @@ var ExtensionManager = class {
}
_onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
this._enabledExtensions = [];
// Disabling extensions modifies the order array, so use a copy
let extensionOrder = this._extensionOrder.slice();
// The loop modifies the extensions map, so iterate over a copy
let extensions = [...this._extensions.values()];
for (let extension of extensions)
this.reloadExtension(extension);
this._enabledExtensions = this._getEnabledExtensions();
// Disable enabled extensions in the reverse order first to avoid
// the "rebasing" done in _callExtensionDisable...
extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
if (Main.sessionMode.allowExtensions) {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
// ...and then reload and enable extensions in the correct order again.
[...this._extensions.values()].sort((a, b) => {
return extensionOrder.indexOf(a.uuid) - extensionOrder.indexOf(b.uuid);
}).forEach(extension => this.reloadExtension(extension));
}
_loadExtensions() {
@@ -482,9 +478,9 @@ var ExtensionManager = class {
if (this._enabled)
return;
if (!this._initted) {
if (!this._initialized) {
this._loadExtensions();
this._initted = true;
this._initialized = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
@@ -497,7 +493,7 @@ var ExtensionManager = class {
if (!this._enabled)
return;
if (this._initted) {
if (this._initialized) {
this._extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
@@ -512,8 +508,8 @@ var ExtensionManager = class {
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (this._initted)
this._enabledExtensions = this._getEnabledExtensions();
// Take care of added or removed sessionMode extensions
this._onEnabledExtensionsChanged();
this._enableAllExtensions();
} else {
this._disableAllExtensions();

View File

@@ -4,15 +4,14 @@
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
var ICON_SIZE = 96;
var MIN_ICON_SIZE = 16;
var EXTRA_SPACE_ANIMATION_TIME = 0.25;
var EXTRA_SPACE_ANIMATION_TIME = 250;
var ANIMATION_TIME_IN = 0.350;
var ANIMATION_TIME_IN = 350;
var ANIMATION_TIME_OUT = 1 / 2 * ANIMATION_TIME_IN;
var ANIMATION_MAX_DELAY_FOR_ITEM = 2 / 3 * ANIMATION_TIME_IN;
var ANIMATION_BASE_DELAY_FOR_ITEM = 1 / 4 * ANIMATION_MAX_DELAY_FOR_ITEM;
@@ -27,7 +26,7 @@ var AnimationDirection = {
};
var APPICON_ANIMATION_OUT_SCALE = 3;
var APPICON_ANIMATION_OUT_TIME = 0.25;
var APPICON_ANIMATION_OUT_TIME = 250;
var BaseIcon = GObject.registerClass(
class BaseIcon extends St.Bin {
@@ -142,6 +141,10 @@ class BaseIcon extends St.Bin {
// animating.
zoomOutActor(this.child);
}
update() {
this._createIconTexture(this.iconSize);
}
});
function clamp(value, min, max) {
@@ -169,18 +172,16 @@ function zoomOutActor(actor) {
let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth);
let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight);
Tweener.addTween(actorClone,
{ time: APPICON_ANIMATION_OUT_TIME,
scale_x: APPICON_ANIMATION_OUT_SCALE,
scale_y: APPICON_ANIMATION_OUT_SCALE,
translation_x: containedX - scaledX,
translation_y: containedY - scaledY,
opacity: 0,
transition: 'easeOutQuad',
onComplete() {
actorClone.destroy();
}
});
actorClone.ease({
scale_x: APPICON_ANIMATION_OUT_SCALE,
scale_y: APPICON_ANIMATION_OUT_SCALE,
translation_x: containedX - scaledX,
translation_y: containedY - scaledY,
opacity: 0,
duration: APPICON_ANIMATION_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => actorClone.destroy()
});
}
var IconGrid = GObject.registerClass({
@@ -225,7 +226,7 @@ var IconGrid = GObject.registerClass({
// swarming into the void ...
this.connect('notify::mapped', () => {
if (!this.mapped)
this._cancelAnimation();
this._resetAnimationActors();
});
this.connect('actor-added', this._childAdded.bind(this));
@@ -246,10 +247,23 @@ var IconGrid = GObject.registerClass({
_childAdded(grid, child) {
child._iconGridKeyFocusInId = child.connect('key-focus-in', this._keyFocusIn.bind(this));
child._paintVisible = child.opacity > 0;
child._opacityChangedId = child.connect('notify::opacity', () => {
let paintVisible = child._paintVisible;
child._paintVisible = child.opacity > 0;
if (paintVisible !== child._paintVisible)
this.queue_relayout();
});
}
_childRemoved(grid, child) {
child.disconnect(child._iconGridKeyFocusInId);
delete child._iconGridKeyFocusInId;
child.disconnect(child._opacityChangedId);
delete child._opacityChangedId;
delete child._paintVisible;
}
vfunc_get_preferred_width(_forHeight) {
@@ -413,21 +427,20 @@ var IconGrid = GObject.registerClass({
* set of items to be animated.
*/
_getChildrenToAnimate() {
return this._getVisibleChildren();
return this._getVisibleChildren().filter(child => child.opacity > 0);
}
_cancelAnimation() {
this._clonesAnimating.forEach(clone => clone.destroy());
this._clonesAnimating = [];
}
_animationDone() {
_resetAnimationActors() {
this._clonesAnimating.forEach(clone => {
clone.source.reactive = true;
clone.source.opacity = 255;
clone.destroy();
});
this._clonesAnimating = [];
}
_animationDone() {
this._resetAnimationActors();
this.emit('animation-done');
}
@@ -436,7 +449,7 @@ var IconGrid = GObject.registerClass({
throw new GObject.NotImplementedError("Pulse animation only implements " +
"'in' animation direction");
this._cancelAnimation();
this._resetAnimationActors();
let actors = this._getChildrenToAnimate();
if (actors.length == 0) {
@@ -459,30 +472,32 @@ var IconGrid = GObject.registerClass({
let delay = index / actors.length * maxDelay;
let bounceUpTime = ANIMATION_TIME_IN / 4;
let isLastItem = index == actors.length - 1;
Tweener.addTween(actor,
{ time: bounceUpTime,
transition: 'easeInOutQuad',
delay: delay,
scale_x: ANIMATION_BOUNCE_ICON_SCALE,
scale_y: ANIMATION_BOUNCE_ICON_SCALE,
onComplete: () => {
Tweener.addTween(actor,
{ time: ANIMATION_TIME_IN - bounceUpTime,
transition: 'easeInOutQuad',
scale_x: 1,
scale_y: 1,
onComplete: () => {
if (isLastItem)
this._animationDone();
}
});
}
});
actor.ease({
scale_x: ANIMATION_BOUNCE_ICON_SCALE,
scale_y: ANIMATION_BOUNCE_ICON_SCALE,
duration: bounceUpTime,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay: delay,
onComplete: () => {
let duration = ANIMATION_TIME_IN - bounceUpTime;
actor.ease({
scale_x: 1,
scale_y: 1,
duration,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
onComplete: () => {
if (isLastItem)
this._animationDone();
actor.reactive = true;
}
});
}
});
}
}
animateSpring(animationDirection, sourceActor) {
this._cancelAnimation();
this._resetAnimationActors();
let actors = this._getChildrenToAnimate();
if (actors.length == 0) {
@@ -536,21 +551,25 @@ var IconGrid = GObject.registerClass({
let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM;
let [finalX, finalY] = actor._transformedPosition;
movementParams = { time: ANIMATION_TIME_IN,
transition: 'easeInOutQuad',
delay: delay,
x: finalX,
y: finalY,
scale_x: 1,
scale_y: 1,
onComplete: () => {
if (isLastItem)
this._animationDone();
} };
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: delay,
opacity: 255 };
movementParams = {
x: finalX,
y: finalY,
scale_x: 1,
scale_y: 1,
duration: ANIMATION_TIME_IN,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
if (isLastItem)
movementParams.onComplete = this._animationDone.bind(this);
fadeParams = {
opacity: 255,
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
} else {
let isLastItem = actor._distance == maxDist;
@@ -558,26 +577,29 @@ var IconGrid = GObject.registerClass({
actorClone.set_position(startX, startY);
let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM;
movementParams = { time: ANIMATION_TIME_OUT,
transition: 'easeInOutQuad',
delay: delay,
x: adjustedSourcePositionX,
y: adjustedSourcePositionY,
scale_x: scaleX,
scale_y: scaleY,
onComplete: () => {
if (isLastItem)
this._animationDone();
} };
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM,
opacity: 0 };
movementParams = {
x: adjustedSourcePositionX,
y: adjustedSourcePositionY,
scale_x: scaleX,
scale_y: scaleY,
duration: ANIMATION_TIME_OUT,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
if (isLastItem)
movementParams.onComplete = this._animationDone.bind(this);
fadeParams = {
opacity: 0,
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM
};
}
Tweener.addTween(actorClone, movementParams);
Tweener.addTween(actorClone, fadeParams);
actorClone.ease(movementParams);
actorClone.ease(fadeParams);
}
}
@@ -862,7 +884,7 @@ var PaginatedIconGrid = GObject.registerClass({
// Overridden from IconGrid
_getChildrenToAnimate() {
let children = this._getVisibleChildren();
let children = super._getChildrenToAnimate();
let firstIndex = this._childrenPerPage * this.currentPage;
let lastIndex = firstIndex + this._childrenPerPage;
@@ -982,13 +1004,14 @@ var PaginatedIconGrid = GObject.registerClass({
for (let i = 0; i < children.length; i++) {
children[i].translation_y = 0;
let params = { translation_y: translationY,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad'
};
let params = {
translation_y: translationY,
duration: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD
};
if (i == (children.length - 1))
params.onComplete = () => this.emit('space-opened');
Tweener.addTween(children[i], params);
children[i].ease(params);
}
}
@@ -1001,12 +1024,12 @@ var PaginatedIconGrid = GObject.registerClass({
for (let i = 0; i < this._translatedChildren.length; i++) {
if (!this._translatedChildren[i].translation_y)
continue;
Tweener.addTween(this._translatedChildren[i],
{ translation_y: 0,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad',
onComplete: () => this.emit('space-closed')
});
this._translatedChildren[i].ease({
translation_y: 0,
duration: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
onComplete: () => this.emit('space-closed')
});
}
}
});

View File

@@ -27,7 +27,7 @@ class KbdA11yDialog extends GObject.Object {
if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
key = KEY_SLOW_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) ? true : false;
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0;
title = enabled ?
_("Slow Keys Turned On") :
_("Slow Keys Turned Off");
@@ -36,7 +36,7 @@ class KbdA11yDialog extends GObject.Object {
} else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
key = KEY_STICKY_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) ? true : false;
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0;
title = enabled ?
_("Sticky Keys Turned On") :
_("Sticky Keys Turned Off");

View File

@@ -11,11 +11,10 @@ const Layout = imports.ui.layout;
const Main = imports.ui.main;
const PageIndicators = imports.ui.pageIndicators;
const PopupMenu = imports.ui.popupMenu;
const Tweener = imports.ui.tweener;
var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2;
var KEY_LONG_PRESS_TIME = 250;
var PANEL_SWITCH_ANIMATION_TIME = 0.5;
var PANEL_SWITCH_ANIMATION_TIME = 500;
var PANEL_SWITCH_RELATIVE_DISTANCE = 1 / 3; /* A third of the actor width */
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
@@ -194,12 +193,12 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
item = this.addAction(is.displayName, () => {
inputSourceManager.activateInputSource(is, true);
});
item.actor.can_focus = false;
item.can_focus = false;
}
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
item = this.addSettingsAction(_("Region & Language Settings"), 'gnome-region-panel.desktop');
item.actor.can_focus = false;
item.can_focus = false;
this._capturedEventId = 0;
@@ -570,11 +569,27 @@ var FocusTracker = class {
};
Signals.addSignalMethods(FocusTracker.prototype);
var EmojiPager = class EmojiPager {
constructor(sections, nCols, nRows) {
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
reactive: true,
clip_to_allocation: true });
var EmojiPager = GObject.registerClass({
Properties: {
'delta': GObject.ParamSpec.int(
'delta', 'delta', 'delta',
GObject.ParamFlags.READWRITE,
GLib.MININT32, GLib.MAXINT32, 0)
},
Signals: {
'emoji': { param_types: [GObject.TYPE_STRING] },
'page-changed': {
param_types: [GObject.TYPE_INT, GObject.TYPE_INT, GObject.TYPE_INT]
}
}
}, class EmojiPager extends St.Widget {
_init(sections, nCols, nRows) {
super._init({
layout_manager: new Clutter.BinLayout(),
reactive: true,
clip_to_allocation: true
});
this._sections = sections;
this._nCols = nCols;
this._nRows = nRows;
@@ -596,7 +611,7 @@ var EmojiPager = class EmojiPager {
panAction.connect('gesture-cancel', this._onPanCancel.bind(this));
panAction.connect('gesture-end', this._onPanEnd.bind(this));
this._panAction = panAction;
this.actor.add_action(panAction);
this.add_action(panAction);
}
get delta() {
@@ -609,7 +624,11 @@ var EmojiPager = class EmojiPager {
else if (value < -this._width)
value = -this._width;
if (this._delta == value)
return;
this._delta = value;
this.notify('delta');
if (value == 0)
return;
@@ -626,8 +645,8 @@ var EmojiPager = class EmojiPager {
if (followingPage != null) {
this._followingPanel = this._generatePanel(followingPage);
this._followingPanel.set_pivot_point(0.5, 0.5);
this.actor.add_child(this._followingPanel);
this.actor.set_child_below_sibling(this._followingPanel, this._panel);
this.add_child(this._followingPanel);
this.set_child_below_sibling(this._followingPanel, this._panel);
}
this._followingPage = followingPage;
@@ -675,12 +694,12 @@ var EmojiPager = class EmojiPager {
}
_onPanBegin() {
this._width = this.actor.width;
this._width = this.width;
return true;
}
_onPanEnd() {
if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
if (Math.abs(this._delta) < this.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
this._onPanCancel();
} else {
let value;
@@ -692,28 +711,24 @@ var EmojiPager = class EmojiPager {
let relDelta = Math.abs(this._delta - value) / this._width;
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
Tweener.removeTweens(this);
Tweener.addTween(this,
{ delta: value,
time: time,
transition: 'easeInOutQuad',
onComplete() {
this.setCurrentPage(this.getFollowingPage());
}
});
this.remove_all_transitions();
this.ease_property('delta', value, {
duration: time,
onComplete: () => {
this.setCurrentPage(this.getFollowingPage());
}
});
}
}
_onPanCancel() {
let relDelta = Math.abs(this._delta) / this.actor.width;
let relDelta = Math.abs(this._delta) / this.width;
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
Tweener.removeTweens(this);
Tweener.addTween(this,
{ delta: 0,
time: time,
transition: 'easeInOutQuad',
});
this.remove_all_transitions();
this.ease_property('delta', 0, {
duration: time,
});
}
_initPagingInfo() {
@@ -823,7 +838,7 @@ var EmojiPager = class EmojiPager {
if (!this._panel) {
this._panel = this._generatePanel(nPage);
this.actor.add_child(this._panel);
this.add_child(this._panel);
}
let page = this._pages[nPage];
@@ -840,8 +855,7 @@ var EmojiPager = class EmojiPager {
}
}
}
};
Signals.addSignalMethods(EmojiPager.prototype);
});
var EmojiSelection = class EmojiSelection {
constructor() {
@@ -1654,19 +1668,23 @@ var Keyboard = class Keyboard {
return;
if (show) {
Tweener.addTween(windowActor,
{ y: windowActor.y - deltaY,
time: Layout.KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._windowSlideAnimationComplete,
onCompleteParams: [window, -deltaY] });
windowActor.ease({
y: windowActor.y - deltaY,
duration: Layout.KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._windowSlideAnimationComplete(window, -deltaY);
}
});
} else {
Tweener.addTween(windowActor,
{ y: windowActor.y + deltaY,
time: Layout.KEYBOARD_ANIMATION_TIME,
transition: 'easeInQuad',
onComplete: this._windowSlideAnimationComplete,
onCompleteParams: [window, deltaY] });
windowActor.ease({
y: windowActor.y + deltaY,
duration: Layout.KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._windowSlideAnimationComplete(window, deltaY);
}
});
}
}

View File

@@ -11,12 +11,11 @@ const LoginManager = imports.misc.loginManager;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Ripples = imports.ui.ripples;
var STARTUP_ANIMATION_TIME = 0.5;
var KEYBOARD_ANIMATION_TIME = 0.15;
var BACKGROUND_FADE_ANIMATION_TIME = 1.0;
var STARTUP_ANIMATION_TIME = 500;
var KEYBOARD_ANIMATION_TIME = 150;
var BACKGROUND_FADE_ANIMATION_TIME = 1000;
var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
@@ -239,11 +238,12 @@ var LayoutManager = GObject.registerClass({
reactive: true });
this.addChrome(this.overviewGroup);
this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.screenShieldGroup = new St.Widget({
name: 'screenShieldGroup',
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.addChrome(this.screenShieldGroup);
this.panelBox = new St.BoxLayout({ name: 'panelBox',
@@ -464,10 +464,11 @@ var LayoutManager = GObject.registerClass({
let backgroundActor = this._bgManagers[i].backgroundActor;
backgroundActor.show();
backgroundActor.opacity = 0;
Tweener.addTween(backgroundActor,
{ opacity: 255,
time: BACKGROUND_FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
backgroundActor.ease({
opacity: 255,
duration: BACKGROUND_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
}
@@ -698,23 +699,23 @@ var LayoutManager = GObject.registerClass({
}
_startupAnimationGreeter() {
Tweener.addTween(this.panelBox,
{ translation_y: 0,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this });
this.panelBox.ease({
translation_y: 0,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._startupAnimationComplete()
});
}
_startupAnimationSession() {
Tweener.addTween(this.uiGroup,
{ scale_x: 1,
scale_y: 1,
opacity: 255,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this });
this.uiGroup.ease({
scale_x: 1,
scale_y: 1,
opacity: 255,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._startupAnimationComplete()
});
}
_startupAnimationComplete() {
@@ -740,14 +741,15 @@ var LayoutManager = GObject.registerClass({
showKeyboard() {
this.keyboardBox.show();
Tweener.addTween(this.keyboardBox,
{ anchor_y: this.keyboardBox.height,
opacity: 255,
time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showKeyboardComplete,
onCompleteScope: this
});
this.keyboardBox.ease({
anchor_y: this.keyboardBox.height,
opacity: 255,
duration: KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._showKeyboardComplete();
}
});
this.emit('keyboard-visible-changed', true);
}
@@ -766,14 +768,16 @@ var LayoutManager = GObject.registerClass({
this.keyboardBox.disconnect(this._keyboardHeightNotifyId);
this._keyboardHeightNotifyId = 0;
}
Tweener.addTween(this.keyboardBox,
{ anchor_y: 0,
opacity: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeInQuad',
onComplete: this._hideKeyboardComplete,
onCompleteScope: this
});
this.keyboardBox.ease({
anchor_y: 0,
opacity: 0,
duration: immediate ? 0
: KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._hideKeyboardComplete();
}
});
this.emit('keyboard-visible-changed', false);
}
@@ -857,7 +861,7 @@ var LayoutManager = GObject.registerClass({
// We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor
for (let prop in defaultParams) {
if (!params.hasOwnProperty(prop))
if (!Object.prototype.hasOwnProperty.call(params, prop))
params[prop] = ancestorData[prop];
}
@@ -1221,6 +1225,8 @@ var HotCorner = class HotCorner {
if (this.actor)
this.actor.destroy();
this._ripples.destroy();
}
_toggleOverview() {

View File

@@ -5,7 +5,6 @@ const { Clutter, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_FADE_FACTOR = 0.4;
var VIGNETTE_BRIGHTNESS = 0.2;
@@ -24,16 +23,31 @@ t = clamp(t, 0.0, 1.0);\n\
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
var RadialShaderEffect = GObject.registerClass(
class RadialShaderEffect extends Shell.GLSLEffect {
var RadialShaderEffect = GObject.registerClass({
Properties: {
'brightness': GObject.ParamSpec.float(
'brightness', 'brightness', 'brightness',
GObject.ParamFlags.READWRITE,
0, 1, 1
),
'sharpness': GObject.ParamSpec.float(
'sharpness', 'sharpness', 'sharpness',
GObject.ParamFlags.READWRITE,
0, 1, 0
)
}
}, class RadialShaderEffect extends Shell.GLSLEffect {
_init(params) {
this._brightness = undefined;
this._sharpness = undefined;
super._init(params);
this._brightnessLocation = this.get_uniform_location('brightness');
this._sharpnessLocation = this.get_uniform_location('vignette_sharpness');
this.brightness = 1.0;
this.vignetteSharpness = 0.0;
this.sharpness = 0.0;
}
vfunc_build_pipeline() {
@@ -46,19 +60,25 @@ class RadialShaderEffect extends Shell.GLSLEffect {
}
set brightness(v) {
if (this._brightness == v)
return;
this._brightness = v;
this.set_uniform_float(this._brightnessLocation,
1, [this._brightness]);
this.notify('brightness');
}
get vignetteSharpness() {
get sharpness() {
return this._sharpness;
}
set vignetteSharpness(v) {
set sharpness(v) {
if (this._sharpness == v)
return;
this._sharpness = v;
this.set_uniform_float(this._sharpnessLocation,
1, [this._sharpness]);
this.notify('sharpness');
}
});
@@ -69,8 +89,8 @@ class RadialShaderEffect extends Shell.GLSLEffect {
* - inhibitEvents: whether to inhibit events for @container
* - width: shade actor width
* - height: shade actor height
* - fadeInTime: seconds used to fade in
* - fadeOutTime: seconds used to fade out
* - fadeInTime: milliseconds used to fade in
* - fadeOutTime: milliseconds used to fade out
*
* Lightbox creates a dark translucent "shade" actor to hide the
* contents of @container, and allows you to specify particular actors
@@ -88,12 +108,13 @@ class RadialShaderEffect extends Shell.GLSLEffect {
*/
var Lightbox = class Lightbox {
constructor(container, params) {
params = Params.parse(params, { inhibitEvents: false,
width: null,
height: null,
fadeFactor: DEFAULT_FADE_FACTOR,
radialEffect: false,
});
params = Params.parse(params, {
inhibitEvents: false,
width: null,
height: null,
fadeFactor: DEFAULT_FADE_FACTOR,
radialEffect: false,
});
this._container = container;
this._children = container.get_children();
@@ -152,65 +173,52 @@ var Lightbox = class Lightbox {
}
show(fadeInTime) {
fadeInTime = fadeInTime || 0;
this.actor.remove_all_transitions();
let easeProps = {
duration: fadeInTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => {
this.shown = true;
this.emit('shown');
};
if (this._radialEffect) {
let effect = this.actor.get_effect('radial');
Tweener.removeTweens(effect);
Tweener.addTween(effect,
{ brightness: VIGNETTE_BRIGHTNESS,
vignetteSharpness: VIGNETTE_SHARPNESS,
time: fadeInTime,
transition: 'easeOutQuad',
onComplete: () => {
this.shown = true;
this.emit('shown');
}
});
this.actor.ease_property(
'@effects.radial.brightness', VIGNETTE_BRIGHTNESS, easeProps);
this.actor.ease_property(
'@effects.radial.sharpness', VIGNETTE_SHARPNESS,
Object.assign({ onComplete }, easeProps));
} else {
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 255 * this._fadeFactor,
time: fadeInTime,
transition: 'easeOutQuad',
onComplete: () => {
this.shown = true;
this.emit('shown');
}
});
this.actor.ease(Object.assign(easeProps, {
opacity: 255 * this._fadeFactor,
onComplete
}));
}
this.actor.show();
}
hide(fadeOutTime) {
fadeOutTime = fadeOutTime || 0;
this.shown = false;
this.actor.remove_all_transitions();
let easeProps = {
duration: fadeOutTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => this.actor.hide();
if (this._radialEffect) {
let effect = this.actor.get_effect('radial');
Tweener.removeTweens(effect);
Tweener.addTween(effect,
{ brightness: 1.0,
vignetteSharpness: 0.0,
opacity: 0,
time: fadeOutTime,
transition: 'easeOutQuad',
onComplete: () => {
this.actor.hide();
}
});
this.actor.ease_property(
'@effects.radial.brightness', 1.0, easeProps);
this.actor.ease_property(
'@effects.radial.sharpness', 0.0, Object.assign({ onComplete }, easeProps));
} else {
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 0,
time: fadeOutTime,
transition: 'easeOutQuad',
onComplete: () => {
this.actor.hide();
}
});
this.actor.ease(Object.assign(easeProps, { opacity: 0, onComplete }));
}
}

View File

@@ -11,12 +11,26 @@ const LOCATE_POINTER_SCHEMA = "org.gnome.desktop.interface";
var LocatePointer = class {
constructor() {
this._settings = new Gio.Settings({ schema_id: LOCATE_POINTER_SCHEMA });
this._ripples = new Ripples.Ripples(0.5, 0.5, 'ripple-pointer-location');
this._ripples.addTo(Main.uiGroup);
this._settings.connect(`changed::${LOCATE_POINTER_KEY}`, () => this._syncEnabled());
this._syncEnabled();
}
_syncEnabled() {
let enabled = this._settings.get_boolean(LOCATE_POINTER_KEY);
if (enabled == !!this._ripples)
return;
if (enabled) {
this._ripples = new Ripples.Ripples(0.5, 0.5, 'ripple-pointer-location');
this._ripples.addTo(Main.uiGroup);
} else {
this._ripples.destroy();
this._ripples = null;
}
}
show() {
if (!this._settings.get_boolean(LOCATE_POINTER_KEY))
if (!this._ripples)
return;
let [x, y] = global.get_pointer();

View File

@@ -3,14 +3,12 @@
const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const System = imports.system;
const History = imports.misc.history;
const ExtensionUtils = imports.misc.extensionUtils;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const JsParse = imports.misc.jsParse;
@@ -21,8 +19,6 @@ const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
'const Main = imports.ui.main; ' +
'const Mainloop = imports.mainloop; ' +
'const Tweener = imports.ui.tweener; ' +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
'const stage = global.stage; ' +
@@ -34,9 +30,11 @@ var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = im
const HISTORY_KEY = 'looking-glass-history';
// Time between tabs for them to count as a double-tab event
var AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
var AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 0.2;
var AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 200;
var AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
const LG_ANIMATION_TIME = 500;
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of window (i.e., ones starting with '_')
@@ -240,7 +238,7 @@ var Notebook = class Notebook {
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) {
if (typeof(o) == typeof(objectToString)) {
if (typeof o == typeof objectToString) {
// special case this since the default is way, way too verbose
return '<js function>';
} else {
@@ -306,6 +304,9 @@ var WindowList = class WindowList {
}
_updateWindowList() {
if (!this._lookingGlass.isOpen)
return;
this.actor.destroy_all_children();
let windows = global.get_window_actors();
let tracker = Shell.WindowTracker.get_default();
@@ -337,6 +338,10 @@ var WindowList = class WindowList {
}
}
}
update() {
this._updateWindowList();
}
};
Signals.addSignalMethods(WindowList.prototype);
@@ -369,7 +374,7 @@ var ObjInspector = class ObjInspector {
let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' });
this._container.add_actor(hbox);
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof(obj),
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof obj,
objectToString(obj)) });
label.single_line_mode = true;
hbox.add(label, { expand: true, y_fill: false });
@@ -387,7 +392,7 @@ var ObjInspector = class ObjInspector {
button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
button.connect('clicked', this.close.bind(this));
hbox.add(button);
if (typeof(obj) == typeof({})) {
if (typeof obj == typeof {}) {
let properties = [];
for (let propName in obj) {
properties.push(propName);
@@ -419,9 +424,12 @@ var ObjInspector = class ObjInspector {
this.actor.show();
if (sourceActor) {
this.actor.set_scale(0, 0);
Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
transition: 'easeOutQuad',
time: 0.2 });
this.actor.ease({
scale_x: 1,
scale_y: 1,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
time: 200
});
} else {
this.actor.set_scale(1, 1);
}
@@ -818,7 +826,7 @@ var LookingGlass = class LookingGlass {
gcIcon.connect('button-press-event', () => {
gcIcon.icon_name = 'user-trash';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, () => {
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => {
gcIcon.icon_name = 'user-trash-full';
this._timeoutId = 0;
return GLib.SOURCE_REMOVE;
@@ -941,7 +949,7 @@ var LookingGlass = class LookingGlass {
this._completionActor.set_text(completions.join(', '));
// Setting the height to -1 allows us to get its actual preferred height rather than
// whatever was last given in set_height by Tweener.
// whatever was last set when animating
this._completionActor.set_height(-1);
let [, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width());
@@ -950,28 +958,32 @@ var LookingGlass = class LookingGlass {
this._completionActor.height = naturalHeight;
} else {
let settings = St.Settings.get();
let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
this._completionActor.show();
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor,
transition: 'easeOutQuad',
height: naturalHeight,
opacity: 255
});
this._completionActor.remove_all_transitions();
this._completionActor.ease({
height: naturalHeight,
opacity: 255,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
_hideCompletions() {
if (this._completionActor) {
let settings = St.Settings.get();
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor,
transition: 'easeOutQuad',
height: 0,
opacity: 0,
onComplete: () => {
this._completionActor.hide();
}
});
let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
this._completionActor.remove_all_transitions();
this._completionActor.ease({
height: 0,
opacity: 0,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._completionActor.hide();
}
});
}
}
@@ -1003,7 +1015,11 @@ var LookingGlass = class LookingGlass {
}
getResult(idx) {
return this._results[idx - this._offset].o;
try {
return this._results[idx - this._offset].o;
} catch (e) {
throw new Error(`Unknown result at index ${idx}`);
}
}
toggle() {
@@ -1080,15 +1096,18 @@ var LookingGlass = class LookingGlass {
this._open = true;
this._history.lastItem();
Tweener.removeTweens(this.actor);
this.actor.remove_all_transitions();
// We inverse compensate for the slow-down so you can change the factor
// through LookingGlass without long waits.
let settings = St.Settings.get();
Tweener.addTween(this.actor, { time: 0.5 / settings.slow_down_factor,
transition: 'easeOutQuad',
y: this._targetY
});
let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor;
this.actor.ease({
y: this._targetY,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._windowList.update();
}
close() {
@@ -1098,20 +1117,25 @@ var LookingGlass = class LookingGlass {
this._objInspector.actor.hide();
this._open = false;
Tweener.removeTweens(this.actor);
this.actor.remove_all_transitions();
this.setBorderPaintTarget(null);
Main.popModal(this._entry);
let settings = St.Settings.get();
Tweener.addTween(this.actor, { time: Math.min(0.5 / settings.slow_down_factor, 0.5),
transition: 'easeOutQuad',
y: this._hiddenY,
onComplete: () => {
this.actor.hide();
}
});
let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor,
LG_ANIMATION_TIME);
this.actor.ease({
y: this._hiddenY,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.actor.hide()
});
}
get isOpen() {
return this._open;
}
};
Signals.addSignalMethods(LookingGlass.prototype);

View File

@@ -2,7 +2,6 @@
const { Atspi, Clutter, GDesktopEnums,
Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -1144,7 +1143,7 @@ var ZoomRegion = class ZoomRegion {
_clearScrollContentsTimer() {
if (this._scrollContentsTimerId != 0) {
Mainloop.source_remove(this._scrollContentsTimerId);
GLib.source_remove(this._scrollContentsTimerId);
this._scrollContentsTimerId = 0;
}
}
@@ -1156,7 +1155,7 @@ var ZoomRegion = class ZoomRegion {
}
this._clearScrollContentsTimer();
this._scrollContentsTimerId = Mainloop.timeout_add(POINTER_REST_TIME, () => {
this._scrollContentsTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, POINTER_REST_TIME, () => {
this._scrollContentsToDelayed(x, y);
return GLib.SOURCE_REMOVE;
});

View File

@@ -9,7 +9,6 @@
initializeDeferredWork, getThemeStylesheet, setThemeStylesheet */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const AccessDialog = imports.ui.accessDialog;
const AudioDeviceSelection = imports.ui.audioDeviceSelection;
@@ -620,7 +619,7 @@ function _runDeferredWork(workId) {
_deferredWorkQueue.splice(index, 1);
_deferredWorkData[workId].callback();
if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
Mainloop.source_remove(_deferredTimeoutId);
GLib.source_remove(_deferredTimeoutId);
_deferredTimeoutId = 0;
}
}
@@ -708,7 +707,7 @@ function queueDeferredWork(workId) {
_queueBeforeRedraw(workId);
return;
} else if (_deferredTimeoutId == 0) {
_deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, () => {
_deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => {
_runAllDeferredWork();
_deferredTimeoutId = 0;
return GLib.SOURCE_REMOVE;

View File

@@ -4,10 +4,9 @@ const MessageTray = imports.ui.messageTray;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
var MESSAGE_ANIMATION_TIME = 0.1;
var MESSAGE_ANIMATION_TIME = 100;
var DEFAULT_EXPAND_LINES = 6;
@@ -440,15 +439,17 @@ var Message = class Message {
}
if (animate) {
Tweener.addTween(this._bodyStack.layout_manager,
{ expansion: 1,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad' });
this._bodyStack.ease_property('@layout.expansion', 1, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: MessageTray.ANIMATION_TIME,
});
this._actionBin.scale_y = 0;
Tweener.addTween(this._actionBin,
{ scale_y: 1,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad' });
this._actionBin.ease({
scale_y: 1,
duration: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} else {
this._bodyStack.layout_manager.expansion = 1;
this._actionBin.scale_y = 1;
@@ -459,18 +460,20 @@ var Message = class Message {
unexpand(animate) {
if (animate) {
Tweener.addTween(this._bodyStack.layout_manager,
{ expansion: 0,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad' });
Tweener.addTween(this._actionBin,
{ scale_y: 0,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._actionBin.hide();
this.expanded = false;
} });
this._bodyStack.ease_property('@layout.expansion', 0, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: MessageTray.ANIMATION_TIME,
});
this._actionBin.ease({
scale_y: 0,
duration: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._actionBin.hide();
this.expanded = false;
}
});
} else {
this._bodyStack.layout_manager.expansion = 0;
this._actionBin.scale_y = 0;
@@ -581,10 +584,12 @@ var MessageListSection = class MessageListSection {
this._list.insert_child_at_index(obj.container, index);
if (animate)
Tweener.addTween(obj.container, { scale_x: 1,
scale_y: 1,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad' });
obj.container.ease({
scale_x: 1,
scale_y: 1,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
moveMessage(message, index, animate) {
@@ -597,16 +602,20 @@ var MessageListSection = class MessageListSection {
let onComplete = () => {
this._list.set_child_at_index(obj.container, index);
Tweener.addTween(obj.container, { scale_x: 1,
scale_y: 1,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad' });
obj.container.ease({
scale_x: 1,
scale_y: 1,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
};
Tweener.addTween(obj.container, { scale_x: 0,
scale_y: 0,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: onComplete });
obj.container.ease({
scale_x: 0,
scale_y: 0,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete
});
}
removeMessage(message, animate) {
@@ -619,13 +628,16 @@ var MessageListSection = class MessageListSection {
this._messages.delete(message);
if (animate) {
Tweener.addTween(obj.container, { scale_x: 0, scale_y: 0,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
obj.container.destroy();
global.sync_pointer();
} });
obj.container.ease({
scale_x: 0,
scale_y: 0,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
obj.container.destroy();
global.sync_pointer();
}
});
} else {
obj.container.destroy();
global.sync_pointer();
@@ -647,15 +659,14 @@ var MessageListSection = class MessageListSection {
for (let i = 0; i < messages.length; i++) {
let message = messages[i];
let obj = this._messages.get(message);
Tweener.addTween(obj.container,
{ anchor_x: this._list.width,
opacity: 0,
time: MESSAGE_ANIMATION_TIME,
delay: i * delay,
transition: 'easeOutQuad',
onComplete() {
message.close();
} });
obj.container.ease({
anchor_x: this._list.width,
opacity: 0,
duration: MESSAGE_ANIMATION_TIME,
delay: i * delay,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => message.close()
});
}
}
}

View File

@@ -4,7 +4,6 @@
SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
@@ -12,15 +11,14 @@ const GnomeSession = imports.misc.gnomeSession;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
var ANIMATION_TIME = 0.2;
var NOTIFICATION_TIMEOUT = 4;
var ANIMATION_TIME = 200;
var NOTIFICATION_TIMEOUT = 4000;
var HIDE_TIMEOUT = 0.2;
var LONGER_HIDE_TIMEOUT = 0.6;
var HIDE_TIMEOUT = 200;
var LONGER_HIDE_TIMEOUT = 600;
var MAX_NOTIFICATIONS_IN_QUEUE = 3;
var MAX_NOTIFICATIONS_PER_SOURCE = 3;
@@ -138,13 +136,14 @@ var FocusGrabber = class FocusGrabber {
// A notification without a policy object will inherit the default one.
var NotificationPolicy = class NotificationPolicy {
constructor(params) {
params = Params.parse(params, { enable: true,
enableSound: true,
showBanners: true,
forceExpanded: false,
showInLockScreen: true,
detailsInLockScreen: false
});
params = Params.parse(params, {
enable: true,
enableSound: true,
showBanners: true,
forceExpanded: false,
showInLockScreen: true,
detailsInLockScreen: false,
});
Object.getOwnPropertyNames(params).forEach(key => {
let desc = Object.getOwnPropertyDescriptor(params, key);
Object.defineProperty(this, `_${key}`, desc);
@@ -154,6 +153,7 @@ var NotificationPolicy = class NotificationPolicy {
// Do nothing for the default policy. These methods are only useful for the
// GSettings policy.
store() { }
destroy() { }
get enable() {
@@ -1005,7 +1005,6 @@ var MessageTray = class MessageTray {
_addSource(source) {
let obj = {
source: source,
notifyId: 0,
destroyId: 0,
};
@@ -1092,7 +1091,7 @@ var MessageTray = class MessageTray {
_resetNotificationLeftTimeout() {
this._useLongerNotificationLeftTimeout = false;
if (this._notificationLeftTimeoutId) {
Mainloop.source_remove(this._notificationLeftTimeoutId);
GLib.source_remove(this._notificationLeftTimeoutId);
this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1;
this._notificationLeftMouseY = -1;
@@ -1137,8 +1136,8 @@ var MessageTray = class MessageTray {
// We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it.
// We wait for a longer period if the notification popped up where the mouse pointer was already positioned.
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, this._onNotificationLeftTimeout.bind(this));
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT : HIDE_TIMEOUT;
this._notificationLeftTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
}
}
@@ -1167,8 +1166,10 @@ var MessageTray = class MessageTray {
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
this._notificationLeftMouseX = -1;
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
this._onNotificationLeftTimeout.bind(this));
this._notificationLeftTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
LONGER_HIDE_TIMEOUT,
this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} else {
this._notificationLeftTimeoutId = 0;
@@ -1249,34 +1250,6 @@ var MessageTray = class MessageTray {
this._notificationExpired = false;
}
_tween(actor, statevar, value, params) {
let onComplete = params.onComplete;
let onCompleteScope = params.onCompleteScope;
let onCompleteParams = params.onCompleteParams;
params.onComplete = this._tweenComplete;
params.onCompleteScope = this;
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
// Remove other tweens that could mess with the state machine
Tweener.removeTweens(actor);
Tweener.addTween(actor, params);
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
this[statevar] = valuing;
}
_tweenComplete(statevar, value, onComplete, onCompleteScope, onCompleteParams) {
this[statevar] = value;
if (onComplete)
onComplete.apply(onCompleteScope, onCompleteParams);
this._updateState();
}
_clampOpacity() {
this._bannerBin.opacity = Math.max(0, Math.min(this._bannerBin._opacity, 255));
}
_onIdleMonitorBecameActive() {
this._userActiveWhileNotificationShown = true;
this._updateNotificationTimeout(2000);
@@ -1303,7 +1276,6 @@ var MessageTray = class MessageTray {
this._bannerBin.add_actor(this._banner.actor);
this._bannerBin._opacity = 0;
this._bannerBin.opacity = 0;
this._bannerBin.y = -this._banner.actor.height;
this.actor.show();
@@ -1349,33 +1321,39 @@ var MessageTray = class MessageTray {
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
// notification is being shown.
let tweenParams = { y: 0,
_opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutBack',
onUpdate: this._clampOpacity,
onUpdateScope: this,
onComplete: this._showNotificationCompleted,
onCompleteScope: this
};
this._tween(this._bannerBin, '_notificationState', State.SHOWN, tweenParams);
this._notificationState = State.SHOWING;
this._bannerBin.remove_all_transitions();
this._bannerBin.ease({
opacity: 255,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR
});
this._bannerBin.ease({
y: 0,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK,
onComplete: () => {
this._notificationState = State.SHOWN;
this._showNotificationCompleted();
this._updateState();
}
});
}
_showNotificationCompleted() {
if (this._notification.urgency != Urgency.CRITICAL)
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000);
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT);
}
_updateNotificationTimeout(timeout) {
if (this._notificationTimeoutId) {
Mainloop.source_remove(this._notificationTimeoutId);
GLib.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0;
}
if (timeout > 0) {
this._notificationTimeoutId =
Mainloop.timeout_add(timeout,
this._notificationTimeout.bind(this));
GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout,
this._notificationTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout');
}
}
@@ -1417,20 +1395,26 @@ var MessageTray = class MessageTray {
}
this._resetNotificationLeftTimeout();
this._bannerBin.remove_all_transitions();
if (animate) {
this._tween(this._bannerBin, '_notificationState', State.HIDDEN,
{ y: -this._bannerBin.height,
_opacity: 0,
time: ANIMATION_TIME,
transition: 'easeOutBack',
onUpdate: this._clampOpacity,
onUpdateScope: this,
onComplete: this._hideNotificationCompleted,
onCompleteScope: this
});
this._notificationState = State.HIDING;
this._bannerBin.ease({
opacity: 0,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK
});
this._bannerBin.ease({
y: -this._bannerBin.height,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK,
onComplete: () => {
this._notificationState = State.HIDDEN;
this._hideNotificationCompleted();
this._updateState();
}
});
} else {
Tweener.removeTweens(this._bannerBin);
this._bannerBin.y = -this._bannerBin.height;
this._bannerBin.opacity = 0;
this._notificationState = State.HIDDEN;

View File

@@ -8,10 +8,9 @@ const Layout = imports.ui.layout;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var OPEN_AND_CLOSE_TIME = 0.1;
var FADE_OUT_DIALOG_TIME = 1.0;
var OPEN_AND_CLOSE_TIME = 100;
var FADE_OUT_DIALOG_TIME = 1000;
var State = {
OPENED: 0,
@@ -125,15 +124,15 @@ var ModalDialog = GObject.registerClass({
this._lightbox.show();
this.opacity = 0;
this.show();
Tweener.addTween(this,
{ opacity: 255,
time: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
transition: 'easeOutQuad',
onComplete: () => {
this._setState(State.OPENED);
this.emit('opened');
}
});
this.ease({
opacity: 255,
duration: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._setState(State.OPENED);
this.emit('opened');
}
});
}
setInitialKeyFocus(actor) {
@@ -176,15 +175,16 @@ var ModalDialog = GObject.registerClass({
this.popModal(timestamp);
this._savedKeyFocus = null;
if (this._shouldFadeOut)
Tweener.addTween(this,
{ opacity: 0,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: this._closeComplete.bind(this)
});
else
if (this._shouldFadeOut) {
this.ease({
opacity: 0,
duration: OPEN_AND_CLOSE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._closeComplete()
});
} else {
this._closeComplete();
}
}
// Drop modal status without closing the dialog; this makes the
@@ -249,13 +249,11 @@ var ModalDialog = GObject.registerClass({
return;
this.popModal(timestamp);
Tweener.addTween(this.dialogLayout,
{ opacity: 0,
time: FADE_OUT_DIALOG_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._setState(State.FADED_OUT);
}
});
this.dialogLayout.ease({
opacity: 0,
duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.state = State.FADED_OUT
});
}
});

View File

@@ -2,7 +2,6 @@
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Config = imports.misc.config;
const Main = imports.ui.main;
@@ -171,7 +170,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// Ignore replacesId since we already sent back a
// NotificationClosed for that id.
id = this._nextNotificationId++;
let idleId = Mainloop.idle_add(() => {
let idleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return GLib.SOURCE_REMOVE;
});
@@ -750,29 +749,33 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
_loadNotifications() {
this._isLoading = true;
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(([appId, notifications]) => {
if (notifications.length == 0)
return;
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
try {
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(([appId, notifications]) => {
if (notifications.length == 0)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
source.addNotification(notificationId, notification.deep_unpack(), false);
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
source.addNotification(notificationId, notification.deep_unpack(), false);
});
});
});
}
} catch (e) {
logError(e, 'Failed to load saved notifications');
} finally {
this._isLoading = false;
}
this._isLoading = false;
}
_saveNotifications() {

View File

@@ -2,16 +2,14 @@
/* exported OsdWindowManager */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
const BarLevel = imports.ui.barLevel;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var HIDE_TIMEOUT = 1500;
var FADE_TIME = 0.1;
var LEVEL_ANIMATION_TIME = 0.1;
var FADE_TIME = 100;
var LEVEL_ANIMATION_TIME = 100;
var OsdWindowConstraint = GObject.registerClass(
class OsdWindowConstraint extends Clutter.Constraint {
@@ -66,8 +64,11 @@ var OsdWindow = class {
this._label = new St.Label();
this._box.add(this._label);
this._level = new BarLevel.BarLevel(0, { styleClass: 'level' });
this._box.add(this._level.actor);
this._level = new BarLevel.BarLevel({
style_class: 'level',
value: 0
});
this._box.add(this._level);
this._hideTimeoutId = 0;
this._reset();
@@ -107,13 +108,13 @@ var OsdWindow = class {
}
setLevel(value) {
this._level.actor.visible = (value != undefined);
this._level.visible = (value != undefined);
if (value != undefined) {
if (this.actor.visible)
Tweener.addTween(this._level,
{ value: value,
time: LEVEL_ANIMATION_TIME,
transition: 'easeOutQuad' });
this._level.ease_property('value', value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: LEVEL_ANIMATION_TIME
});
else
this._level.value = value;
}
@@ -133,16 +134,17 @@ var OsdWindow = class {
this.actor.opacity = 0;
this.actor.get_parent().set_child_above_sibling(this.actor, null);
Tweener.addTween(this.actor,
{ opacity: 255,
time: FADE_TIME,
transition: 'easeOutQuad' });
this.actor.ease({
opacity: 255,
duration: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
if (this._hideTimeoutId)
Mainloop.source_remove(this._hideTimeoutId);
this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT,
this._hide.bind(this));
GLib.source_remove(this._hideTimeoutId);
this._hideTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, HIDE_TIMEOUT, this._hide.bind(this));
GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide');
}
@@ -150,21 +152,21 @@ var OsdWindow = class {
if (!this._hideTimeoutId)
return;
Mainloop.source_remove(this._hideTimeoutId);
GLib.source_remove(this._hideTimeoutId);
this._hide();
}
_hide() {
this._hideTimeoutId = 0;
Tweener.addTween(this.actor,
{ opacity: 0,
time: FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._reset();
Meta.enable_unredirect_for_display(global.display);
}
});
this.actor.ease({
opacity: 0,
duration: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._reset();
Meta.enable_unredirect_for_display(global.display);
}
});
return GLib.SOURCE_REMOVE;
}

View File

@@ -2,7 +2,6 @@
/* exported Overview */
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -13,16 +12,15 @@ const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode
var ANIMATION_TIME = 0.25;
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
var SHADE_ANIMATION_TIME = .20;
var SHADE_ANIMATION_TIME = 200;
var DND_WINDOW_SWITCH_TIMEOUT = 750;
@@ -44,9 +42,10 @@ var ShellInfo = class {
}
setMessage(text, options) {
options = Params.parse(options, { undoCallback: null,
forFeedback: false
});
options = Params.parse(options, {
undoCallback: null,
forFeedback: false,
});
let undoCallback = options.undoCallback;
let forFeedback = options.forFeedback;
@@ -174,24 +173,28 @@ var Overview = class {
_unshadeBackgrounds() {
let backgrounds = this._backgroundGroup.get_children();
for (let i = 0; i < backgrounds.length; i++) {
Tweener.addTween(backgrounds[i],
{ brightness: 1.0,
vignette_sharpness: 0.0,
time: SHADE_ANIMATION_TIME,
transition: 'easeOutQuad'
});
backgrounds[i].ease_property('brightness', 1.0, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
backgrounds[i].ease_property('vignette-sharpness', 0.0, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
_shadeBackgrounds() {
let backgrounds = this._backgroundGroup.get_children();
for (let i = 0; i < backgrounds.length; i++) {
Tweener.addTween(backgrounds[i],
{ brightness: Lightbox.VIGNETTE_BRIGHTNESS,
vignette_sharpness: Lightbox.VIGNETTE_SHARPNESS,
time: SHADE_ANIMATION_TIME,
transition: 'easeOutQuad'
});
backgrounds[i].ease_property('brightness', Lightbox.VIGNETTE_BRIGHTNESS, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
backgrounds[i].ease_property('vignette-sharpness', Lightbox.VIGNETTE_SHARPNESS, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
@@ -297,7 +300,7 @@ var Overview = class {
_resetWindowSwitchTimeout() {
if (this._windowSwitchTimeoutId != 0) {
Mainloop.source_remove(this._windowSwitchTimeoutId);
GLib.source_remove(this._windowSwitchTimeoutId);
this._windowSwitchTimeoutId = 0;
}
}
@@ -320,7 +323,9 @@ var Overview = class {
if (targetIsWindow) {
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
this._windowSwitchTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
DND_WINDOW_SWITCH_TIMEOUT,
() => {
this._windowSwitchTimeoutId = 0;
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
@@ -427,10 +432,11 @@ var Overview = class {
fadeInDesktop() {
this._desktopFade.opacity = 0;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
this._desktopFade.ease({
opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME
});
}
fadeOutDesktop() {
@@ -444,11 +450,11 @@ var Overview = class {
this._desktopFade.opacity = 255;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 0,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
this._desktopFade.ease({
opacity: 0,
mode: Clutter.Animates.EASE_OUT_QUAD,
duration: ANIMATION_TIME
});
}
// Checks if the Activities button is currently sensitive to
@@ -477,15 +483,13 @@ var Overview = class {
if (this._shown) {
let shouldBeModal = !this._inXdndDrag;
if (shouldBeModal) {
if (!this._modal) {
if (Main.pushModal(this._overview,
{ actionMode: Shell.ActionMode.OVERVIEW })) {
this._modal = true;
} else {
this.hide();
return false;
}
if (shouldBeModal && !this._modal) {
let actionMode = Shell.ActionMode.OVERVIEW;
if (Main.pushModal(this._overview, { actionMode })) {
this._modal = true;
} else {
this.hide();
return false;
}
}
} else {
@@ -528,13 +532,12 @@ var Overview = class {
this.viewSelector.show();
this._overview.opacity = 0;
Tweener.addTween(this._overview,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._showDone,
onCompleteScope: this
});
this._overview.ease({
opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME,
onComplete: () => this._showDone()
});
this._shadeBackgrounds();
this._coverPane.raise_top();
@@ -592,13 +595,12 @@ var Overview = class {
this.viewSelector.animateFromOverview();
// Make other elements fade out.
Tweener.addTween(this._overview,
{ opacity: 0,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._hideDone,
onCompleteScope: this
});
this._overview.ease({
opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME,
onComplete: () => this._hideDone()
});
this._unshadeBackgrounds();
this._coverPane.raise_top();

View File

@@ -6,11 +6,10 @@ const { Clutter, GObject, Meta, St } = imports.gi;
const Dash = imports.ui.dash;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
var SIDE_CONTROLS_ANIMATION_TIME = 0.16;
var SIDE_CONTROLS_ANIMATION_TIME = 160;
function getRtlSlideDirection(direction, actor) {
let rtl = (actor.text_direction == Clutter.TextDirection.RTL);
@@ -26,11 +25,21 @@ var SlideDirection = {
RIGHT: 1
};
var SlideLayout = GObject.registerClass(
class SlideLayout extends Clutter.FixedLayout {
var SlideLayout = GObject.registerClass({
Properties: {
'slide-x': GObject.ParamSpec.double(
'slide-x', 'slide-x', 'slide-x',
GObject.ParamFlags.READWRITE,
0, 1, 1),
'translation-x': GObject.ParamSpec.double(
'translation-x', 'translation-x', 'translation-x',
GObject.ParamFlags.READWRITE,
-Infinity, Infinity, 0)
}
}, class SlideLayout extends Clutter.FixedLayout {
_init(params) {
this._slideX = 1;
this._translationX = undefined;
this._translationX = 0;
this._direction = SlideDirection.LEFT;
super._init(params);
@@ -70,12 +79,17 @@ class SlideLayout extends Clutter.FixedLayout {
child.allocate(actorBox, flags);
}
set slideX(value) {
// eslint-disable-next-line camelcase
set slide_x(value) {
if (this._slideX == value)
return;
this._slideX = value;
this.notify('slide-x');
this.layout_changed();
}
get slideX() {
// eslint-disable-next-line camelcase
get slide_x() {
return this._slideX;
}
@@ -88,12 +102,17 @@ class SlideLayout extends Clutter.FixedLayout {
return this._direction;
}
set translationX(value) {
// eslint-disable-next-line camelcase
set translation_x(value) {
if (this._translationX == value)
return;
this._translationX = value;
this.notify('translation-x');
this.layout_changed();
}
get translationX() {
// eslint-disable-next-line camelcase
get translation_x() {
return this._translationX;
}
});
@@ -127,9 +146,10 @@ var SlidingControl = class {
}
_updateSlide() {
Tweener.addTween(this.layout, { slideX: this._getSlide(),
time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' });
this.actor.ease_property('@layout.slide-x', this._getSlide(), {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SIDE_CONTROLS_ANIMATION_TIME,
});
}
getVisibleWidth() {
@@ -161,13 +181,14 @@ var SlidingControl = class {
translationEnd = translation;
}
if (this.layout.translationX == translationEnd)
if (this.layout.translation_x == translationEnd)
return;
this.layout.translationX = translationStart;
Tweener.addTween(this.layout, { translationX: translationEnd,
time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' });
this.layout.translation_x = translationStart;
this.actor.ease_property('@layout.translation-x', translationEnd, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SIDE_CONTROLS_ANIMATION_TIME,
});
}
_onOverviewHiding() {
@@ -196,28 +217,30 @@ var SlidingControl = class {
}
fadeIn() {
Tweener.addTween(this.actor, { opacity: 255,
time: SIDE_CONTROLS_ANIMATION_TIME / 2,
transition: 'easeInQuad'
});
this.actor.ease({
opacity: 255,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
}
fadeHalf() {
Tweener.addTween(this.actor, { opacity: 128,
time: SIDE_CONTROLS_ANIMATION_TIME / 2,
transition: 'easeOutQuad'
});
this.actor.ease({
opacity: 128,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
slideIn() {
this._visible = true;
// we will update slideX and the translation from pageEmpty
// we will update slide_x and the translation from pageEmpty
}
slideOut() {
this._visible = false;
this._updateTranslation();
// we will update slideX from pageEmpty
// we will update slide_x from pageEmpty
}
pageEmpty() {
@@ -225,7 +248,8 @@ var SlidingControl = class {
// selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called,
// changing the visiblity
this.layout.slideX = this._getSlide();
this.actor.remove_transition('@layout.slide-x');
this.layout.slide_x = this._getSlide();
this._updateTranslation();
}
};
@@ -424,17 +448,6 @@ var ControlsManager = class {
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
Main.overview.connect('showing', this._updateSpacerVisibility.bind(this));
Main.overview.connect('item-drag-begin', () => {
let activePage = this.viewSelector.getActivePage();
if (activePage != ViewSelector.ViewPage.WINDOWS)
this.viewSelector.fadeHalf();
});
Main.overview.connect('item-drag-end', () => {
this.viewSelector.fadeIn();
});
Main.overview.connect('item-drag-cancelled', () => {
this.viewSelector.fadeIn();
});
}
_updateWorkspacesGeometry() {

View File

@@ -1,22 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PageIndicators, AnimatedPageIndicators */
const { Clutter, GObject, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Tweener = imports.ui.tweener;
const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
var INDICATORS_BASE_TIME = 0.25;
var INDICATORS_BASE_TIME_OUT = 0.125;
var INDICATORS_ANIMATION_DELAY = 0.125;
var INDICATORS_ANIMATION_DELAY_OUT = 0.0625;
var INDICATORS_ANIMATION_MAX_TIME = 0.75;
var SWITCH_TIME = 0.4;
var INDICATORS_BASE_TIME = 250;
var INDICATORS_BASE_TIME_OUT = 125;
var INDICATORS_ANIMATION_DELAY = 125;
var INDICATORS_ANIMATION_DELAY_OUT = 62.5;
var INDICATORS_ANIMATION_MAX_TIME = 750;
var SWITCH_TIME = 400;
var INDICATORS_ANIMATION_MAX_TIME_OUT =
Math.min (SWITCH_TIME,
ANIMATION_TIME_OUT + ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
var ANIMATION_DELAY = 0.1;
var ANIMATION_DELAY = 100;
var PageIndicators = GObject.registerClass({
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
@@ -97,7 +96,15 @@ class AnimatedPageIndicators extends PageIndicators {
super._init(true);
this.connect('notify::mapped', () => {
this.animateIndicators(AnimationDirection.IN);
if (!this.mapped)
return;
// Implicit animations are skipped for unmapped actors, and our
// children aren't mapped yet, so defer to a later handler
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.animateIndicators(AnimationDirection.IN);
return GLib.SOURCE_REMOVE;
});
});
}
@@ -110,7 +117,7 @@ class AnimatedPageIndicators extends PageIndicators {
return;
for (let i = 0; i < this._nPages; i++)
Tweener.removeTweens(children[i]);
children[i].remove_all_transitions();
let offset;
if (this.get_text_direction() == Clutter.TextDirection.RTL)
@@ -130,10 +137,10 @@ class AnimatedPageIndicators extends PageIndicators {
for (let i = 0; i < this._nPages; i++) {
children[i].translation_x = isAnimationIn ? offset : 0;
Tweener.addTween(children[i], {
children[i].ease({
translation_x: isAnimationIn ? 0 : offset,
time: baseTime + delay * i,
transition: 'easeInOutQuad',
duration: baseTime + delay * i,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay: isAnimationIn ? ANIMATION_DELAY : 0
});
}

View File

@@ -3,7 +3,6 @@
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
const Mainloop = imports.mainloop;
const Animation = imports.ui.animation;
const Config = imports.misc.config;
@@ -13,7 +12,6 @@ const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var PANEL_ICON_SIZE = 16;
var APP_MENU_ICON_MARGIN = 0;
@@ -262,11 +260,12 @@ var AppMenuButton = GObject.registerClass({
this._visible = true;
this.reactive = true;
this.show();
Tweener.removeTweens(this);
Tweener.addTween(this,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' });
this.remove_all_transitions();
this.ease({
opacity: 255,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
fadeOut() {
@@ -275,14 +274,13 @@ var AppMenuButton = GObject.registerClass({
this._visible = false;
this.reactive = false;
Tweener.removeTweens(this);
Tweener.addTween(this,
{ opacity: 0,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.hide();
} });
this.remove_all_transitions();
this.ease({
opacity: 0,
mode: Clutter.Animation.EASE_OUT_QUAD,
duration: Overview.ANIMATION_TIME,
onComplete: () => this.hide()
});
}
_syncIcon() {
@@ -452,8 +450,8 @@ class ActivitiesButton extends PanelMenu.Button {
return DND.DragMotionResult.CONTINUE;
if (this._xdndTimeOut != 0)
Mainloop.source_remove(this._xdndTimeOut);
this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT, () => {
GLib.source_remove(this._xdndTimeOut);
this._xdndTimeOut = GLib.timeout_add(GLib.PRIORITY_DEFAULT, BUTTON_DND_ACTIVATION_TIMEOUT, () => {
this._xdndToggleOverview();
});
GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview');
@@ -497,7 +495,7 @@ class ActivitiesButton extends PanelMenu.Button {
if (pickedActor == this && Main.overview.shouldToggleByCornerOrButton())
Main.overview.toggle();
Mainloop.source_remove(this._xdndTimeOut);
GLib.source_remove(this._xdndTimeOut);
this._xdndTimeOut = 0;
return GLib.SOURCE_REMOVE;
}

View File

@@ -1,20 +1,42 @@
/* exported PointerA11yTimeout */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Tweener = imports.ui.tweener;
const { Clutter, GObject, Meta, St } = imports.gi;
const Main = imports.ui.main;
const Cairo = imports.cairo;
var PieTimer = GObject.registerClass(
class PieTimer extends St.DrawingArea {
const SUCCESS_ZOOM_OUT_DURATION = 150;
var PieTimer = GObject.registerClass({
Properties: {
'angle': GObject.ParamSpec.double(
'angle', 'angle', 'angle',
GObject.ParamFlags.READWRITE,
0, 2 * Math.PI, 0)
}
}, class PieTimer extends St.DrawingArea {
_init() {
this._x = 0;
this._y = 0;
this._startTime = 0;
this._duration = 0;
super._init( { style_class: 'pie-timer',
visible: false,
can_focus: false,
reactive: false });
this._angle = 0;
super._init({
style_class: 'pie-timer',
opacity: 0,
visible: false,
can_focus: false,
reactive: false
});
this.set_pivot_point(0.5, 0.5);
}
get angle() {
return this._angle;
}
set angle(angle) {
if (this._angle == angle)
return;
this._angle = angle;
this.notify('angle');
this.queue_repaint();
}
vfunc_repaint() {
@@ -25,20 +47,22 @@ class PieTimer extends St.DrawingArea {
let [width, height] = this.get_surface_size();
let radius = Math.min(width / 2, height / 2);
let currentTime = GLib.get_monotonic_time() / 1000.0;
let ellapsed = currentTime - this._startTime;
let angle = (ellapsed / this._duration) * 2 * Math.PI;
let startAngle = 3 * Math.PI / 2;
let endAngle = startAngle + angle;
let endAngle = startAngle + this._angle;
let cr = this.get_context();
cr.setLineCap(Cairo.LineCap.ROUND);
cr.setLineJoin(Cairo.LineJoin.ROUND);
cr.translate(width / 2, height / 2);
cr.moveTo(0, 0);
if (this._angle < 2 * Math.PI)
cr.moveTo(0, 0);
cr.arc(0, 0, radius - borderWidth, startAngle, endAngle);
cr.lineTo(0, 0);
if (this._angle < 2 * Math.PI)
cr.lineTo(0, 0);
cr.closePath();
cr.setLineWidth(0);
@@ -53,47 +77,56 @@ class PieTimer extends St.DrawingArea {
}
start(x, y, duration) {
Tweener.removeTweens(this);
this.x = x - this.width / 2;
this.y = y - this.height / 2;
this.show();
Main.uiGroup.set_child_above_sibling(this, null);
this._startTime = GLib.get_monotonic_time() / 1000.0;
this._duration = duration;
this.ease({
opacity: 255,
duration: duration / 4,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
Tweener.addTween(this,
{ opacity: 255,
time: duration / 1000,
transition: 'easeOutQuad',
onUpdate: () => this.queue_repaint(),
onComplete: () => this.stop()
});
this.ease_property('angle', 2 * Math.PI, {
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: this._onTransitionComplete.bind(this)
});
}
stop() {
Tweener.removeTweens(this);
this.hide();
_onTransitionComplete() {
this.ease({
scale_x: 2,
scale_y: 2,
opacity: 0,
duration: SUCCESS_ZOOM_OUT_DURATION,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: () => this.destroy()
});
}
});
var PointerA11yTimeout = class PointerA11yTimeout {
constructor() {
let manager = Clutter.DeviceManager.get_default();
let pieTimer = new PieTimer();
Main.uiGroup.add_actor(pieTimer);
manager.connect('ptr-a11y-timeout-started', (manager, device, type, timeout) => {
let [x, y] = global.get_pointer();
pieTimer.start(x, y, timeout);
this._pieTimer = new PieTimer();
Main.uiGroup.add_actor(this._pieTimer);
Main.uiGroup.set_child_above_sibling(this._pieTimer, null);
this._pieTimer.start(x, y, timeout);
if (type == Clutter.PointerA11yTimeoutType.GESTURE)
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
});
manager.connect('ptr-a11y-timeout-stopped', (manager, device, type) => {
pieTimer.stop();
manager.connect('ptr-a11y-timeout-stopped', (manager, device, type, clicked) => {
if (!clicked)
this._pieTimer.destroy();
if (type == Clutter.PointerA11yTimeoutType.GESTURE)
global.display.set_cursor(Meta.Cursor.DEFAULT);
});

View File

@@ -2,7 +2,6 @@
/* exported getPointerWatcher */
const { GLib, Meta } = imports.gi;
const Mainloop = imports.mainloop;
// We stop polling if the user is idle for more than this amount of time
var IDLE_TIME = 1000;
@@ -87,7 +86,7 @@ var PointerWatcher = class {
_updateTimeout() {
if (this._timeoutId) {
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
@@ -98,8 +97,8 @@ var PointerWatcher = class {
for (let i = 1; i < this._watches.length; i++)
minInterval = Math.min(this._watches[i].interval, minInterval);
this._timeoutId = Mainloop.timeout_add(minInterval,
this._onTimeout.bind(this));
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, minInterval,
this._onTimeout.bind(this));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
}

View File

@@ -10,7 +10,6 @@ const BoxPointer = imports.ui.boxpointer;
const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var Ornament = {
NONE: 0,
@@ -58,11 +57,9 @@ var PopupBaseMenuItem = GObject.registerClass({
Properties: {
'active': GObject.ParamSpec.boolean('active', 'active', 'active',
GObject.ParamFlags.READWRITE,
GObject.TYPE_BOOLEAN,
false),
'sensitive': GObject.ParamSpec.boolean('sensitive', 'sensitive', 'sensitive',
GObject.ParamFlags.READWRITE,
GObject.TYPE_BOOLEAN,
true),
},
Signals: {
@@ -70,12 +67,13 @@ var PopupBaseMenuItem = GObject.registerClass({
}
}, class PopupBaseMenuItem extends St.BoxLayout {
_init(params) {
params = Params.parse (params, { reactive: true,
activate: true,
hover: true,
style_class: null,
can_focus: true
});
params = Params.parse (params, {
reactive: true,
activate: true,
hover: true,
style_class: null,
can_focus: true,
});
super._init({ style_class: 'popup-menu-item',
reactive: params.reactive,
track_hover: params.reactive,
@@ -334,9 +332,10 @@ var PopupSwitchMenuItem = GObject.registerClass({
this._statusBin = new St.Bin({ x_align: St.Align.END });
this.add(this._statusBin, { expand: true, x_align: St.Align.END });
this._statusLabel = new St.Label({ text: '',
style_class: 'popup-status-menu-item'
});
this._statusLabel = new St.Label({
text: '',
style_class: 'popup-status-menu-item',
});
this._statusBin.child = this._switch;
}
@@ -1013,18 +1012,17 @@ var PopupSubMenu = class extends PopupMenuBase {
if (animate) {
let [, naturalHeight] = this.actor.get_preferred_height(-1);
this.actor.height = 0;
this.actor._arrowRotation = this._arrow.rotation_angle_z;
Tweener.addTween(this.actor,
{ _arrowRotation: targetAngle,
height: naturalHeight,
time: 0.25,
onUpdate: () => {
this._arrow.rotation_angle_z = this.actor._arrowRotation;
},
onComplete: () => {
this.actor.set_height(-1);
}
});
this.actor.ease({
height: naturalHeight,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO,
onComplete: () => this.actor.set_height(-1)
});
this._arrow.ease({
rotation_angle_z: targetAngle,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO
});
} else {
this._arrow.rotation_angle_z = targetAngle;
}
@@ -1044,19 +1042,20 @@ var PopupSubMenu = class extends PopupMenuBase {
animate = false;
if (animate) {
this.actor._arrowRotation = this._arrow.rotation_angle_z;
Tweener.addTween(this.actor,
{ _arrowRotation: 0,
height: 0,
time: 0.25,
onUpdate: () => {
this._arrow.rotation_angle_z = this.actor._arrowRotation;
},
onComplete: () => {
this.actor.hide();
this.actor.set_height(-1);
},
});
this.actor.ease({
height: 0,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO,
onComplete: () => {
this.actor.hide();
this.actor.set_height(-1);
}
});
this._arrow.ease({
rotation_angle_z: 0,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO
});
} else {
this._arrow.rotation_angle_z = 0;
this.actor.hide();

View File

@@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Ripples */
const { St } = imports.gi;
const Tweener = imports.ui.tweener;
const { Clutter, St } = imports.gi;
// Shamelessly copied from the layout "hotcorner" ripples implementation
var Ripples = class Ripples {
@@ -35,30 +34,41 @@ var Ripples = class Ripples {
this._ripple3.set_pivot_point(px, py);
}
_animRipple(ripple, delay, time, startScale, startOpacity, finalScale) {
destroy() {
this._ripple1.destroy();
this._ripple2.destroy();
this._ripple3.destroy();
}
_animRipple(ripple, delay, duration, startScale, startOpacity, finalScale) {
// We draw a ripple by using a source image and animating it scaling
// outwards and fading away. We want the ripples to move linearly
// or it looks unrealistic, but if the opacity of the ripple goes
// linearly to zero it fades away too quickly, so we use Tweener's
// 'onUpdate' to give a non-linear curve to the fade-away and make
// linearly to zero it fades away too quickly, so we use a separate
// tween to give a non-linear curve to the fade-away and make
// it more visible in the middle section.
ripple.x = this._x;
ripple.y = this._y;
ripple._opacity = startOpacity;
ripple.visible = true;
ripple.opacity = 255 * Math.sqrt(startOpacity);
ripple.scale_x = ripple.scale_y = startScale;
ripple.set_translation( - this._px * ripple.width, - this._py * ripple.height, 0.0);
Tweener.addTween(ripple, { _opacity: 0,
scale_x: finalScale,
scale_y: finalScale,
delay: delay,
time: time,
transition: 'linear',
onUpdate: () => ripple.opacity = 255 * Math.sqrt(ripple._opacity),
onComplete: () => ripple.visible = false });
ripple.ease({
opacity: 0,
delay,
duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
ripple.ease({
scale_x: finalScale,
scale_y: finalScale,
delay,
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => ripple.visible = false
});
}
addTo(stage) {
@@ -86,9 +96,9 @@ var Ripples = class Ripples {
// parameters were found by trial and error, so don't look
// for them to make perfect sense mathematically
// delay time scale opacity => scale
this._animRipple(this._ripple1, 0.0, 0.83, 0.25, 1.0, 1.5);
this._animRipple(this._ripple2, 0.05, 1.0, 0.0, 0.7, 1.25);
this._animRipple(this._ripple3, 0.35, 1.0, 0.0, 0.3, 1);
// delay time scale opacity => scale
this._animRipple(this._ripple1, 0, 830, 0.25, 1.0, 1.5);
this._animRipple(this._ripple2, 50, 1000, 0.0, 0.7, 1.25);
this._animRipple(this._ripple3, 350, 1000, 0.0, 0.3, 1);
}
};

View File

@@ -6,7 +6,6 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
const History = imports.misc.history;
@@ -19,7 +18,7 @@ const TERMINAL_SCHEMA = 'org.gnome.desktop.default-applications.terminal';
const EXEC_KEY = 'exec';
const EXEC_ARG_KEY = 'exec-arg';
var DIALOG_GROW_TIME = 0.1;
var DIALOG_GROW_TIME = 100;
var RunDialog = GObject.registerClass(
class RunDialog extends ModalDialog.ModalDialog {
@@ -95,9 +94,11 @@ class RunDialog extends ModalDialog.ModalDialog {
this._errorBox.hide();
this.setButtons([{ action: this.close.bind(this),
label: _("Close"),
key: Clutter.Escape }]);
this.setButtons([{
action: this.close.bind(this),
label: _("Close"),
key: Clutter.Escape,
}]);
this._pathCompleter = new Gio.FilenameCompleter();
@@ -243,15 +244,16 @@ class RunDialog extends ModalDialog.ModalDialog {
let [, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1);
let parentActor = this._errorBox.get_parent();
Tweener.addTween(parentActor,
{ height: parentActor.height + errorBoxNaturalHeight,
time: DIALOG_GROW_TIME,
transition: 'easeOutQuad',
onComplete: () => {
parentActor.set_height(-1);
this._errorBox.show();
}
});
let height = parentActor.height + errorBoxNaturalHeight;
parentActor.ease({
height,
duration: DIALOG_GROW_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
parentActor.set_height(-1);
this._errorBox.show();
}
});
}
}

View File

@@ -3,9 +3,7 @@
const { AccountsService, Clutter, Cogl, Gio, GLib,
GnomeDesktop, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const TweenerEquations = imports.tweener.equations;
const Background = imports.ui.background;
const GnomeSession = imports.misc.gnomeSession;
@@ -18,7 +16,6 @@ const Overview = imports.ui.overview;
const MessageTray = imports.ui.messageTray;
const ShellDBus = imports.ui.shellDBus;
const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
@@ -34,7 +31,7 @@ var ARROW_DRAG_THRESHOLD = 0.1;
// Parameters for the arrow animation
var N_ARROWS = 3;
var ARROW_ANIMATION_TIME = 0.6;
var ARROW_ANIMATION_TIME = 600;
var ARROW_ANIMATION_PEAK_OPACITY = 0.4;
var ARROW_IDLE_TIME = 30000; // ms
@@ -45,9 +42,9 @@ var SUMMARY_ICON_SIZE = 48;
// - MANUAL_FADE_TIME is used for lowering the shield when asked by the user,
// or when cancelling the dialog
// - CURTAIN_SLIDE_TIME is used when raising the shield before unlocking
var STANDARD_FADE_TIME = 10;
var MANUAL_FADE_TIME = 0.3;
var CURTAIN_SLIDE_TIME = 0.3;
var STANDARD_FADE_TIME = 10000;
var MANUAL_FADE_TIME = 300;
var CURTAIN_SLIDE_TIME = 300;
var Clock = class {
constructor() {
@@ -251,15 +248,15 @@ var NotificationsBox = class {
let widget = obj.sourceBox;
let [, natHeight] = widget.get_preferred_height(-1);
widget.height = 0;
Tweener.addTween(widget,
{ height: natHeight,
transition: 'easeOutQuad',
time: 0.25,
onComplete: () => {
this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
widget.set_height(-1);
}
});
widget.ease({
height: natHeight,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: 250,
onComplete: () => {
this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
widget.set_height(-1);
}
});
this._updateVisibility();
if (obj.sourceBox.visible)
@@ -432,13 +429,14 @@ var ScreenShield = class {
this.actor = Main.layoutManager.screenShieldGroup;
this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup = new St.Widget({ x_expand: true,
y_expand: true,
reactive: true,
can_focus: true,
name: 'lockScreenGroup',
visible: false,
});
this._lockScreenGroup = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
can_focus: true,
name: 'lockScreenGroup',
visible: false,
});
this._lockScreenGroup.connect('key-press-event',
this._onLockScreenKeyPress.bind(this));
this._lockScreenGroup.connect('scroll-event',
@@ -735,24 +733,26 @@ var ScreenShield = class {
let maxOpacity = 255 * ARROW_ANIMATION_PEAK_OPACITY;
for (let i = 0; i < arrows.length; i++) {
arrows[i].opacity = 0;
Tweener.addTween(arrows[i],
{ opacity: 0,
delay: unitaryDelay * (N_ARROWS - (i + 1)),
time: ARROW_ANIMATION_TIME,
transition(t, b, c, d) {
if (t < d / 2)
return TweenerEquations.easeOutQuad(t, 0, maxOpacity, d / 2);
else
return TweenerEquations.easeInQuad(t - d / 2, maxOpacity, -maxOpacity, d / 2);
}
});
arrows[i].ease({
opacity: maxOpacity,
delay: unitaryDelay * (N_ARROWS - (i + 1)),
duration: ARROW_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
arrows[i].ease({
opacity: 0,
duration: ARROW_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
}
});
}
return GLib.SOURCE_CONTINUE;
}
_onDragBegin() {
Tweener.removeTweens(this._lockScreenGroup);
this._lockScreenGroup.remove_all_transitions();
this._lockScreenState = MessageTray.State.HIDING;
if (this._isLocked)
@@ -784,17 +784,17 @@ var ScreenShield = class {
// restore the lock screen to its original place
// try to use the same speed as the normal animation
let h = global.stage.height;
let time = MANUAL_FADE_TIME * (-this._lockScreenGroup.y) / h;
Tweener.removeTweens(this._lockScreenGroup);
Tweener.addTween(this._lockScreenGroup,
{ y: 0,
time: time,
transition: 'easeInQuad',
onComplete: () => {
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenState = MessageTray.State.SHOWN;
}
});
let duration = MANUAL_FADE_TIME * (-this._lockScreenGroup.y) / h;
this._lockScreenGroup.remove_all_transitions();
this._lockScreenGroup.ease({
y: 0,
duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenState = MessageTray.State.SHOWN;
}
});
this._maybeCancelDialog();
}
@@ -830,13 +830,17 @@ var ScreenShield = class {
let shouldLock = this._settings.get_boolean(LOCK_ENABLED_KEY) && !this._isLocked;
if (shouldLock) {
let lockTimeout = Math.max(STANDARD_FADE_TIME, this._settings.get_uint(LOCK_DELAY_KEY));
this._lockTimeoutId = Mainloop.timeout_add(lockTimeout * 1000,
() => {
this._lockTimeoutId = 0;
this.lock(false);
return GLib.SOURCE_REMOVE;
});
let lockTimeout = Math.max(
STANDARD_FADE_TIME,
this._settings.get_uint(LOCK_DELAY_KEY) * 1000);
this._lockTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
lockTimeout,
() => {
this._lockTimeoutId = 0;
this.lock(false);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._lockTimeoutId, '[gnome-shell] this.lock');
}
@@ -922,7 +926,7 @@ var ScreenShield = class {
this._lockScreenState = MessageTray.State.HIDING;
Tweener.removeTweens(this._lockScreenGroup);
this._lockScreenGroup.remove_all_transitions();
if (animate) {
// Tween the lock screen out of screen
@@ -931,17 +935,17 @@ var ScreenShield = class {
// if velocity is specified, it's in pixels per milliseconds
let h = global.stage.height;
let delta = (h + this._lockScreenGroup.y);
let minVelocity = global.stage.height / (CURTAIN_SLIDE_TIME * 1000);
let minVelocity = global.stage.height / CURTAIN_SLIDE_TIME;
velocity = Math.max(minVelocity, velocity);
let time = (delta / velocity) / 1000;
let duration = delta / velocity;
Tweener.addTween(this._lockScreenGroup,
{ y: -h,
time: time,
transition: 'easeInQuad',
onComplete: this._hideLockScreenComplete.bind(this),
});
this._lockScreenGroup.ease({
y: -h,
duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => this._hideLockScreenComplete()
});
} else {
this._hideLockScreenComplete();
}
@@ -1001,16 +1005,15 @@ var ScreenShield = class {
if (params.animateLockScreen) {
this._lockScreenGroup.y = -global.screen_height;
Tweener.removeTweens(this._lockScreenGroup);
Tweener.addTween(this._lockScreenGroup,
{ y: 0,
time: MANUAL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._lockScreenShown({ fadeToBlack: fadeToBlack,
animateFade: true });
}
});
this._lockScreenGroup.remove_all_transitions();
this._lockScreenGroup.ease({
y: 0,
duration: MANUAL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._lockScreenShown({ fadeToBlack, animateFade: true });
}
});
} else {
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenShown({ fadeToBlack: fadeToBlack,
@@ -1027,7 +1030,7 @@ var ScreenShield = class {
this._arrowActiveWatchId = 0;
if (!this._arrowAnimationId) {
this._arrowAnimationId = Mainloop.timeout_add(6000, this._animateArrows.bind(this));
this._arrowAnimationId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 6000, this._animateArrows.bind(this));
GLib.Source.set_name_by_id(this._arrowAnimationId, '[gnome-shell] this._animateArrows');
this._animateArrows();
}
@@ -1039,7 +1042,7 @@ var ScreenShield = class {
_pauseArrowAnimation() {
if (this._arrowAnimationId) {
Mainloop.source_remove(this._arrowAnimationId);
GLib.source_remove(this._arrowAnimationId);
this._arrowAnimationId = 0;
}
@@ -1049,7 +1052,7 @@ var ScreenShield = class {
_stopArrowAnimation() {
if (this._arrowAnimationId) {
Mainloop.source_remove(this._arrowAnimationId);
GLib.source_remove(this._arrowAnimationId);
this._arrowAnimationId = 0;
}
if (this._arrowActiveWatchId) {
@@ -1096,7 +1099,7 @@ var ScreenShield = class {
if (params.fadeToBlack && params.animateFade) {
// Take a beat
let id = Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, () => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MANUAL_FADE_TIME, () => {
this._activateFade(this._shortLightbox, MANUAL_FADE_TIME);
return GLib.SOURCE_REMOVE;
});
@@ -1214,13 +1217,12 @@ var ScreenShield = class {
this._isModal = false;
}
Tweener.addTween(this._lockDialogGroup, {
this._lockDialogGroup.ease({
scale_x: 0,
scale_y: 0,
time: animate ? Overview.ANIMATION_TIME : 0,
transition: 'easeOutQuad',
onComplete: this._completeDeactivate.bind(this),
onCompleteScope: this
duration: animate ? Overview.ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._completeDeactivate()
});
}
@@ -1240,7 +1242,7 @@ var ScreenShield = class {
}
if (this._lockTimeoutId != 0) {
Mainloop.source_remove(this._lockTimeoutId);
GLib.source_remove(this._lockTimeoutId);
this._lockTimeoutId = 0;
}

View File

@@ -7,7 +7,6 @@ const Signals = imports.signals;
const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -272,7 +271,7 @@ var SelectArea = class {
}
_onMotionEvent(actor, event) {
if (this._startX == -1 || this._startY == -1)
if (this._startX == -1 || this._startY == -1 || this._result)
return Clutter.EVENT_PROPAGATE;
[this._lastX, this._lastY] = event.get_coords();
@@ -298,14 +297,12 @@ var SelectArea = class {
_onButtonRelease() {
this._result = this._getGeometry();
Tweener.addTween(this._group,
{ opacity: 0,
time: 0.2,
transition: 'easeOutQuad',
onComplete: () => {
this._grabHelper.ungrab();
}
});
this._group.ease({
opacity: 0,
duration: 200,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._grabHelper.ungrab()
});
return Clutter.EVENT_PROPAGATE;
}
@@ -367,7 +364,7 @@ var PickPixel = class {
};
Signals.addSignalMethods(PickPixel.prototype);
var FLASHSPOT_ANIMATION_OUT_TIME = 0.5; // seconds
var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds
var Flashspot = class extends Lightbox.Lightbox {
constructor(area) {
@@ -382,15 +379,15 @@ var Flashspot = class extends Lightbox.Lightbox {
fire(doneCallback) {
this.actor.show();
this.actor.opacity = 255;
Tweener.addTween(this.actor,
{ opacity: 0,
time: FLASHSPOT_ANIMATION_OUT_TIME,
transition: 'easeOutQuad',
onComplete: () => {
if (doneCallback)
doneCallback();
this.destroy();
}
});
this.actor.ease({
opacity: 0,
duration: FLASHSPOT_ANIMATION_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
if (doneCallback)
doneCallback();
this.destroy();
}
});
}
};

View File

@@ -4,7 +4,6 @@
collectStatistics, runPerfScript */
const { Gio, GLib, Meta, Shell } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Params = imports.misc.params;
@@ -41,7 +40,7 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
*/
function sleep(milliseconds) {
return new Promise(resolve => {
let id = Mainloop.timeout_add(milliseconds, () => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, milliseconds, () => {
resolve();
return GLib.SOURCE_REMOVE;
});

View File

@@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
@@ -158,10 +158,15 @@ var SearchResultsBase = class {
this._clipboard = St.Clipboard.get_default();
this._cancellable = new Gio.Cancellable();
this.actor.connect('destroy', this._onDestroy.bind(this));
}
destroy() {
this.actor.destroy();
}
_onDestroy() {
this._terms = [];
}
@@ -245,7 +250,9 @@ var SearchResultsBase = class {
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
let results = this.provider.filterResults(providerResults, maxResults);
let results = maxResults > -1
? this.provider.filterResults(providerResults, maxResults)
: providerResults;
let moreCount = Math.max(providerResults.length - results.length, 0);
this._ensureResultActors(results, successful => {
@@ -339,22 +346,44 @@ var GridSearchResults = class extends SearchResultsBase {
this._resultDisplayBin.set_child(this._bin);
}
_onDestroy() {
if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater;
}
super._onDestroy();
}
updateSearch(...args) {
if (this._notifyAllocationId)
this.actor.disconnect(this._notifyAllocationId);
if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater;
}
// Make sure the maximum number of results calculated by
// _getMaxDisplayedResults() is updated after width changes.
this._notifyAllocationId = this.actor.connect('notify::allocation', () => {
super.updateSearch(...args);
if (this._updateSearchLater)
return;
this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
delete this._updateSearchLater;
super.updateSearch(...args);
return GLib.SOURCE_REMOVE;
});
});
super.updateSearch(...args);
}
_getMaxDisplayedResults() {
let allocation = this.actor.allocation;
let nCols = this._grid.columnsForWidth(allocation.x2 - allocation.x1);
let width = this.actor.allocation.x2 - this.actor.allocation.x1;
if (width == 0)
return -1;
let nCols = this._grid.columnsForWidth(width);
return nCols * this._grid.getRowLimit();
}

View File

@@ -2,7 +2,6 @@
/* exported SessionMode, listModes */
const GLib = imports.gi.GLib;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const FileUtils = imports.misc.fileUtils;
@@ -112,7 +111,7 @@ function _loadMode(file, info) {
let suffix = name.indexOf('.json');
let modeName = suffix == -1 ? name : name.slice(name, suffix);
if (_modes.hasOwnProperty(modeName))
if (Object.prototype.hasOwnProperty.call(_modes, modeName))
return;
let fileContent, success_, newMode;
@@ -141,15 +140,16 @@ function _loadModes() {
function listModes() {
_loadModes();
let id = Mainloop.idle_add(() => {
let loop = new GLib.MainLoop(null, false);
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
let names = Object.getOwnPropertyNames(_modes);
for (let i = 0; i < names.length; i++)
if (_modes[names[i]].isPrimary)
print(names[i]);
Mainloop.quit('listModes');
loop.quit();
});
GLib.Source.set_name_by_id(id, '[gnome-shell] listModes');
Mainloop.run('listModes');
loop.run();
}
var SessionMode = class {

View File

@@ -26,9 +26,10 @@ function _setButtonsForChoices(dialog, choices) {
for (let idx = 0; idx < choices.length; idx++) {
let button = idx;
buttons.unshift({ label: choices[idx],
action: () => dialog.emit('response', button)
});
buttons.unshift({
label: choices[idx],
action: () => dialog.emit('response', button),
});
}
dialog.setButtons(buttons);
@@ -387,24 +388,26 @@ var ShellMountPasswordDialog = GObject.registerClass({
this._rememberChoice = null;
}
this._defaultButtons = [{ label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape
},
{ label: _("Unlock"),
action: this._onUnlockButton.bind(this),
default: true
}];
this._defaultButtons = [{
label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape,
}, {
label: _("Unlock"),
action: this._onUnlockButton.bind(this),
default: true,
}];
this._usesKeyfilesButtons = [{ label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape
},
{ /* Translators: %s is the Disks application */
label: _("Open %s").format(disksApp.get_name()),
action: this._onOpenDisksButton.bind(this),
default: true
}];
this._usesKeyfilesButtons = [{
label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape,
}, {
/* Translators: %s is the Disks application */
label: _("Open %s").format(disksApp.get_name()),
action: this._onOpenDisksButton.bind(this),
default: true,
}];
this.setButtons(this._defaultButtons);
}

View File

@@ -1,27 +1,31 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported Slider */
const { Atk, Clutter } = imports.gi;
const Signals = imports.signals;
const { Atk, Clutter, GObject } = imports.gi;
const BarLevel = imports.ui.barLevel;
var SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */
var Slider = class extends BarLevel.BarLevel {
constructor(value) {
let params = {
styleClass: 'slider',
canFocus: true,
var Slider = GObject.registerClass({
Signals: {
'drag-begin': {},
'drag-end': {}
}
}, class Slider extends BarLevel.BarLevel {
_init(value) {
super._init({
value,
style_class: 'slider',
can_focus: true,
reactive: true,
accessibleRole: Atk.Role.SLIDER,
};
super(value, params);
accessible_role: Atk.Role.SLIDER
});
this.actor.connect('button-press-event', this._startDragging.bind(this));
this.actor.connect('touch-event', this._touchDragging.bind(this));
this.actor.connect('scroll-event', this._onScrollEvent.bind(this));
this.actor.connect('key-press-event', this.onKeyPressEvent.bind(this));
this.connect('button-press-event', this._startDragging.bind(this));
this.connect('touch-event', this._touchDragging.bind(this));
this.connect('scroll-event', this._onScrollEvent.bind(this));
this.connect('key-press-event', this.onKeyPressEvent.bind(this));
this._releaseId = this._motionId = 0;
this._dragging = false;
@@ -29,13 +33,13 @@ var Slider = class extends BarLevel.BarLevel {
this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this));
}
_barLevelRepaint(area) {
super._barLevelRepaint(area);
vfunc_repaint() {
super.vfunc_repaint();
// Add handle
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let cr = this.get_context();
let themeNode = this.get_theme_node();
let [width, height] = this.get_surface_size();
let handleRadius = themeNode.get_length('-slider-handle-radius');
@@ -72,20 +76,20 @@ var Slider = class extends BarLevel.BarLevel {
let sequence = event.get_event_sequence();
if (sequence != null)
device.sequence_grab(sequence, this.actor);
device.sequence_grab(sequence, this);
else
device.grab(this.actor);
device.grab(this);
this._grabbedDevice = device;
this._grabbedSequence = sequence;
if (sequence == null) {
this._releaseId = this.actor.connect('button-release-event', this._endDragging.bind(this));
this._motionId = this.actor.connect('motion-event', this._motionEvent.bind(this));
this._releaseId = this.connect('button-release-event', this._endDragging.bind(this));
this._motionId = this.connect('motion-event', this._motionEvent.bind(this));
}
// We need to emit 'drag-begin' before moving the handle to make
// sure that no 'value-changed' signal is emitted before this one.
// sure that no 'notify::value' signal is emitted before this one.
this.emit('drag-begin');
let absX, absY;
@@ -97,9 +101,9 @@ var Slider = class extends BarLevel.BarLevel {
_endDragging() {
if (this._dragging) {
if (this._releaseId)
this.actor.disconnect(this._releaseId);
this.disconnect(this._releaseId);
if (this._motionId)
this.actor.disconnect(this._motionId);
this.disconnect(this._motionId);
if (this._grabbedSequence != null)
this._grabbedDevice.sequence_ungrab(this._grabbedSequence);
@@ -151,10 +155,8 @@ var Slider = class extends BarLevel.BarLevel {
delta = -dy * SLIDER_SCROLL_STEP;
}
this._value = Math.min(Math.max(0, this._value + delta), this._maxValue);
this.value = Math.min(Math.max(0, this._value + delta), this._maxValue);
this.actor.queue_repaint();
this.emit('value-changed', this._value);
return Clutter.EVENT_STOP;
}
@@ -173,10 +175,8 @@ var Slider = class extends BarLevel.BarLevel {
let key = event.get_key_symbol();
if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
this._value = Math.max(0, Math.min(this._value + delta, this._maxValue));
this.actor.queue_repaint();
this.emit('drag-begin');
this.emit('value-changed', this._value);
this.value = Math.max(0, Math.min(this._value + delta, this._maxValue));
this.emit('drag-end');
return Clutter.EVENT_STOP;
}
@@ -185,11 +185,11 @@ var Slider = class extends BarLevel.BarLevel {
_moveHandle(absX, _absY) {
let relX, sliderX;
[sliderX] = this.actor.get_transformed_position();
[sliderX] = this.get_transformed_position();
relX = absX - sliderX;
let width = this._barLevelWidth;
let handleRadius = this.actor.get_theme_node().get_length('-slider-handle-radius');
let handleRadius = this.get_theme_node().get_length('-slider-handle-radius');
let newvalue;
if (relX < handleRadius)
@@ -198,13 +198,10 @@ var Slider = class extends BarLevel.BarLevel {
newvalue = 1;
else
newvalue = (relX - handleRadius) / (width - 2 * handleRadius);
this._value = newvalue * this._maxValue;
this.actor.queue_repaint();
this.emit('value-changed', this._value);
this.value = newvalue * this._maxValue;
}
_getMinimumIncrement() {
return 0.1;
}
};
Signals.addSignalMethods(Slider.prototype);
});

View File

@@ -2,7 +2,6 @@
/* exported ATIndicator */
const { Gio, GLib, GObject, St } = imports.gi;
const Mainloop = imports.mainloop;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@@ -96,7 +95,7 @@ class ATIndicator extends PanelMenu.Button {
if (this._syncMenuVisibilityIdle)
return;
this._syncMenuVisibilityIdle = Mainloop.idle_add(this._syncMenuVisibility.bind(this));
this._syncMenuVisibilityIdle = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._syncMenuVisibility.bind(this));
GLib.Source.set_name_by_id(this._syncMenuVisibilityIdle, '[gnome-shell] this._syncMenuVisibility');
}

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const { Gio, St } = imports.gi;
const { Gio, GObject, St } = imports.gi;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@@ -33,13 +33,14 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this.menu.addMenuItem(this._item);
this._slider = new Slider.Slider(0);
this._slider.connect('value-changed', this._sliderChanged.bind(this));
this._slider.actor.accessible_name = _("Brightness");
this._sliderChangedId = this._slider.connect('notify::value',
this._sliderChanged.bind(this));
this._slider.accessible_name = _("Brightness");
let icon = new St.Icon({ icon_name: 'display-brightness-symbolic',
style_class: 'popup-menu-icon' });
this._item.add(icon);
this._item.add(this._slider.actor, { expand: true });
this._item.add(this._slider, { expand: true });
this._item.connect('button-press-event', (actor, event) => {
return this._slider.startDragging(event);
});
@@ -49,15 +50,21 @@ var Indicator = class extends PanelMenu.SystemIndicator {
}
_sliderChanged(slider, value) {
let percent = value * 100;
_sliderChanged() {
let percent = this._slider.value * 100;
this._proxy.Brightness = percent;
}
_changeSlider(value) {
GObject.signal_handler_block(this._slider, this._sliderChangedId);
this._slider.value = value;
GObject.signal_handler_unblock(this._slider, this._sliderChangedId);
}
_sync() {
let visible = this._proxy.Brightness >= 0;
this._item.visible = visible;
if (visible)
this._slider.value = this._proxy.Brightness / 100.0;
this._changeSlider(this._proxy.Brightness / 100.0);
}
};

View File

@@ -13,8 +13,8 @@ const PanelMenu = imports.ui.panelMenu;
const SwitcherPopup = imports.ui.switcherPopup;
const Util = imports.misc.util;
const INPUT_SOURCE_TYPE_XKB = 'xkb';
const INPUT_SOURCE_TYPE_IBUS = 'ibus';
var INPUT_SOURCE_TYPE_XKB = 'xkb';
var INPUT_SOURCE_TYPE_IBUS = 'ibus';
var LayoutMenuItem = GObject.registerClass(
class LayoutMenuItem extends PopupMenu.PopupBaseMenuItem {

View File

@@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NMApplet */
const { Clutter, Gio, GLib, GObject, NM, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Animation = imports.ui.animation;
@@ -719,7 +718,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._updateSensitivity();
this._syncView();
this._scanTimeoutId = Mainloop.timeout_add_seconds(15, this._onScanTimeout.bind(this));
this._scanTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 15, this._onScanTimeout.bind(this));
GLib.Source.set_name_by_id(this._scanTimeoutId, '[gnome-shell] this._onScanTimeout');
this._onScanTimeout();
@@ -757,7 +756,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
}
if (this._scanTimeoutId) {
Mainloop.source_remove(this._scanTimeoutId);
GLib.source_remove(this._scanTimeoutId);
this._scanTimeoutId = 0;
}
}
@@ -874,7 +873,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._airplaneHeadline = new St.Label({ style_class: 'nm-dialog-airplane-headline headline' });
this._airplaneText = new St.Label({ style_class: 'nm-dialog-airplane-text' });
let airplaneSubStack = new St.Widget({ layout_manager: new Clutter.BinLayout });
let airplaneSubStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._airplaneButton = new St.Button({ style_class: 'modal-dialog-button button' });
this._airplaneButton.connect('clicked', () => {
if (this._rfkill.airplaneMode)
@@ -1074,13 +1073,14 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._resortItems();
} else {
network = { ssid: accessPoint.get_ssid(),
mode: accessPoint.mode,
security: this._getApSecurityType(accessPoint),
connections: [],
item: null,
accessPoints: [accessPoint]
};
network = {
ssid: accessPoint.get_ssid(),
mode: accessPoint.mode,
security: this._getApSecurityType(accessPoint),
connections: [],
item: null,
accessPoints: [accessPoint],
};
network.ssidText = ssidToLabel(network.ssid);
this._checkConnections(network, accessPoint);

View File

@@ -110,7 +110,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
// The icons
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
? '-charging' : '';
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
let fillLevel = 10 * Math.ceil(this._proxy.Percentage / 10);
let icon = this._proxy.State == UPower.DeviceState.FULLY_CHARGED
? 'battery-level-100-charged-symbolic'
: `battery-level-${fillLevel}${chargingState}-symbolic`;

View File

@@ -137,15 +137,6 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._sessionUpdated();
}
_updateActionsVisibility() {
let visible = (this._settingsAction.visible ||
this._orientationLockAction.visible ||
this._lockScreenAction.visible ||
this._altSwitcher.actor.visible);
this.buttonGroup.visible = visible;
}
_sessionUpdated() {
this._settingsAction.visible = Main.sessionMode.allowSettings;
}
@@ -253,7 +244,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._orientationLockAction = this._createActionButton('', _("Orientation Lock"));
this._orientationLockAction.connect('clicked', () => {
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE),
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
this._systemActions.activateLockOrientation();
});
item.add(this._orientationLockAction, { expand: true, x_fill: false });
@@ -302,15 +293,18 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this.menu.addMenuItem(item);
let visibilityGroup = [
this._settingsAction,
this._orientationLockAction,
this._lockScreenAction,
this._altSwitcher.actor,
];
this._settingsAction.connect('notify::visible',
() => this._updateActionsVisibility());
this._orientationLockAction.connect('notify::visible',
() => this._updateActionsVisibility());
this._lockScreenAction.connect('notify::visible',
() => this._updateActionsVisibility());
this._altSwitcher.actor.connect('notify::visible',
() => this._updateActionsVisibility());
for (let actor of visibilityGroup) {
actor.connect('notify::visible', () => {
this.buttonGroup.visible = visibilityGroup.some(a => a.visible);
});
}
}
_onSettingsClicked() {

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const { Clutter, Gio, Gvc, St } = imports.gi;
const { Clutter, Gio, GObject, Gvc, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
@@ -36,12 +36,13 @@ var StreamSlider = class {
this._soundSettings.connect(`changed::${ALLOW_AMPLIFIED_VOLUME_KEY}`, this._amplifySettingsChanged.bind(this));
this._amplifySettingsChanged();
this._slider.connect('value-changed', this._sliderChanged.bind(this));
this._sliderChangedId = this._slider.connect('notify::value',
this._sliderChanged.bind(this));
this._slider.connect('drag-end', this._notifyVolumeChange.bind(this));
this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
this.item.add(this._icon);
this.item.add(this._slider.actor, { expand: true });
this.item.add(this._slider, { expand: true });
this.item.connect('button-press-event', (actor, event) => {
return this._slider.startDragging(event);
});
@@ -99,10 +100,11 @@ var StreamSlider = class {
return this._slider.scroll(event);
}
_sliderChanged(slider, value) {
_sliderChanged() {
if (!this._stream)
return;
let value = this._slider.value;
let volume = value * this._control.get_vol_max_norm();
let prevMuted = this._stream.is_muted;
if (volume < 1) {
@@ -128,17 +130,23 @@ var StreamSlider = class {
this._volumeCancellable);
}
_changeSlider(value) {
GObject.signal_handler_block(this._slider, this._sliderChangedId);
this._slider.value = value;
GObject.signal_handler_unblock(this._slider, this._sliderChangedId);
}
_updateVolume() {
let muted = this._stream.is_muted;
this._slider.value = muted
? 0 : (this._stream.volume / this._control.get_vol_max_norm());
this._changeSlider(muted
? 0 : (this._stream.volume / this._control.get_vol_max_norm()));
this.emit('stream-updated');
}
_amplifySettingsChanged() {
this._allowAmplified = this._soundSettings.get_boolean(ALLOW_AMPLIFIED_VOLUME_KEY);
this._slider.maximum_level = this._allowAmplified
this._slider.maximum_value = this._allowAmplified
? this.getMaxLevel() : 1;
if (this._stream)
@@ -189,7 +197,7 @@ Signals.addSignalMethods(StreamSlider.prototype);
var OutputStreamSlider = class extends StreamSlider {
constructor(control) {
super(control);
this._slider.actor.accessible_name = _("Volume");
this._slider.accessible_name = _("Volume");
}
_connectStream(stream) {
@@ -237,7 +245,7 @@ var OutputStreamSlider = class extends StreamSlider {
var InputStreamSlider = class extends StreamSlider {
constructor(control) {
super(control);
this._slider.actor.accessible_name = _("Microphone");
this._slider.accessible_name = _("Microphone");
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';

View File

@@ -2,15 +2,13 @@
/* exported SwitcherPopup, SwitcherList */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var POPUP_DELAY_TIMEOUT = 150; // milliseconds
var POPUP_SCROLL_TIME = 0.10; // seconds
var POPUP_FADE_OUT_TIME = 0.1; // seconds
var POPUP_SCROLL_TIME = 100; // milliseconds
var POPUP_FADE_OUT_TIME = 100; // milliseconds
var DISABLE_HOVER_TIMEOUT = 500; // milliseconds
var NO_MODS_TIMEOUT = 1500; // milliseconds
@@ -143,13 +141,15 @@ var SwitcherPopup = GObject.registerClass({
// We delay showing the popup so that fast Alt+Tab users aren't
// disturbed by the popup briefly flashing.
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
() => {
Main.osdWindowManager.hideAll();
this.opacity = 255;
this._initialDelayTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
this._initialDelayTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
POPUP_DELAY_TIMEOUT,
() => {
Main.osdWindowManager.hideAll();
this.opacity = 255;
this._initialDelayTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._initialDelayTimeoutId, '[gnome-shell] Main.osdWindow.cancel');
return true;
}
@@ -250,9 +250,9 @@ var SwitcherPopup = GObject.registerClass({
this.mouseActive = false;
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
GLib.source_remove(this._motionTimeoutId);
this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, this._mouseTimedOut.bind(this));
this._motionTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, DISABLE_HOVER_TIMEOUT, this._mouseTimedOut.bind(this));
GLib.Source.set_name_by_id(this._motionTimeoutId, '[gnome-shell] this._mouseTimedOut');
}
@@ -264,14 +264,16 @@ var SwitcherPopup = GObject.registerClass({
_resetNoModsTimeout() {
if (this._noModsTimeoutId != 0)
Mainloop.source_remove(this._noModsTimeoutId);
GLib.source_remove(this._noModsTimeoutId);
this._noModsTimeoutId = Mainloop.timeout_add(NO_MODS_TIMEOUT,
() => {
this._finish(global.get_current_time());
this._noModsTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
this._noModsTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
NO_MODS_TIMEOUT,
() => {
this._finish(global.get_current_time());
this._noModsTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
}
_popModal() {
@@ -283,15 +285,13 @@ var SwitcherPopup = GObject.registerClass({
fadeAndDestroy() {
this._popModal();
if (this.visible) {
Tweener.addTween(this,
{ opacity: 0,
time: POPUP_FADE_OUT_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.destroy();
}
});
if (this.opacity > 0) {
this.ease({
opacity: 0,
duration: POPUP_FADE_OUT_TIME,
mode: Clutter.Animation.EASE_OUT_QUAD,
onComplete: () => this.destroy()
});
} else {
this.destroy();
}
@@ -305,11 +305,11 @@ var SwitcherPopup = GObject.registerClass({
this._popModal();
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
GLib.source_remove(this._motionTimeoutId);
if (this._initialDelayTimeoutId != 0)
Mainloop.source_remove(this._initialDelayTimeoutId);
GLib.source_remove(this._initialDelayTimeoutId);
if (this._noModsTimeoutId != 0)
Mainloop.source_remove(this._noModsTimeoutId);
GLib.source_remove(this._noModsTimeoutId);
}
_select(num) {
@@ -461,16 +461,15 @@ var SwitcherList = GObject.registerClass({
value = Math.max(upper, item.allocation.x2 - pageSize);
this._scrollableRight = true;
Tweener.addTween(adjustment,
{ value: value,
time: POPUP_SCROLL_TIME,
transition: 'easeOutQuad',
onComplete: () => {
if (this._highlighted == 0)
this._scrollableLeft = false;
this.queue_relayout();
}
});
adjustment.ease(value, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: POPUP_SCROLL_TIME,
onComplete: () => {
if (this._highlighted == 0)
this._scrollableLeft = false;
this.queue_relayout();
}
});
}
_scrollToRight() {
@@ -485,16 +484,15 @@ var SwitcherList = GObject.registerClass({
value = Math.min(upper, item.allocation.x2 - pageSize);
this._scrollableLeft = true;
Tweener.addTween(adjustment,
{ value: value,
time: POPUP_SCROLL_TIME,
transition: 'easeOutQuad',
onComplete: () => {
if (this._highlighted == this._items.length - 1)
this._scrollableRight = false;
this.queue_relayout();
}
});
adjustment.ease(value, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: POPUP_SCROLL_TIME,
onComplete: () => {
if (this._highlighted == this._items.length - 1)
this._scrollableRight = false;
this.queue_relayout();
}
});
}
_itemActivated(n) {

View File

@@ -3,10 +3,12 @@
pauseTweens, resumeTweens, registerSpecialProperty,
registerSpecialPropertyModifier, registerSpecialPropertySplitter */
const { Clutter, GLib, Shell, St } = imports.gi;
const { Clutter, GLib, Shell } = imports.gi;
const Signals = imports.signals;
const Tweener = imports.tweener.tweener;
const { adjustAnimationTime } = imports.ui.environment;
// This is a wrapper around imports.tweener.tweener that adds a bit of
// Clutter integration. If the tweening target is a Clutter.Actor, then
// the tweenings will automatically be removed if the actor is destroyed.
@@ -50,10 +52,11 @@ function _wrapTweening(target, tweeningParameters) {
}
}
if (!St.Settings.get().enable_animations) {
tweeningParameters['time'] = 0.000001;
tweeningParameters['delay'] = 0.000001;
}
let { time, delay } = tweeningParameters;
if (!isNaN(time))
tweeningParameters['time'] = adjustAnimationTime(1000 * time) / 1000;
if (!isNaN(delay))
tweeningParameters['delay'] = adjustAnimationTime(1000 * delay) / 1000;
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
}
@@ -211,9 +214,6 @@ var ClutterFrameTicker = class {
}
start() {
let settings = St.Settings.get();
if (settings.slow_down_factor > 0)
Tweener.setTimeScale(1 / settings.slow_down_factor);
this._timeline.start();
global.begin_work();
}

View File

@@ -10,7 +10,6 @@ const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const Search = imports.ui.search;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const WorkspacesView = imports.ui.workspacesView;
const EdgeDragAction = imports.ui.edgeDragAction;
const IconGrid = imports.ui.iconGrid;
@@ -310,35 +309,31 @@ var ViewSelector = class {
if (params.a11yFocus)
Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
else
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon,
{ proxy: this.actor,
focusCallback: () => {
this._a11yFocusPage(page);
}
});
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, {
proxy: this.actor,
focusCallback: () => this._a11yFocusPage(page),
});
page.hide();
this.actor.add_actor(page);
return page;
}
_fadePageIn() {
Tweener.addTween(this._activePage,
{ opacity: 255,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad'
});
this._activePage.ease({
opacity: 255,
duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
_fadePageOut(page) {
let oldPage = page;
Tweener.addTween(page,
{ opacity: 0,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._animateIn(oldPage);
}
});
page.ease({
opacity: 0,
duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: () => this._animateIn(oldPage)
});
}
_animateIn(oldPage) {
@@ -602,21 +597,5 @@ var ViewSelector = class {
else
return ViewPage.SEARCH;
}
fadeIn() {
let actor = this._activePage;
Tweener.addTween(actor, { opacity: 255,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 2,
transition: 'easeInQuad'
});
}
fadeHalf() {
let actor = this._activePage;
Tweener.addTween(actor, { opacity: 128,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 2,
transition: 'easeOutQuad'
});
}
};
Signals.addSignalMethods(ViewSelector.prototype);

View File

@@ -2,7 +2,6 @@
/* exported WindowManager */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AltTab = imports.ui.altTab;
@@ -12,25 +11,25 @@ const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const InhibitShortcutsDialog = imports.ui.inhibitShortcutsDialog;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const WindowMenu = imports.ui.windowMenu;
const PadOsd = imports.ui.padOsd;
const EdgeDragAction = imports.ui.edgeDragAction;
const CloseDialog = imports.ui.closeDialog;
const SwitchMonitor = imports.ui.switchMonitor;
const IBusManager = imports.misc.ibusManager;
const { loadInterfaceXML } = imports.misc.fileUtils;
var SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
var MINIMIZE_WINDOW_ANIMATION_TIME = 0.2;
var SHOW_WINDOW_ANIMATION_TIME = 0.15;
var DIALOG_SHOW_WINDOW_ANIMATION_TIME = 0.1;
var DESTROY_WINDOW_ANIMATION_TIME = 0.15;
var DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 0.1;
var WINDOW_ANIMATION_TIME = 0.25;
var MINIMIZE_WINDOW_ANIMATION_TIME = 200;
var SHOW_WINDOW_ANIMATION_TIME = 150;
var DIALOG_SHOW_WINDOW_ANIMATION_TIME = 100;
var DESTROY_WINDOW_ANIMATION_TIME = 150;
var DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 100;
var WINDOW_ANIMATION_TIME = 250;
var DIM_BRIGHTNESS = -0.3;
var DIM_TIME = 0.500;
var UNDIM_TIME = 0.250;
var DIM_TIME = 500;
var UNDIM_TIME = 250;
var MOTION_THRESHOLD = 100;
var ONE_SECOND = 1000; // in ms
@@ -71,13 +70,13 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
action: this._onSuccess.bind(this),
default: true });
this._timeoutId = Mainloop.timeout_add(ONE_SECOND, this._tick.bind(this));
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ONE_SECOND, this._tick.bind(this));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._tick');
}
close(timestamp) {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
@@ -117,16 +116,19 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
var WindowDimmer = class {
constructor(actor) {
this._brightnessEffect = new Clutter.BrightnessContrastEffect();
this._brightnessEffect = new Clutter.BrightnessContrastEffect({
name: 'dim',
enabled: false
});
actor.add_effect(this._brightnessEffect);
this.actor = actor;
this._enabled = true;
this._dimFactor = 0.0;
this._syncEnabled();
}
_syncEnabled() {
this._brightnessEffect.enabled = (this._enabled && this._dimFactor > 0);
let animating = this.actor.get_transition('@effects.dim.brightness') != null;
let dimmed = this._brightnessEffect.brightness.red != 127;
this._brightnessEffect.enabled = this._enabled && (animating || dimmed);
}
setEnabled(enabled) {
@@ -134,14 +136,17 @@ var WindowDimmer = class {
this._syncEnabled();
}
set dimFactor(factor) {
this._dimFactor = factor;
this._brightnessEffect.set_brightness(factor * DIM_BRIGHTNESS);
this._syncEnabled();
}
setDimmed(dimmed, animate) {
let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS);
let color = Clutter.Color.new(val, val, val, 255);
get dimFactor() {
return this._dimFactor;
this.actor.ease_property('@effects.dim.brightness', color, {
mode: Clutter.AnimationMode.LINEAR,
duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0),
onComplete: () => this._syncEnabled()
});
this._syncEnabled();
}
};
@@ -275,9 +280,9 @@ var WorkspaceTracker = class {
keepWorkspaceAlive(workspace, duration) {
if (workspace._keepAliveId)
Mainloop.source_remove(workspace._keepAliveId);
GLib.source_remove(workspace._keepAliveId);
workspace._keepAliveId = Mainloop.timeout_add(duration, () => {
workspace._keepAliveId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, duration, () => {
workspace._keepAliveId = 0;
this._queueCheckWorkspaces();
return GLib.SOURCE_REMOVE;
@@ -288,7 +293,7 @@ var WorkspaceTracker = class {
_windowRemoved(workspace, window) {
workspace._lastRemovedWindow = window;
this._queueCheckWorkspaces();
let id = Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, () => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, LAST_WINDOW_GRACE_TIME, () => {
if (workspace._lastRemovedWindow == window) {
workspace._lastRemovedWindow = null;
this._queueCheckWorkspaces();
@@ -413,15 +418,15 @@ var TilePreview = class {
this._showing = true;
this.actor.show();
Tweener.addTween(this.actor,
{ x: tileRect.x,
y: tileRect.y,
width: tileRect.width,
height: tileRect.height,
opacity: 255,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad'
});
this.actor.ease({
x: tileRect.x,
y: tileRect.y,
width: tileRect.width,
height: tileRect.height,
opacity: 255,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
hide() {
@@ -429,12 +434,12 @@ var TilePreview = class {
return;
this._showing = false;
Tweener.addTween(this.actor,
{ opacity: 0,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._reset.bind(this)
});
this.actor.ease({
opacity: 0,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._reset()
});
}
_reset() {
@@ -927,12 +932,6 @@ var WindowManager = class {
Shell.ActionMode.OVERVIEW,
this._startSwitcher.bind(this));
this.addKeybinding('pause-resume-tweens',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE,
Shell.ActionMode.ALL,
this._toggleTweens.bind(this));
this.addKeybinding('open-application-menu',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
@@ -1042,6 +1041,15 @@ var WindowManager = class {
}
});
global.display.connect('x11-display-opened', () => {
IBusManager.getIBusManager().restartDaemon(['--xim']);
Shell.util_start_systemd_unit('gnome-session-x11-services.target', 'fail');
});
global.display.connect('x11-display-closing', () => {
Shell.util_stop_systemd_unit('gnome-session-x11-services.target', 'fail');
IBusManager.getIBusManager().restartDaemon();
});
Main.overview.connect('showing', () => {
for (let i = 0; i < this._dimmedWindows.length; i++)
this._undimWindow(this._dimmedWindows[i]);
@@ -1136,15 +1144,13 @@ var WindowManager = class {
return;
let switchData = this._switchData;
this._switchData = null;
Tweener.addTween(switchData.container,
{ x: 0,
y: 0,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._finishWorkspaceSwitch,
onCompleteScope: this,
onCompleteParams: [switchData],
});
switchData.container.ease({
x: 0,
y: 0,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._finishWorkspaceSwitch(switchData)
});
}
_actionSwitchWorkspace(action, direction) {
@@ -1282,17 +1288,17 @@ var WindowManager = class {
this._minimizing.push(actor);
if (actor.meta_window.is_monitor_sized()) {
Tweener.addTween(actor,
{ opacity: 0,
time: MINIMIZE_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._minimizeWindowOverwritten,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
opacity: 0,
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: isFinished => {
if (isFinished)
this._minimizeWindowDone(shellwm, actor);
else
this._minimizeWindowOverwritten(shellwm, actor);
}
});
} else {
let xDest, yDest, xScale, yScale;
let [success, geom] = actor.meta_window.get_icon_geometry();
@@ -1315,26 +1321,26 @@ var WindowManager = class {
yScale = 0;
}
Tweener.addTween(actor,
{ scale_x: xScale,
scale_y: yScale,
x: xDest,
y: yDest,
time: MINIMIZE_WINDOW_ANIMATION_TIME,
transition: 'easeInExpo',
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._minimizeWindowOverwritten,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
scale_x: xScale,
scale_y: yScale,
x: xDest,
y: yDest,
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_EXPO,
onStopped: isFinished => {
if (isFinished)
this._minimizeWindowDone(shellwm, actor);
else
this._minimizeWindowOverwritten(shellwm, actor);
}
});
}
}
_minimizeWindowDone(shellwm, actor) {
if (this._removeEffect(this._minimizing, actor)) {
Tweener.removeTweens(actor);
actor.remove_all_transitions();
actor.set_scale(1.0, 1.0);
actor.set_opacity(255);
actor.set_pivot_point(0, 0);
@@ -1363,17 +1369,17 @@ var WindowManager = class {
if (actor.meta_window.is_monitor_sized()) {
actor.opacity = 0;
actor.set_scale(1.0, 1.0);
Tweener.addTween(actor,
{ opacity: 255,
time: MINIMIZE_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._unminimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._unminimizeWindowOverwritten,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
opacity: 255,
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: isFinished => {
if (isFinished)
this._unminimizeWindowDone(shellwm, actor);
else
this._unminimizeWindowOverwritten(shellwm, actor);
}
});
} else {
let [success, geom] = actor.meta_window.get_icon_geometry();
if (success) {
@@ -1397,26 +1403,26 @@ var WindowManager = class {
let [xDest, yDest] = [rect.x, rect.y];
actor.show();
Tweener.addTween(actor,
{ scale_x: 1.0,
scale_y: 1.0,
x: xDest,
y: yDest,
time: MINIMIZE_WINDOW_ANIMATION_TIME,
transition: 'easeInExpo',
onComplete: this._unminimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._unminimizeWindowOverwritten,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
scale_x: 1,
scale_y: 1,
x: xDest,
y: yDest,
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_EXPO,
onStopped: isFinished => {
if (isFinished)
this._unminimizeWindowDone(shellwm, actor);
else
this._unminimizeWindowOverwritten(shellwm, actor);
}
});
}
}
_unminimizeWindowDone(shellwm, actor) {
if (this._removeEffect(this._unminimizing, actor)) {
Tweener.removeTweens(actor);
actor.remove_all_transitions();
actor.set_scale(1.0, 1.0);
actor.set_opacity(255);
actor.set_pivot_point(0, 0);
@@ -1482,15 +1488,15 @@ var WindowManager = class {
this._resizing.push(actor);
// Now scale and fade out the clone
Tweener.addTween(actorClone,
{ x: targetRect.x,
y: targetRect.y,
scale_x: scaleX,
scale_y: scaleY,
opacity: 0,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad'
});
actorClone.ease({
x: targetRect.x,
y: targetRect.y,
scale_x: scaleX,
scale_y: scaleY,
opacity: 0,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
actor.translation_x = -targetRect.x + sourceRect.x;
actor.translation_y = -targetRect.y + sourceRect.y;
@@ -1500,20 +1506,20 @@ var WindowManager = class {
actor.scale_y = 1 / scaleY;
// Scale it to its actual new size
Tweener.addTween(actor,
{ scale_x: 1.0,
scale_y: 1.0,
translation_x: 0,
translation_y: 0,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._sizeChangeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._sizeChangeWindowOverwritten,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
scale_x: 1,
scale_y: 1,
translation_x: 0,
translation_y: 0,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: isFinished => {
if (isFinished)
this._sizeChangeWindowDone(shellwm, actor);
else
this._sizeChangeWindowOverwritten(shellwm, actor);
}
});
// Now unfreeze actor updates, to get it to the new size.
// It's important that we don't wait until the animation is completed to
@@ -1533,7 +1539,7 @@ var WindowManager = class {
_sizeChangeWindowDone(shellwm, actor) {
if (this._removeEffect(this._resizing, actor)) {
Tweener.removeTweens(actor);
actor.remove_all_transitions();
actor.scale_x = 1.0;
actor.scale_y = 1.0;
actor.translation_x = 0;
@@ -1583,14 +1589,7 @@ var WindowManager = class {
let dimmer = getWindowDimmer(actor);
if (!dimmer)
return;
if (this._shouldAnimate())
Tweener.addTween(dimmer,
{ dimFactor: 1.0,
time: DIM_TIME,
transition: 'linear'
});
else
dimmer.dimFactor = 1.0;
dimmer.setDimmed(true, this._shouldAnimate());
}
_undimWindow(window) {
@@ -1600,13 +1599,7 @@ var WindowManager = class {
let dimmer = getWindowDimmer(actor);
if (!dimmer)
return;
if (this._shouldAnimate())
Tweener.addTween(dimmer,
{ dimFactor: 0.0,
time: UNDIM_TIME,
transition: 'linear' });
else
dimmer.dimFactor = 0.0;
dimmer.setDimmed(false, this._shouldAnimate());
}
_mapWindow(shellwm, actor) {
@@ -1651,19 +1644,19 @@ var WindowManager = class {
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ opacity: 255,
scale_x: 1,
scale_y: 1,
time: SHOW_WINDOW_ANIMATION_TIME,
transition: 'easeOutExpo',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
opacity: 255,
scale_x: 1,
scale_y: 1,
duration: SHOW_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_EXPO,
onStopped: isFinished => {
if (isFinished)
this._mapWindowDone(shellwm, actor);
else
this._mapWindowOverwrite(shellwm, actor);
}
});
break;
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
@@ -1673,19 +1666,19 @@ var WindowManager = class {
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ opacity: 255,
scale_x: 1,
scale_y: 1,
time: DIALOG_SHOW_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
opacity: 255,
scale_x: 1,
scale_y: 1,
duration: DIALOG_SHOW_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: isFinished => {
if (isFinished)
this._mapWindowDone(shellwm, actor);
else
this._mapWindowOverwrite(shellwm, actor);
}
});
break;
default:
shellwm.completed_map(actor);
@@ -1695,7 +1688,7 @@ var WindowManager = class {
_mapWindowDone(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
Tweener.removeTweens(actor);
actor.remove_all_transitions();
actor.opacity = 255;
actor.set_pivot_point(0, 0);
actor.scale_y = 1;
@@ -1739,19 +1732,14 @@ var WindowManager = class {
actor.set_pivot_point(0.5, 0.5);
this._destroying.push(actor);
Tweener.addTween(actor,
{ opacity: 0,
scale_x: 0.8,
scale_y: 0.8,
time: DESTROY_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowDone,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
opacity: 0,
scale_x: 0.8,
scale_y: 0.8,
duration: DESTROY_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: () => this._destroyWindowDone(shellwm, actor)
});
break;
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
@@ -1761,22 +1749,17 @@ var WindowManager = class {
if (window.is_attached_dialog()) {
let parent = window.get_transient_for();
actor._parentDestroyId = parent.connect('unmanaged', () => {
Tweener.removeTweens(actor);
actor.remove_all_transitions();
this._destroyWindowDone(shellwm, actor);
});
}
Tweener.addTween(actor,
{ scale_y: 0,
time: DIALOG_DESTROY_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowDone,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
actor.ease({
scale_y: 0,
duration: DIALOG_DESTROY_WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: () => this._destroyWindowDone(shellwm, actor)
});
break;
default:
shellwm.completed_destroy(actor);
@@ -1981,7 +1964,6 @@ var WindowManager = class {
global.workspace_manager.get_active_workspace())
w.window.hide();
}
Tweener.removeTweens(switchData.container);
switchData.container.destroy();
switchData.movingWindowBin.destroy();
@@ -2014,15 +1996,13 @@ var WindowManager = class {
xDest = -xDest;
yDest = -yDest;
Tweener.addTween(this._switchData.container,
{ x: xDest,
y: yDest,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._switchWorkspaceDone,
onCompleteScope: this,
onCompleteParams: [shellwm]
});
this._switchData.container.ease({
x: xDest,
y: yDest,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._switchWorkspaceDone(shellwm)
});
}
_switchWorkspaceDone(shellwm) {
@@ -2112,15 +2092,6 @@ var WindowManager = class {
Main.panel.toggleCalendar();
}
_toggleTweens() {
this._tweensPaused = !this._tweensPaused;
const OrigTweener = imports.tweener.tweener;
if (this._tweensPaused)
OrigTweener.pauseAllTweens();
else
OrigTweener.resumeAllTweens();
}
_showWorkspaceSwitcher(display, window, binding) {
let workspaceManager = display.get_workspace_manager();

View File

@@ -224,7 +224,7 @@ var WindowMenuManager = class {
this._sourceActor.set_position(rect.x, rect.y);
this._sourceActor.show();
menu.open(BoxPointer.PopupAnimation.NONE);
menu.open(BoxPointer.PopupAnimation.FADE);
menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
menu.connect('open-state-changed', (menu_, isOpen) => {
if (isOpen)

View File

@@ -2,20 +2,18 @@
/* exported Workspace */
const { Atk, Clutter, GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const Tweener = imports.ui.tweener;
var WINDOW_DND_SIZE = 256;
var WINDOW_CLONE_MAXIMUM_SCALE = 1.0;
var WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
var WINDOW_OVERLAY_FADE_TIME = 0.1;
var WINDOW_OVERLAY_FADE_TIME = 100;
var WINDOW_REPOSITIONING_DELAY = 750;
@@ -58,17 +56,16 @@ class WindowCloneLayout extends Clutter.LayoutManager {
// has an extra set of "padding" around it that we need to trim
// down.
// The outer rect (from which we compute the bounding box)
// paradoxically is the smaller rectangle, containing the positions
// of the visible frame. The input rect contains everything,
// including the invisible border padding.
let inputRect = window.get_buffer_rect();
// The bounding box is based on the (visible) frame rect, while
// the buffer rect contains everything, including the invisible
// border padding.
let bufferRect = window.get_buffer_rect();
let box = new Clutter.ActorBox();
box.set_origin(inputRect.x - this._boundingBox.x,
inputRect.y - this._boundingBox.y);
box.set_size(inputRect.width, inputRect.height);
box.set_origin(bufferRect.x - this._boundingBox.x,
bufferRect.y - this._boundingBox.y);
box.set_size(bufferRect.width, bufferRect.height);
return box;
}
@@ -84,8 +81,8 @@ class WindowCloneLayout extends Clutter.LayoutManager {
vfunc_allocate(container, box, flags) {
container.get_children().forEach(child => {
let realWindow;
if (child == container._delegate._windowClone)
realWindow = container._delegate.realWindow;
if (child == container._windowClone)
realWindow = container.realWindow;
else
realWindow = child.source;
@@ -105,7 +102,7 @@ var WindowClone = GObject.registerClass({
'show-chrome': {},
'size-changed': {}
},
}, class WindowClone extends St.Widget {
}, class WorkspaceWindowClone extends St.Widget {
_init(realWindow, workspace) {
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
@@ -355,6 +352,11 @@ var WindowClone = GObject.registerClass({
this.metaWindow._delegate = null;
this._delegate = null;
if (this._longPressLater) {
Meta.later_remove(this._longPressLater);
delete this._longPressLater;
}
if (this.inDrag) {
this.emit('drag-end');
this.inDrag = false;
@@ -389,9 +391,13 @@ var WindowClone = GObject.registerClass({
let event = Clutter.get_current_event();
this._dragTouchSequence = event.get_event_sequence();
if (this._longPressLater)
return true;
// A click cancels a long-press before any click handler is
// run - make sure to not start a drag in that case
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._longPressLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
delete this._longPressLater;
if (this._selected)
return;
let [x, y] = action.get_coords();
@@ -541,9 +547,9 @@ var WindowOverlay = class {
let title = this.title;
let border = this.border;
Tweener.removeTweens(button);
Tweener.removeTweens(border);
Tweener.removeTweens(title);
button.remove_all_transitions();
border.remove_all_transitions();
title.remove_all_transitions();
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
@@ -610,16 +616,16 @@ var WindowOverlay = class {
}
_animateOverlayActor(actor, x, y, width, height) {
let params = { x: x,
y: y,
width: width,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' };
let params = {
x, y, width,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
if (height !== undefined)
params.height = height;
Tweener.addTween(actor, params);
actor.ease(params);
}
_windowCanClose() {
@@ -629,7 +635,7 @@ var WindowOverlay = class {
_onDestroy() {
if (this._idleHideOverlayId > 0) {
Mainloop.source_remove(this._idleHideOverlayId);
GLib.source_remove(this._idleHideOverlayId);
this._idleHideOverlayId = 0;
}
this._windowClone.metaWindow.disconnect(this._updateCaptionId);
@@ -648,20 +654,22 @@ var WindowOverlay = class {
toAnimate.forEach(a => {
a.show();
a.opacity = 0;
Tweener.addTween(a,
{ opacity: 255,
time: WINDOW_OVERLAY_FADE_TIME,
transition: 'easeOutQuad' });
a.ease({
opacity: 255,
duration: WINDOW_OVERLAY_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
});
}
_animateInvisible() {
[this.closeButton, this.border, this.title].forEach(a => {
a.opacity = 255;
Tweener.addTween(a,
{ opacity: 0,
time: WINDOW_OVERLAY_FADE_TIME,
transition: 'easeInQuad' });
a.ease({
opacity: 0,
duration: WINDOW_OVERLAY_FADE_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
});
}
@@ -679,7 +687,7 @@ var WindowOverlay = class {
_onHideChrome() {
if (this._idleHideOverlayId == 0) {
this._idleHideOverlayId = Mainloop.timeout_add(WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
}
}
@@ -696,7 +704,7 @@ var WindowOverlay = class {
hideOverlay() {
if (this._idleHideOverlayId > 0) {
Mainloop.source_remove(this._idleHideOverlayId);
GLib.source_remove(this._idleHideOverlayId);
this._idleHideOverlayId = 0;
}
this.closeButton.hide();
@@ -735,10 +743,6 @@ var WindowPositionFlags = {
// which rows, row sizes and other general state tracking that would make
// calculating window positions from this information fairly easy.
//
// We don't compute some global order of windows right now for optimal
// travel when animating into the overview; windows are assumed to be
// in some stable order.
//
// After a layout is computed that's considered the best layout, we
// compute the layout scale to fit it in the area, and then compute
// slots (sizes and positions) for each thumbnail.
@@ -942,7 +946,7 @@ var LayoutStrategy = class {
y += row.height * row.additionalScale + this._rowSpacing;
}
compensation = compensation / 2;
compensation /= 2;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
@@ -996,8 +1000,13 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
}
_sortRow(row) {
// Sort windows horizontally to minimize travel distance
row.windows.sort((a, b) => a.realWindow.x - b.realWindow.x);
// Sort windows horizontally to minimize travel distance.
// This affects in what order the windows end up in a row.
row.windows.sort((a, b) => {
let aCenter = a.realWindow.x + a.realWindow.width / 2;
let bCenter = b.realWindow.x + b.realWindow.width / 2;
return aCenter - bCenter;
});
}
computeLayout(windows, layout) {
@@ -1012,13 +1021,23 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
}
let idealRowWidth = totalWidth / numRows;
// Sort windows vertically to minimize travel distance.
// This affects what rows the windows get placed in.
let sortedWindows = windows.slice();
sortedWindows.sort((a, b) => {
let aCenter = a.realWindow.y + a.realWindow.height / 2;
let bCenter = b.realWindow.y + b.realWindow.height / 2;
return aCenter - bCenter;
});
let windowIdx = 0;
for (let i = 0; i < numRows; i++) {
let row = this._newRow();
rows.push(row);
for (; windowIdx < windows.length; windowIdx++) {
let window = windows[windowIdx];
for (; windowIdx < sortedWindows.length; windowIdx++) {
let window = sortedWindows[windowIdx];
let s = this._computeWindowScale(window);
let width = window.width * s;
let height = window.height * s;
@@ -1078,10 +1097,8 @@ const WorkspaceActor = GObject.registerClass(
class WorkspaceActor extends St.Widget {
vfunc_get_focus_chain() {
return this.get_children().filter(c => c.visible).sort((a, b) => {
let cloneA = (a._delegate && a._delegate instanceof WindowClone) ? a._delegate : null;
let cloneB = (b._delegate && b._delegate instanceof WindowClone) ? b._delegate : null;
if (cloneA && cloneB)
return cloneA.slotId - cloneB.slotId;
if (a instanceof WindowClone && b instanceof WindowClone)
return a.slotId - b.slotId;
return 0;
});
@@ -1251,7 +1268,7 @@ var Workspace = class {
_realRecalculateWindowPositions(flags) {
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1344,17 +1361,17 @@ var Workspace = class {
clone.y = y;
}
Tweener.addTween(clone,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeInQuad'
});
clone.ease({
opacity: 255,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
duration: Overview.ANIMATION_TIME
});
}
this._animateClone(clone, clone.overlay, x, y, scale);
} else {
// cancel any active tweens (otherwise they might override our changes)
Tweener.removeTweens(clone);
clone.remove_all_transitions();
clone.set_position(x, y);
clone.set_scale(scale, scale);
clone.set_opacity(255);
@@ -1384,18 +1401,16 @@ var Workspace = class {
}
_animateClone(clone, overlay, x, y, scale) {
Tweener.addTween(clone,
{ x: x,
y: y,
scale_x: scale,
scale_y: scale,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._showWindowOverlay(clone, overlay);
}
});
clone.ease({
x, y,
scale_x: scale,
scale_y: scale,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._showWindowOverlay(clone, overlay);
}
});
clone.overlay.relayout(true);
}
@@ -1463,7 +1478,7 @@ var Workspace = class {
// remove old handler
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1473,7 +1488,7 @@ var Workspace = class {
this._cursorY = y;
this._currentLayout = null;
this._repositionWindowsId = Mainloop.timeout_add(WINDOW_REPOSITIONING_DELAY,
this._repositionWindowsId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_REPOSITIONING_DELAY,
this._delayedWindowRepositioning.bind(this));
GLib.Source.set_name_by_id(this._repositionWindowsId, '[gnome-shell] this._delayedWindowRepositioning');
}
@@ -1487,7 +1502,7 @@ var Workspace = class {
if (!win) {
// Newly-created windows are added to a workspace before
// the compositor finds out about them...
let id = Mainloop.idle_add(() => {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
if (this.actor &&
metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace)
@@ -1629,13 +1644,11 @@ var Workspace = class {
if (this._windows.length == 0)
return;
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
Tweener.removeTweens(clone);
}
for (let i = 0; i < this._windows.length; i++)
this._windows[i].remove_all_transitions();
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1681,7 +1694,7 @@ var Workspace = class {
}
}
_fadeWindow(index, time, opacity) {
_fadeWindow(index, duration, opacity) {
let clone = this._windows[index];
let overlay = this._windowOverlays[index];
@@ -1694,11 +1707,11 @@ var Workspace = class {
clone.scale_y = 1;
clone.x = origX;
clone.y = origY;
Tweener.addTween(clone,
{ time: time,
opacity: opacity,
transition: 'easeOutQuad'
});
clone.ease({
opacity,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} else {
// The window is hidden
clone.opacity = 0;
@@ -1716,13 +1729,11 @@ var Workspace = class {
this.leavingOverview = true;
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
Tweener.removeTweens(clone);
}
for (let i = 0; i < this._windows.length; i++)
this._windows[i].remove_all_transitions();
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
this._overviewHiddenId = Main.overview.connect('hidden', this._doneLeavingOverview.bind(this));
@@ -1744,24 +1755,24 @@ var Workspace = class {
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
Tweener.addTween(clone,
{ x: origX,
y: origY,
scale_x: 1.0,
scale_y: 1.0,
time: Overview.ANIMATION_TIME,
opacity: 255,
transition: 'easeOutQuad'
});
clone.ease({
x: origX,
y: origY,
scale_x: 1,
scale_y: 1,
opacity: 255,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} else {
// The window is hidden, make it shrink and fade it out
Tweener.addTween(clone,
{ scale_x: 0,
scale_y: 0,
opacity: 0,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad'
});
clone.ease({
scale_x: 0,
scale_y: 0,
opacity: 0,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
@@ -1769,12 +1780,11 @@ var Workspace = class {
this.actor.destroy();
}
_onDestroy(actor) {
_onDestroy() {
if (this._overviewHiddenId) {
Main.overview.disconnect(this._overviewHiddenId);
this._overviewHiddenId = 0;
}
Tweener.removeTweens(actor);
if (this.metaWorkspace) {
this.metaWorkspace.disconnect(this._windowAddedId);
@@ -1784,7 +1794,7 @@ var Workspace = class {
global.display.disconnect(this._windowLeftMonitorId);
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1973,7 +1983,7 @@ var Workspace = class {
}
_onCloneSelected(clone, time) {
let wsIndex = undefined;
let wsIndex;
if (this.metaWorkspace)
wsIndex = this.metaWorkspace.index();
Main.activateWindow(clone.metaWindow, time, wsIndex);

View File

@@ -2,12 +2,10 @@
/* exported WorkspaceSwitcherPopup */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var ANIMATION_TIME = 0.1;
var ANIMATION_TIME = 100;
var DISPLAY_TIMEOUT = 600;
var WorkspaceSwitcherPopupList = GObject.registerClass(
@@ -182,10 +180,11 @@ class WorkspaceSwitcherPopup extends St.Widget {
}
_show() {
Tweener.addTween(this._container, { opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
this._container.ease({
opacity: 255,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this.show();
}
@@ -195,26 +194,27 @@ class WorkspaceSwitcherPopup extends St.Widget {
this._redisplay();
if (this._timeoutId != 0)
Mainloop.source_remove(this._timeoutId);
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, this._onTimeout.bind(this));
GLib.source_remove(this._timeoutId);
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, DISPLAY_TIMEOUT, this._onTimeout.bind(this));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
this._show();
}
_onTimeout() {
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
Tweener.addTween(this._container, { opacity: 0.0,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => this.destroy()
});
this._container.ease({
opacity: 0.0,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.destroy()
});
return GLib.SOURCE_REMOVE;
}
_onDestroy() {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
let workspaceManager = global.workspace_manager;

View File

@@ -2,21 +2,19 @@
/* exported WorkspaceThumbnail, ThumbnailsBox */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Background = imports.ui.background;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
const WorkspacesView = imports.ui.workspacesView;
// The maximum size of a thumbnail is 1/10 the width and height of the screen
let MAX_THUMBNAIL_SCALE = 1 / 10.;
var RESCALE_ANIMATION_TIME = 0.2;
var SLIDE_ANIMATION_TIME = 0.2;
var RESCALE_ANIMATION_TIME = 200;
var SLIDE_ANIMATION_TIME = 200;
// When we create workspaces by dragging, we add a "cut" into the top and
// bottom of each workspace so that the user doesn't have to hit the
@@ -244,21 +242,34 @@ var ThumbnailState = {
/**
* @metaWorkspace: a #Meta.Workspace
*/
var WorkspaceThumbnail = class {
constructor(metaWorkspace) {
var WorkspaceThumbnail = GObject.registerClass({
Properties: {
'collapse-fraction': GObject.ParamSpec.double(
'collapse-fraction', 'collapse-fraction', 'collapse-fraction',
GObject.ParamFlags.READWRITE,
0, 1, 0),
'slide-position': GObject.ParamSpec.double(
'slide-position', 'slide-position', 'slide-position',
GObject.ParamFlags.READWRITE,
0, 1, 0),
}
}, class WorkspaceThumbnail extends St.Widget {
_init(metaWorkspace) {
super._init({
clip_to_allocation: true,
style_class: 'workspace-thumbnail'
});
this._delegate = this;
this.metaWorkspace = metaWorkspace;
this.monitorIndex = Main.layoutManager.primaryIndex;
this._removed = false;
this.actor = new St.Widget({ clip_to_allocation: true,
style_class: 'workspace-thumbnail' });
this.actor._delegate = this;
this._contents = new Clutter.Actor();
this.actor.add_child(this._contents);
this.add_child(this._contents);
this.actor.connect('destroy', this._onDestroy.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this._createBackground();
@@ -308,7 +319,7 @@ var WorkspaceThumbnail = class {
}
setPorthole(x, y, width, height) {
this.actor.set_size(width, height);
this.set_size(width, height);
this._contents.set_position(-x, -y);
}
@@ -334,21 +345,31 @@ var WorkspaceThumbnail = class {
}
}
set slidePosition(slidePosition) {
// eslint-disable-next-line camelcase
set slide_position(slidePosition) {
if (this._slidePosition == slidePosition)
return;
this._slidePosition = slidePosition;
this.actor.queue_relayout();
this.notify('slide-position');
this.queue_relayout();
}
get slidePosition() {
// eslint-disable-next-line camelcase
get slide_position() {
return this._slidePosition;
}
set collapseFraction(collapseFraction) {
// eslint-disable-next-line camelcase
set collapse_fraction(collapseFraction) {
if (this._collapseFraction == collapseFraction)
return;
this._collapseFraction = collapseFraction;
this.actor.queue_relayout();
this.notify('collapse-fraction');
this.queue_relayout();
}
get collapseFraction() {
// eslint-disable-next-line camelcase
get collapse_fraction() {
return this._collapseFraction;
}
@@ -367,7 +388,7 @@ var WorkspaceThumbnail = class {
if (!win) {
// Newly-created windows are added to a workspace before
// the compositor finds out about them...
let id = Mainloop.idle_add(() => {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
if (!this._removed &&
metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace)
@@ -446,11 +467,6 @@ var WorkspaceThumbnail = class {
this._doAddWindow(metaWin);
}
destroy() {
if (this.actor)
this.actor.destroy();
}
workspaceRemoved() {
if (this._removed)
return;
@@ -475,7 +491,6 @@ var WorkspaceThumbnail = class {
}
this._windows = [];
this.actor = null;
}
// Tests if @actor belongs to this workspace and monitor
@@ -590,12 +605,21 @@ var WorkspaceThumbnail = class {
return false;
}
};
Signals.addSignalMethods(WorkspaceThumbnail.prototype);
});
var ThumbnailsBox = GObject.registerClass(
class ThumbnailsBox extends St.Widget {
var ThumbnailsBox = GObject.registerClass({
Properties: {
'indicator-y': GObject.ParamSpec.double(
'indicator-y', 'indicator-y', 'indicator-y',
GObject.ParamFlags.READWRITE,
0, Infinity, 0),
'scale': GObject.ParamSpec.double(
'scale', 'scale', 'scale',
GObject.ParamFlags.READWRITE,
0, Infinity, 0)
}
}, class ThumbnailsBox extends St.Widget {
_init() {
super._init({ reactive: true,
style_class: 'workspace-thumbnails',
@@ -686,14 +710,12 @@ class ThumbnailsBox extends St.Widget {
_activateThumbnailAtPoint(stageX, stageY, time) {
let [r_, x_, y] = this.transform_stage_point(stageX, stageY);
for (let i = 0; i < this._thumbnails.length; i++) {
let thumbnail = this._thumbnails[i];
let [, h] = thumbnail.actor.get_transformed_size();
if (y >= thumbnail.actor.y && y <= thumbnail.actor.y + h) {
thumbnail.activate(time);
break;
}
}
let thumbnail = this._thumbnails.find(t => {
let [, h] = t.get_transformed_size();
return y >= t.y && y <= t.y + h;
});
if (thumbnail)
thumbnail.activate(time);
}
_onButtonRelease(actor, event) {
@@ -769,14 +791,14 @@ class ThumbnailsBox extends St.Widget {
if (this._dropPlaceholderPos == 0)
targetBase = this._dropPlaceholder.y;
else
targetBase = this._thumbnails[0].actor.y;
targetBase = this._thumbnails[0].y;
let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE;
let length = this._thumbnails.length;
for (let i = 0; i < length; i ++) {
// Allow the reorder target to have a 10px "cut" into
// each side of the thumbnail, to make dragging onto the
// placeholder easier
let [, h] = this._thumbnails[i].actor.get_transformed_size();
let [, h] = this._thumbnails[i].get_transformed_size();
let targetBottom = targetBase + WORKSPACE_CUT_SIZE;
let nextTargetBase = targetBase + h + spacing;
let nextTargetTop = nextTargetBase - spacing - ((i == length - 1) ? 0 : WORKSPACE_CUT_SIZE);
@@ -847,7 +869,7 @@ class ThumbnailsBox extends St.Widget {
// an old one which just became empty)
let thumbnail = this._thumbnails[newWorkspaceIndex];
this._setThumbnailState(thumbnail, ThumbnailState.NEW);
thumbnail.slidePosition = 1;
thumbnail.slide_position = 1;
this._queueUpdateStates();
@@ -955,12 +977,12 @@ class ThumbnailsBox extends St.Widget {
thumbnail.setPorthole(this._porthole.x, this._porthole.y,
this._porthole.width, this._porthole.height);
this._thumbnails.push(thumbnail);
this.add_actor(thumbnail.actor);
this.add_actor(thumbnail);
if (start > 0 && this._spliceIndex == -1) {
// not the initial fill, and not splicing via DND
thumbnail.state = ThumbnailState.NEW;
thumbnail.slidePosition = 1; // start slid out
thumbnail.slide_position = 1; // start slid out
this._haveNewThumbnails = true;
} else {
thumbnail.state = ThumbnailState.NORMAL;
@@ -1003,7 +1025,11 @@ class ThumbnailsBox extends St.Widget {
}
set scale(scale) {
if (this._scale == scale)
return;
this._scale = scale;
this.notify('scale');
this.queue_relayout();
}
@@ -1011,12 +1037,18 @@ class ThumbnailsBox extends St.Widget {
return this._scale;
}
set indicatorY(indicatorY) {
// eslint-disable-next-line camelcase
set indicator_y(indicatorY) {
if (this._indicatorY == indicatorY)
return;
this._indicatorY = indicatorY;
this.notify('indicator-y');
this.queue_relayout();
}
get indicatorY() {
// eslint-disable-next-line camelcase
get indicator_y() {
return this._indicatorY;
}
@@ -1036,15 +1068,6 @@ class ThumbnailsBox extends St.Widget {
}
}
_tweenScale() {
Tweener.addTween(this,
{ scale: this._targetScale,
time: RESCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._queueUpdateStates,
onCompleteScope: this });
}
_updateStates() {
this._stateUpdateQueued = false;
@@ -1056,15 +1079,14 @@ class ThumbnailsBox extends St.Widget {
this._iterateStateThumbnails(ThumbnailState.REMOVING, thumbnail => {
this._setThumbnailState(thumbnail, ThumbnailState.ANIMATING_OUT);
Tweener.addTween(thumbnail,
{ slidePosition: 1,
time: SLIDE_ANIMATION_TIME,
transition: 'linear',
onComplete: () => {
this._setThumbnailState(thumbnail, ThumbnailState.ANIMATED_OUT);
this._queueUpdateStates();
}
});
thumbnail.ease_property('slide-position', 1, {
duration: SLIDE_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this._setThumbnailState(thumbnail, ThumbnailState.ANIMATED_OUT);
this._queueUpdateStates();
}
});
});
// As long as things are sliding out, don't proceed
@@ -1074,25 +1096,28 @@ class ThumbnailsBox extends St.Widget {
// Once that's complete, we can start scaling to the new size and collapse any removed thumbnails
this._iterateStateThumbnails(ThumbnailState.ANIMATED_OUT, thumbnail => {
this._setThumbnailState(thumbnail, ThumbnailState.COLLAPSING);
Tweener.addTween(thumbnail,
{ collapseFraction: 1,
time: RESCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._stateCounts[thumbnail.state]--;
thumbnail.state = ThumbnailState.DESTROYED;
thumbnail.ease_property('collapse-fraction', 1, {
duration: RESCALE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._stateCounts[thumbnail.state]--;
thumbnail.state = ThumbnailState.DESTROYED;
let index = this._thumbnails.indexOf(thumbnail);
this._thumbnails.splice(index, 1);
thumbnail.destroy();
let index = this._thumbnails.indexOf(thumbnail);
this._thumbnails.splice(index, 1);
thumbnail.destroy();
this._queueUpdateStates();
}
});
this._queueUpdateStates();
}
});
});
if (this._pendingScaleUpdate) {
this._tweenScale();
this.ease_property('scale', this._targetScale, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: RESCALE_ANIMATION_TIME,
onComplete: () => this._queueUpdateStates()
});
this._pendingScaleUpdate = false;
}
@@ -1103,14 +1128,13 @@ class ThumbnailsBox extends St.Widget {
// And then slide in any new thumbnails
this._iterateStateThumbnails(ThumbnailState.NEW, thumbnail => {
this._setThumbnailState(thumbnail, ThumbnailState.ANIMATING_IN);
Tweener.addTween(thumbnail,
{ slidePosition: 0,
time: SLIDE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._setThumbnailState(thumbnail, ThumbnailState.NORMAL);
}
});
thumbnail.ease_property('slide-position', 0, {
duration: SLIDE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._setThumbnailState(thumbnail, ThumbnailState.NORMAL);
}
});
});
}
@@ -1245,14 +1269,14 @@ class ThumbnailsBox extends St.Widget {
let thumbnail = this._thumbnails[i];
if (i > 0)
y += spacing - Math.round(thumbnail.collapseFraction * spacing);
y += spacing - Math.round(thumbnail.collapse_fraction * spacing);
let x1, x2;
if (rtl) {
x1 = box.x1 + slideOffset * thumbnail.slidePosition;
x1 = box.x1 + slideOffset * thumbnail.slide_position;
x2 = x1 + thumbnailWidth;
} else {
x1 = box.x2 - thumbnailWidth + slideOffset * thumbnail.slidePosition;
x1 = box.x2 - thumbnailWidth + slideOffset * thumbnail.slide_position;
x2 = x1 + thumbnailWidth;
}
@@ -1289,13 +1313,13 @@ class ThumbnailsBox extends St.Widget {
childBox.y1 = y1;
childBox.y2 = y1 + portholeHeight;
thumbnail.actor.set_scale(roundedHScale, roundedVScale);
thumbnail.actor.allocate(childBox, flags);
thumbnail.set_scale(roundedHScale, roundedVScale);
thumbnail.allocate(childBox, flags);
// We round the collapsing portion so that we don't get thumbnails resizing
// during an animation due to differences in rounded, but leave the uncollapsed
// portion unrounded so that non-animating we end up with the right total
y += thumbnailHeight - Math.round(thumbnailHeight * thumbnail.collapseFraction);
y += thumbnailHeight - Math.round(thumbnailHeight * thumbnail.collapse_fraction);
}
if (rtl) {
@@ -1313,28 +1337,21 @@ class ThumbnailsBox extends St.Widget {
}
_activeWorkspaceChanged(_wm, _from, _to, _direction) {
let thumbnail;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
for (let i = 0; i < this._thumbnails.length; i++) {
if (this._thumbnails[i].metaWorkspace == activeWorkspace) {
thumbnail = this._thumbnails[i];
break;
}
}
let thumbnail = this._thumbnails.find(t => t.metaWorkspace == activeWorkspace);
this._animatingIndicator = true;
let indicatorThemeNode = this._indicator.get_theme_node();
let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP);
this.indicatorY = this._indicator.allocation.y1 + indicatorTopFullBorder;
Tweener.addTween(this,
{ indicatorY: thumbnail.actor.allocation.y1,
time: WorkspacesView.WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._animatingIndicator = false;
this._queueUpdateStates();
}
});
this.indicator_y = this._indicator.allocation.y1 + indicatorTopFullBorder;
this.ease_property('indicator-y', thumbnail.allocation.y1, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: WorkspacesView.WORKSPACE_SWITCH_TIME,
onComplete: () => {
this._animatingIndicator = false;
this._queueUpdateStates();
}
});
}
});

View File

@@ -5,11 +5,10 @@ const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const WindowManager = imports.ui.windowManager;
const Workspace = imports.ui.workspace;
var WORKSPACE_SWITCH_TIME = 0.25;
var WORKSPACE_SWITCH_TIME = 250;
var AnimationType = {
ZOOM: 0,
@@ -188,7 +187,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
Tweener.removeTweens(workspace.actor);
workspace.actor.remove_all_transitions();
let params = {};
if (workspaceManager.layout_rows == -1)
@@ -199,21 +198,21 @@ var WorkspacesView = class extends WorkspacesViewBase {
params.x = (w - active) * this._fullGeometry.width;
if (showAnimation) {
let tweenParams = Object.assign(params, {
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad'
let easeParams = Object.assign(params, {
duration: WORKSPACE_SWITCH_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
// 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();
tweenParams.onComplete = () => {
easeParams.onComplete = () => {
this._animating = false;
this._updateVisibility();
};
}
Tweener.addTween(workspace.actor, tweenParams);
workspace.actor.ease(easeParams);
} else {
workspace.actor.set(params);
if (w == 0)
@@ -245,13 +244,10 @@ var WorkspacesView = class extends WorkspacesViewBase {
this._animatingScroll = true;
Tweener.addTween(this.scrollAdjustment, {
value: index,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._animatingScroll = false;
}
this.scrollAdjustment.ease(index, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: WORKSPACE_SWITCH_TIME,
onComplete: () => this._animatingScroll = false
});
}
@@ -528,6 +524,22 @@ var WorkspacesDisplay = class {
this._keyPressEventId = 0;
this._fullGeometry = null;
this.actor.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
if (this._notifyOpacityId) {
let parent = this.actor.get_parent();
if (parent)
parent.disconnect(this._notifyOpacityId);
this._notifyOpacityId = 0;
}
if (this._parentSetLater) {
Meta.later_remove(this._parentSetLater);
this._parentSetLater = 0;
}
}
_onPan(action) {
@@ -721,7 +733,11 @@ var WorkspacesDisplay = class {
oldParent.disconnect(this._notifyOpacityId);
this._notifyOpacityId = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
if (this._parentSetLater)
return;
this._parentSetLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._parentSetLater = 0;
let newParent = this.actor.get_parent();
if (!newParent)
return;

View File

@@ -1,5 +1,5 @@
project('gnome-shell', 'c',
version: '3.33.4',
version: '3.34.0',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)
@@ -26,7 +26,7 @@ gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1'
gjs_req = '>= 1.57.3'
gtk_req = '>= 3.15.0'
mutter_req = '>= 3.33.4'
mutter_req = '>= 3.34.0'
polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1'
startup_req = '>= 0.11'
@@ -132,9 +132,20 @@ else
have_systemd = false
endif
if get_option('extensions_tool')
autoar_dep = dependency('gnome-autoar-0')
json_dep = dependency('json-glib-1.0')
endif
bash_completion = dependency('bash-completion', required: false)
if get_option('man')
xsltproc = find_program('xsltproc')
if get_option('extensions_tool')
a2x = find_program('a2x')
endif
subdir('man')
endif
@@ -243,6 +254,8 @@ libgvc = subproject('gvc',
)
libgvc_gir = libgvc.get_variable('libgvc_gir')
po_dir = join_paths(meson.current_source_dir(), 'po')
subdir('js')
subdir('src')
subdir('po')

View File

@@ -1,3 +1,9 @@
option('extensions_tool',
type: 'boolean',
value: true,
description: 'Build gnome-extensions CLI tool'
)
option('gtk_doc',
type: 'boolean',
value: false,

View File

@@ -72,6 +72,17 @@ js/ui/windowAttentionHandler.js
js/ui/windowManager.js
js/ui/windowMenu.js
src/calendar-server/evolution-calendar.desktop.in
src/extensions-tool/command-create.c
src/extensions-tool/command-disable.c
src/extensions-tool/command-enable.c
src/extensions-tool/command-info.c
src/extensions-tool/command-install.c
src/extensions-tool/command-list.c
src/extensions-tool/command-pack.c
src/extensions-tool/command-prefs.c
src/extensions-tool/command-reset.c
src/extensions-tool/command-uninstall.c
src/extensions-tool/main.c
src/main.c
src/shell-app.c
src/shell-app-system.c

1404
po/ca.po

File diff suppressed because it is too large Load Diff

1325
po/cs.po

File diff suppressed because it is too large Load Diff

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